From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mogw1027.ocn.ad.jp (mogw1027.ocn.ad.jp [153.149.231.33]) by dpdk.org (Postfix) with ESMTP id 475AD4CBD for ; Tue, 27 Feb 2018 13:34:52 +0100 (CET) Received: from mf-smf-ucb020c2 (mf-smf-ucb020c2.ocn.ad.jp [153.153.66.134]) by mogw1027.ocn.ad.jp (Postfix) with ESMTP id AF72C28024F; Tue, 27 Feb 2018 21:34:50 +0900 (JST) Received: from ntt.pod01.mv-mta-ucb019 ([153.149.142.82]) by mf-smf-ucb020c2 with ESMTP id qeT4eIbodQByzqeT4e5Ehz; Tue, 27 Feb 2018 21:34:50 +0900 Received: from smtp.ocn.ne.jp ([153.149.227.135]) by ntt.pod01.mv-mta-ucb019 with id Foaq1x0092vuoep01oaqP5; Tue, 27 Feb 2018 12:34:50 +0000 Received: from localhost.localdomain (p5157022-ipngn2402marunouchi.tokyo.ocn.ne.jp [180.35.69.22]) by smtp.ocn.ne.jp (Postfix) with ESMTPA; Tue, 27 Feb 2018 21:34:50 +0900 (JST) From: ogawa.yasufumi@lab.ntt.co.jp To: spp@dpdk.org, ferruh.yigit@intel.com, x-fn-spp@sl.ntt-tx.co.jp Cc: Hiroyuki Nakamura , Daiki Yamashita , Naoki Takada Date: Tue, 27 Feb 2018 21:34:27 +0900 Message-Id: <1519734869-21582-8-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1519734869-21582-1-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> References: <201802080551.w185pkLL010335@imss03.silk.ntt-tx.co.jp> <1519734869-21582-1-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> Subject: [spp] [PATCH v2 7/9] spp_vf: add VID classification to the classifier X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Feb 2018 12:34:53 -0000 From: Hiroyuki Nakamura Classifier has a table for virtual MAC address for resolving the destination MAC address and port incoming packets are sent to. This patch for adding another type of table to support vlan-tag (TPID:0x8100). If TPID of an incoming packet equals to 0x8100, classifier looks up the new table. Signed-off-by: Daiki Yamashita Signed-off-by: Naoki Takada --- src/vf/classifier_mac.c | 656 +++++++++++++++++++++++++++++++++++------------- src/vf/command_dec.c | 87 +++++-- src/vf/command_dec.h | 41 ++- src/vf/command_proc.c | 41 ++- src/vf/spp_vf.c | 150 ++++++----- src/vf/spp_vf.h | 41 +-- 6 files changed, 728 insertions(+), 288 deletions(-) diff --git a/src/vf/classifier_mac.c b/src/vf/classifier_mac.c index 1719889..d07870d 100644 --- a/src/vf/classifier_mac.c +++ b/src/vf/classifier_mac.c @@ -78,6 +78,9 @@ /* interval that transmit burst packet, if buffer is not filled (nano second) */ #define DRAIN_TX_PACKET_INTERVAL 100 +/* VID of VLAN untagged */ +#define VLAN_UNTAGGED_VID 0x0fff + /* * hash table name buffer size *[reson for value] @@ -116,13 +119,10 @@ struct classified_data { struct rte_mbuf *pkts[MAX_PKT_BURST]; }; -/* classifier component information */ -struct component_info { - /* component name */ - char name[SPP_NAME_STR_LEN]; - - /* hash table keeps classifier_table */ - struct rte_hash *classifier_table; +/* mac address classification */ +struct mac_classification { + /* hash table keeps classification */ + struct rte_hash *classification_tab; /* number of valid classification */ int num_active_classified; @@ -132,6 +132,15 @@ struct component_info { /* index of default classification */ int default_classified; +}; + +/* classifier component information */ +struct component_info { + /* component name */ + char name[SPP_NAME_STR_LEN]; + + /* mac address classification per vlan-id */ + struct mac_classification *mac_classifications[SPP_NUM_VLAN_VID]; /* number of transmission ports */ int n_classified_data_tx; @@ -153,6 +162,9 @@ struct management_info { /* Update index number for classifier information */ volatile int upd_index; + + /* used flag */ + volatile int is_used; }; /* classifier information per lcore */ @@ -166,11 +178,200 @@ static struct management_info g_mng_infos[RTE_MAX_LCORE]; */ static rte_atomic16_t g_hash_table_count = RTE_ATOMIC16_INIT(0xff); +/* get vid from packet */ +static inline uint16_t +get_vid(const struct rte_mbuf *pkt) +{ + struct ether_hdr *eth; + struct vlan_hdr *vh; + + eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + if (eth->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { + /* vlan tagged */ + vh = (struct vlan_hdr *)(eth + 1); + return rte_be_to_cpu_16(vh->vlan_tci) & 0x0fff; + } + + /* vlan untagged */ + return VLAN_UNTAGGED_VID; +} + +#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG + +#define LOG_DBG(name, fmt, ...) \ + RTE_LOG_DP(DEBUG, SPP_CLASSIFIER_MAC, \ + "[%s]Log(%s:%d):"fmt, \ + name, __func__, __LINE__, __VA_ARGS__) + +static void +log_packet(const char *name, struct rte_mbuf *pkt, + const char *func_name, int line_num) +{ + struct ether_hdr *eth; + uint16_t vid; + char mac_addr_str[2][ETHER_ADDR_STR_BUF_SZ]; + + eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + vid = get_vid(pkt); + + ether_format_addr(mac_addr_str[0], sizeof(mac_addr_str), + ð->d_addr); + ether_format_addr(mac_addr_str[1], sizeof(mac_addr_str), + ð->s_addr); + + RTE_LOG_DP(DEBUG, SPP_CLASSIFIER_MAC, + "[%s]Packet(%s:%d). d_addr=%s, s_addr=%s, vid=%hu, pktlen=%u\n", + name, + func_name, + line_num, + mac_addr_str[0], + mac_addr_str[1], + vid, + rte_pktmbuf_pkt_len(pkt)); +} + +#define LOG_PKT(name, pkt) \ + log_packet(name, pkt, __func__, __LINE__) + +static void +log_classification( + long clsd_idx, + struct rte_mbuf *pkt, + struct component_info *cmp_info, + struct classified_data *clsd_data, + const char *func_name, + int line_num) +{ + struct ether_hdr *eth; + uint16_t vid; + char mac_addr_str[2][ETHER_ADDR_STR_BUF_SZ]; + char iface_str[SPP_NAME_STR_LEN]; + + eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + vid = get_vid(pkt); + + ether_format_addr(mac_addr_str[0], sizeof(mac_addr_str), + ð->d_addr); + ether_format_addr(mac_addr_str[1], sizeof(mac_addr_str), + ð->s_addr); + + if (clsd_idx < 0) + snprintf(iface_str, sizeof(iface_str), "%ld", clsd_idx); + else + spp_format_port_string( + iface_str, + clsd_data[clsd_idx].iface_type, + clsd_data[clsd_idx].iface_no_global); + + RTE_LOG_DP(DEBUG, SPP_CLASSIFIER_MAC, + "[%s]Classification(%s:%d). d_addr=%s, s_addr=%s, vid=%hu, pktlen=%u, tx_iface=%s\n", + cmp_info->name, + func_name, + line_num, + mac_addr_str[0], + mac_addr_str[1], + vid, + rte_pktmbuf_pkt_len(pkt), + iface_str); +} + +#define LOG_CLS(clsd_idx, pkt, cmp_info, clsd_data) \ + log_classification(clsd_idx, pkt, cmp_info, clsd_data, \ + __func__, __LINE__) + +static void +log_entry( + long clsd_idx, + uint16_t vid, + const char *mac_addr_str, + struct component_info *cmp_info, + struct classified_data *clsd_data, + const char *func_name, + int line_num) +{ + char iface_str[SPP_NAME_STR_LEN]; + + if (clsd_idx < 0) + snprintf(iface_str, sizeof(iface_str), "%ld", clsd_idx); + else + spp_format_port_string( + iface_str, + clsd_data[clsd_idx].iface_type, + clsd_data[clsd_idx].iface_no_global); + + RTE_LOG_DP(DEBUG, SPP_CLASSIFIER_MAC, + "[%s]Entry(%s:%d). vid=%hu, mac_addr=%s, iface=%s\n", + cmp_info->name, + func_name, + line_num, + vid, + mac_addr_str, + iface_str); +} +#define LOG_ENT(clsd_idx, vid, mac_addr_str, cmp_info, clsd_data) \ + log_entry(clsd_idx, vid, mac_addr_str, cmp_info, clsd_data, \ + __func__, __LINE__) +#else +#define LOG_DBG(name, fmt, ...) +#define LOG_PKT(name, pkt) +#define LOG_CLS(pkt, clsd_idx, cmp_info, clsd_data) +#define LOG_ENT(clsd_idx, vid, mac_addr_str, cmp_info, clsd_data) +#endif + +/* check if management information is used. */ static inline int is_used_mng_info(const struct management_info *mng_info) { - return (mng_info != NULL && - mng_info->cmp_infos[0].classifier_table != NULL); + return (mng_info != NULL && mng_info->is_used); +} + +/* create mac classification instance. */ +static struct mac_classification * +create_mac_classification(void) +{ + struct mac_classification *mac_cls; + char hash_tab_name[HASH_TABLE_NAME_BUF_SZ]; + struct rte_hash **mac_cls_tab; + + mac_cls = (struct mac_classification *)rte_zmalloc( + NULL, sizeof(struct mac_classification), 0); + + if (unlikely(mac_cls == NULL)) + return NULL; + + mac_cls->num_active_classified = 0; + mac_cls->default_classified = -1; + + mac_cls_tab = &mac_cls->classification_tab; + + /* make hash table name(require uniqueness between processes) */ + sprintf(hash_tab_name, "cmtab_%07x%02hx", + getpid(), + rte_atomic16_add_return(&g_hash_table_count, 1)); + + RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Create table. name=%s, bufsz=%lu\n", + hash_tab_name, HASH_TABLE_NAME_BUF_SZ); + + /* set hash creating parameters */ + struct rte_hash_parameters hash_params = { + .name = hash_tab_name, + .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY, + .key_len = sizeof(struct ether_addr), + .hash_func = DEFAULT_HASH_FUNC, + .hash_func_init_val = 0, + .socket_id = rte_socket_id(), + }; + + /* create classifier mac table (hash table) */ + *mac_cls_tab = rte_hash_create(&hash_params); + if (unlikely(*mac_cls_tab == NULL)) { + RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create mac classification table. " + "name=%s\n", hash_tab_name); + rte_free(mac_cls); + return NULL; + } + + return mac_cls; } /* initialize classifier information. */ @@ -180,19 +381,15 @@ init_component_info(struct component_info *cmp_info, { int ret = -1; int i; - struct rte_hash **classifier_table = &cmp_info->classifier_table; + struct mac_classification *mac_cls; struct ether_addr eth_addr; char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; - struct classified_data *clsd_data_rx = - &cmp_info->classified_data_rx; - struct classified_data *clsd_data_tx = - cmp_info->classified_data_tx; + struct classified_data *clsd_data_rx = &cmp_info->classified_data_rx; + struct classified_data *clsd_data_tx = cmp_info->classified_data_tx; struct spp_port_info *tx_port = NULL; + uint16_t vid; - rte_hash_reset(*classifier_table); - cmp_info->num_active_classified = 0; - cmp_info->default_classified = -1; - cmp_info->n_classified_data_tx = component_info->num_tx_port; + /* set rx */ if (component_info->num_rx_port == 0) { clsd_data_rx->iface_type = UNDEF; clsd_data_rx->iface_no = 0; @@ -210,8 +407,11 @@ init_component_info(struct component_info *cmp_info, clsd_data_rx->num_pkt = 0; } + /* set tx */ + cmp_info->n_classified_data_tx = component_info->num_tx_port; for (i = 0; i < component_info->num_tx_port; i++) { tx_port = component_info->tx_ports[i]; + vid = tx_port->class_id.vlantag.vid; /* store ports information */ clsd_data_tx[i].iface_type = tx_port->iface_type; @@ -220,19 +420,33 @@ init_component_info(struct component_info *cmp_info, clsd_data_tx[i].port = tx_port->dpdk_port; clsd_data_tx[i].num_pkt = 0; - if (component_info->tx_ports[i]->mac_addr == 0) + if (tx_port->class_id.mac_addr == 0) continue; + /* if mac classification is NULL, make instance */ + if (unlikely(cmp_info->mac_classifications[vid] == NULL)) { + RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, + "Mac classification is not registered. create." + "vid=%hu\n", vid); + cmp_info->mac_classifications[vid] = + create_mac_classification(); + if (unlikely(cmp_info->mac_classifications[vid] == + NULL)) + return -1; + } + mac_cls = cmp_info->mac_classifications[vid]; + /* store active tx_port that associate with mac address */ - cmp_info->active_classifieds[cmp_info-> - num_active_classified++] = i; + mac_cls->active_classifieds[ + mac_cls->num_active_classified++] = i; /* store default classified */ - if (unlikely(tx_port->mac_addr == + if (unlikely(tx_port->class_id.mac_addr == SPP_DEFAULT_CLASSIFIED_DMY_ADDR)) { - cmp_info->default_classified = i; + mac_cls->default_classified = i; RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "default classified. " - "iface_type=%d, iface_no=%d, dpdk_port=%d\n", + "vid=%hu, iface_type=%d, iface_no=%d, dpdk_port=%d\n", + vid, tx_port->iface_type, tx_port->iface_no, tx_port->dpdk_port); @@ -240,24 +454,24 @@ init_component_info(struct component_info *cmp_info, } /* add entry to classifier mac table */ - rte_memcpy(ð_addr, &tx_port->mac_addr, ETHER_ADDR_LEN); + rte_memcpy(ð_addr, &tx_port->class_id.mac_addr, + ETHER_ADDR_LEN); ether_format_addr(mac_addr_str, sizeof(mac_addr_str), ð_addr); - ret = rte_hash_add_key_data(*classifier_table, + ret = rte_hash_add_key_data(mac_cls->classification_tab, (void *)ð_addr, (void *)(long)i); if (unlikely(ret < 0)) { RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot add entry to classifier mac table. " - "ret=%d, mac_addr=%s\n", - ret, mac_addr_str); - rte_hash_free(*classifier_table); - *classifier_table = NULL; + "ret=%d, vid=%hu, mac_addr=%s\n", + ret, vid, mac_addr_str); return -1; } RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Add entry to classifier mac table. " - "mac_addr=%s, iface_type=%d, iface_no=%d, dpdk_port=%d\n", + "vid=%hu, mac_addr=%s, iface_type=%d, iface_no=%d, dpdk_port=%d\n", + vid, mac_addr_str, tx_port->iface_type, tx_port->iface_no, @@ -272,10 +486,6 @@ static int init_classifier(struct management_info *mng_info) { int ret = -1; - int i; - char hash_table_name[HASH_TABLE_NAME_BUF_SZ]; - - struct rte_hash **classifier_mac_table = NULL; struct spp_component_info component_info; memset(mng_info, 0, sizeof(struct management_info)); @@ -295,39 +505,6 @@ init_classifier(struct management_info *mng_info) RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Disabled SSE4.2. use Jenkins hash.\n"); #endif - for (i = 0; i < NUM_CLASSIFIER_MAC_INFO; ++i) { - - classifier_mac_table = - &mng_info->cmp_infos[i].classifier_table; - - /* make hash table name(require uniqueness between processes) */ - sprintf(hash_table_name, "cmtab_%07x%02hx%x", - getpid(), - rte_atomic16_add_return(&g_hash_table_count, 1), - i); - - RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Create table. name=%s, bufsz=%lu\n", - hash_table_name, HASH_TABLE_NAME_BUF_SZ); - - /* set hash creating parameters */ - struct rte_hash_parameters hash_params = { - .name = hash_table_name, - .entries = NUM_CLASSIFIER_MAC_TABLE_ENTRY, - .key_len = sizeof(struct ether_addr), - .hash_func = DEFAULT_HASH_FUNC, - .hash_func_init_val = 0, - .socket_id = rte_socket_id(), - }; - - /* create classifier mac table (hash table) */ - *classifier_mac_table = rte_hash_create(&hash_params); - if (unlikely(*classifier_mac_table == NULL)) { - RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "Cannot create classifier mac table. " - "name=%s\n", hash_table_name); - return -1; - } - } - /* populate the classifier information at reference */ ret = init_component_info(&mng_info-> cmp_infos[mng_info->ref_index], &component_info); @@ -340,25 +517,48 @@ init_classifier(struct management_info *mng_info) /* updating side can be set by completion of initialization. */ mng_info->upd_index = mng_info->ref_index + 1; + mng_info->is_used = 1; return 0; } +/* free mac classification instance. */ +static inline void +free_mac_classification(struct mac_classification *mac_cls) +{ + if (mac_cls == NULL) + return; + + if (mac_cls->classification_tab != NULL) + rte_hash_free(mac_cls->classification_tab); + + rte_free(mac_cls); +} + +/* uninitialize classifier information. */ +static void +uninit_component_info(struct component_info *cmp_info) +{ + int i; + + for (i = 0; i < SPP_NUM_VLAN_VID; ++i) + free_mac_classification(cmp_info->mac_classifications[i]); + + memset(cmp_info, 0, sizeof(struct component_info)); +} + /* uninitialize classifier. */ static void uninit_classifier(struct management_info *mng_info) { int i; - for (i = 0; i < NUM_CLASSIFIER_MAC_INFO; ++i) { - if (mng_info->cmp_infos[i].classifier_table != NULL) { - rte_hash_free(mng_info->cmp_infos[i]. - classifier_table); - mng_info->cmp_infos[i].classifier_table = NULL; - mng_info->ref_index = 0; - mng_info->upd_index = 0; - } - } + mng_info->is_used = 0; + + for (i = 0; i < NUM_CLASSIFIER_MAC_INFO; ++i) + uninit_component_info(mng_info->cmp_infos + (long)i); + + memset(mng_info, 0, sizeof(struct management_info)); } /* transmit packet to one destination. */ @@ -415,7 +615,8 @@ push_packet(struct rte_mbuf *pkt, struct classified_data *clsd_data) if (unlikely(clsd_data->num_pkt == MAX_PKT_BURST)) { RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "transmit packets (buffer is filled). " - "iface_type=%d, iface_no={%d,%d}, tx_port=%hu, num_pkt=%hu\n", + "iface_type=%d, iface_no={%d,%d}, " + "tx_port=%hu, num_pkt=%hu\n", clsd_data->iface_type, clsd_data->iface_no_global, clsd_data->iface_no, @@ -425,6 +626,22 @@ push_packet(struct rte_mbuf *pkt, struct classified_data *clsd_data) } } +/* get index of general default classified */ +static inline int +get_general_default_classified_index(struct component_info *cmp_info) +{ + struct mac_classification *mac_cls; + + mac_cls = cmp_info->mac_classifications[VLAN_UNTAGGED_VID]; + if (unlikely(mac_cls == NULL)) { + LOG_DBG(cmp_info->name, "Untagged's default is not set. vid=%d\n", + (int)VLAN_UNTAGGED_VID); + return -1; + } + + return mac_cls->default_classified; +} + /* handle L2 multicast(include broadcast) packet */ static inline void handle_l2multicast_packet(struct rte_mbuf *pkt, @@ -432,20 +649,103 @@ handle_l2multicast_packet(struct rte_mbuf *pkt, struct classified_data *clsd_data) { int i; + struct mac_classification *mac_cls; + uint16_t vid = get_vid(pkt); + int gen_def_clsd_idx = get_general_default_classified_index(cmp_info); + int n_act_clsd; + + /* select mac address classification by vid */ + mac_cls = cmp_info->mac_classifications[vid]; + if (unlikely(mac_cls == NULL || + mac_cls->num_active_classified == 0)) { + /* specific vlan is not registered + * use untagged's default(as general default) + */ + if (unlikely(gen_def_clsd_idx < 0)) { + /* untagged's default is not registered too */ + RTE_LOG(ERR, SPP_CLASSIFIER_MAC, + "No entry.(l2 multicast packet)\n"); + rte_pktmbuf_free(pkt); + return; + } - if (unlikely(cmp_info->num_active_classified == 0)) { - RTE_LOG(ERR, SPP_CLASSIFIER_MAC, "No mac address.(l2 multicast packet)\n"); - rte_pktmbuf_free(pkt); + /* transmit to untagged's default(as general default) */ + LOG_CLS((long)gen_def_clsd_idx, pkt, cmp_info, clsd_data); + push_packet(pkt, clsd_data + (long)gen_def_clsd_idx); return; } - rte_mbuf_refcnt_update(pkt, - (cmp_info->num_active_classified - 1)); + /* add to mbuf's refcnt */ + n_act_clsd = mac_cls->num_active_classified; + if (gen_def_clsd_idx >= 0 && vid != VLAN_UNTAGGED_VID) + ++n_act_clsd; - for (i = 0; i < cmp_info->num_active_classified; i++) { + rte_mbuf_refcnt_update(pkt, (int16_t)(n_act_clsd - 1)); + + /* transmit to specific segment & general default */ + for (i = 0; i < mac_cls->num_active_classified; i++) { + LOG_CLS((long)mac_cls->active_classifieds[i], + pkt, cmp_info, clsd_data); push_packet(pkt, clsd_data + - (long)cmp_info->active_classifieds[i]); + (long)mac_cls->active_classifieds[i]); + } + + if (gen_def_clsd_idx >= 0 && vid != VLAN_UNTAGGED_VID) { + LOG_CLS((long)gen_def_clsd_idx, pkt, cmp_info, clsd_data); + push_packet(pkt, clsd_data + (long)gen_def_clsd_idx); + } +} + +/* select index of classified */ +static inline int +select_classified_index(const struct rte_mbuf *pkt, + struct component_info *cmp_info) +{ + int ret; + struct ether_hdr *eth; + void *lookup_data; + struct mac_classification *mac_cls; + uint16_t vid; + + eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *); + vid = get_vid(pkt); + + /* select mac address classification by vid */ + mac_cls = cmp_info->mac_classifications[vid]; + if (unlikely(mac_cls == NULL)) { + LOG_DBG(cmp_info->name, "Mac classification is not registered. vid=%hu\n", + vid); + return get_general_default_classified_index(cmp_info); + } + + /* find in table (by destination mac address) */ + ret = rte_hash_lookup_data(mac_cls->classification_tab, + (const void *)ð->d_addr, &lookup_data); + if (ret >= 0) { + LOG_DBG(cmp_info->name, "Mac address is registered. ret=%d, vid=%hu\n", + ret, vid); + return (int)(long)lookup_data; + } + + LOG_DBG(cmp_info->name, + "Mac address is not registered. ret=%d, (EINVAL=%d, ENOENT=%d)\n", + ret, EINVAL, ENOENT); + + /* check if packet is l2 multicast */ + if (unlikely(is_multicast_ether_addr(ð->d_addr))) + return -2; + + /* if default is not set, use untagged's default */ + if (unlikely(mac_cls->default_classified < 0 && + vid != VLAN_UNTAGGED_VID)) { + LOG_DBG(cmp_info->name, "Vid's default is not set. use general default. vid=%hu\n", + vid); + return get_general_default_classified_index(cmp_info); } + + /* use default */ + LOG_DBG(cmp_info->name, "Use vid's default. vid=%hu\n", vid); + return mac_cls->default_classified; } /* @@ -457,55 +757,29 @@ classify_packet(struct rte_mbuf **rx_pkts, uint16_t n_rx, struct component_info *cmp_info, struct classified_data *clsd_data) { - int ret; int i; - struct ether_hdr *eth; - void *lookup_data; - char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; + long clsd_idx; for (i = 0; i < n_rx; i++) { - eth = rte_pktmbuf_mtod(rx_pkts[i], struct ether_hdr *); - - /* find in table (by destination mac address)*/ - ret = rte_hash_lookup_data(cmp_info->classifier_table, - (const void *)ð->d_addr, &lookup_data); - if (ret < 0) { - /* L2 multicast(include broadcast) ? */ - if (unlikely(is_multicast_ether_addr(ð->d_addr))) { - RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, - "multicast mac address.\n"); - handle_l2multicast_packet(rx_pkts[i], - cmp_info, - clsd_data); - continue; - } - - /* if no default, drop packet */ - if (unlikely(cmp_info->default_classified == - -1)) { - ether_format_addr(mac_addr_str, - sizeof(mac_addr_str), - ð->d_addr); - RTE_LOG(ERR, SPP_CLASSIFIER_MAC, - "unknown mac address. " - "ret=%d, mac_addr=%s\n", - ret, mac_addr_str); - rte_pktmbuf_free(rx_pkts[i]); - continue; - } - - /* to default classified */ - RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, - "to default classified.\n"); - lookup_data = (void *)(long)cmp_info-> - default_classified; + LOG_PKT(cmp_info->name, rx_pkts[i]); + + clsd_idx = select_classified_index(rx_pkts[i], cmp_info); + LOG_CLS(clsd_idx, rx_pkts[i], cmp_info, clsd_data); + + if (likely(clsd_idx >= 0)) { + LOG_DBG(cmp_info->name, "as unicast packet. i=%d\n", + i); + push_packet(rx_pkts[i], clsd_data + clsd_idx); + } else if (unlikely(clsd_idx == -1)) { + LOG_DBG(cmp_info->name, "no destination. drop packet. i=%d\n", + i); + rte_pktmbuf_free(rx_pkts[i]); + } else if (unlikely(clsd_idx == -2)) { + LOG_DBG(cmp_info->name, "as multicast packet. i=%d\n", + i); + handle_l2multicast_packet(rx_pkts[i], + cmp_info, clsd_data); } - - /* - * set mbuf pointer to tx buffer - * and transmit packet, if buffer is filled - */ - push_packet(rx_pkts[i], clsd_data + (long)lookup_data); } } @@ -575,6 +849,9 @@ spp_classifier_mac_update(struct spp_component_info *component_info) mng_info->upd_index)) rte_delay_us_block(CHANGE_UPDATE_INDEX_WAIT_INTERVAL); + /* uninitialize old */ + uninit_component_info(mng_info->cmp_infos + mng_info->upd_index); + RTE_LOG(INFO, SPP_CLASSIFIER_MAC, "Component[%u] Complete update component.\n", id); @@ -602,8 +879,10 @@ spp_classifier_mac_do(int id) /* initialize */ ret = init_classifier(mng_info); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + uninit_classifier(mng_info); return ret; + } while (likely(spp_get_core_status(lcore_id) == SPP_CORE_FORWARD) && likely(spp_check_core_index(lcore_id) == 0)) { @@ -710,20 +989,79 @@ spp_classifier_get_component_status( return 0; } +static void +mac_classification_iterate_table( + struct spp_iterate_classifier_table_params *params, + uint16_t vid, + struct mac_classification *mac_cls, + __rte_unused struct component_info *cmp_info, + struct classified_data *clsd_data) +{ + int ret; + const void *key; + void *data; + uint32_t next; + struct spp_port_index port; + char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; + enum spp_classifier_type type; + + type = SPP_CLASSIFIER_TYPE_VLAN; + if (unlikely(vid == VLAN_UNTAGGED_VID)) + type = SPP_CLASSIFIER_TYPE_MAC; + + if (mac_cls->default_classified >= 0) { + port.iface_type = (clsd_data + + mac_cls->default_classified)->iface_type; + port.iface_no = (clsd_data + + mac_cls->default_classified)->iface_no_global; + + LOG_ENT((long)mac_cls->default_classified, + vid, + SPP_DEFAULT_CLASSIFIED_SPEC_STR, + cmp_info, clsd_data); + + (*params->element_proc)( + params, + type, + vid, + SPP_DEFAULT_CLASSIFIED_SPEC_STR, + &port); + } + + next = 0; + while (1) { + ret = rte_hash_iterate(mac_cls->classification_tab, + &key, &data, &next); + + if (unlikely(ret < 0)) + break; + + ether_format_addr(mac_addr_str, sizeof(mac_addr_str), + (const struct ether_addr *)key); + + port.iface_type = (clsd_data + (long)data)->iface_type; + port.iface_no = (clsd_data + (long)data)->iface_no_global; + + LOG_ENT((long)data, vid, mac_addr_str, cmp_info, clsd_data); + + (*params->element_proc)( + params, + type, + vid, + mac_addr_str, + &port); + } +} + /* classifier(mac address) iterate classifier table. */ int spp_classifier_mac_iterate_table( struct spp_iterate_classifier_table_params *params) { - int ret, i; - const void *key; - void *data; - uint32_t next = 0; + int i, n; struct management_info *mng_info; struct component_info *cmp_info; struct classified_data *clsd_data; - struct spp_port_index port; - char mac_addr_str[ETHER_ADDR_STR_BUF_SZ]; for (i = 0; i < RTE_MAX_LCORE; i++) { mng_info = g_mng_infos + i; @@ -731,49 +1069,21 @@ spp_classifier_mac_iterate_table( continue; cmp_info = mng_info->cmp_infos + mng_info->ref_index; - clsd_data = cmp_info->classified_data_tx; RTE_LOG(DEBUG, SPP_CLASSIFIER_MAC, "Core[%u] Start iterate classifier table.\n", i); - if (cmp_info->default_classified >= 0) { - port.iface_type = (clsd_data + - cmp_info->default_classified)-> - iface_type; - port.iface_no = (clsd_data + - cmp_info->default_classified)-> - iface_no_global; - - (*params->element_proc)( - params, - SPP_CLASSIFIER_TYPE_MAC, - SPP_DEFAULT_CLASSIFIED_SPEC_STR, - &port); - } - - next = 0; - while (1) { - ret = rte_hash_iterate( - cmp_info->classifier_table, - &key, &data, &next); - - if (unlikely(ret < 0)) - break; - - ether_format_addr(mac_addr_str, sizeof(mac_addr_str), - (const struct ether_addr *)key); - - port.iface_type = (clsd_data + (long)data)-> - iface_type; - port.iface_no = (clsd_data + (long)data)-> - iface_no_global; + for (n = 0; n < SPP_NUM_VLAN_VID; ++n) { + if (cmp_info->mac_classifications[n] == NULL) + continue; - (*params->element_proc)( + mac_classification_iterate_table( params, - SPP_CLASSIFIER_TYPE_MAC, - mac_addr_str, - &port); + (uint16_t)n, + cmp_info->mac_classifications[n], + cmp_info, + clsd_data); } } diff --git a/src/vf/command_dec.c b/src/vf/command_dec.c index 374a105..35d421a 100644 --- a/src/vf/command_dec.c +++ b/src/vf/command_dec.c @@ -51,6 +51,7 @@ const char *CLASSIFILER_TYPE_STRINGS[] = { "none", "mac", + "vlan", /* termination */ "", }; @@ -535,21 +536,18 @@ decode_classifier_type_value(void *output, const char *arg_val) return 0; } -/* decoding procedure of value for classifier_table command */ +/* decoding procedure of vlan id for classifier_table command */ static int -decode_classifier_value_value(void *output, const char *arg_val) +decode_classifier_vid_value(void *output, const char *arg_val) { int ret = -1; - struct spp_command_classifier_table *classifier_table = output; - switch (classifier_table->type) { - case SPP_CLASSIFIER_TYPE_MAC: - ret = decode_mac_addr_str_value(classifier_table->value, + ret = get_int_value(output, arg_val, 0, ETH_VLAN_ID_MAX); + if (unlikely(ret < 0)) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Bad VLAN ID. val=%s\n", arg_val); - break; - default: - break; + return -1; } - return ret; + return 0; } /* decoding procedure of port for classifier_table command */ @@ -571,20 +569,24 @@ decode_classifier_port_value(void *output, const char *arg_val) return -1; } + if (classifier_table->type == SPP_CLASSIFIER_TYPE_MAC) + classifier_table->vid = ETH_VLAN_ID_MAX; + if (unlikely(classifier_table->action == SPP_CMD_ACTION_ADD)) { - if (!spp_check_mac_used_port(0, tmp_port.iface_type, - tmp_port.iface_no)) { + if (!spp_check_classid_used_port(ETH_VLAN_ID_MAX, 0, + tmp_port.iface_type, tmp_port.iface_no)) { RTE_LOG(ERR, SPP_COMMAND_PROC, "Port in used. (classifier_table command) val=%s\n", arg_val); return -1; } } else if (unlikely(classifier_table->action == SPP_CMD_ACTION_DEL)) { - mac_addr = spp_change_mac_str_to_int64(classifier_table->value); + mac_addr = spp_change_mac_str_to_int64(classifier_table->mac); if (mac_addr < 0) return -1; - if (!spp_check_mac_used_port((uint64_t)mac_addr, + if (!spp_check_classid_used_port(classifier_table->vid, + (uint64_t)mac_addr, tmp_port.iface_type, tmp_port.iface_no)) { RTE_LOG(ERR, SPP_COMMAND_PROC, "Port in used. (classifier_table command) val=%s\n", @@ -610,7 +612,7 @@ struct decode_parameter_list { /* parameter list for each command */ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = { - { /* classifier_table */ + { /* classifier_table(mac) */ { .name = "action", .offset = offsetof(struct spp_command, @@ -624,10 +626,43 @@ static struct decode_parameter_list parameter_list[][SPP_CMD_MAX_PARAMETERS] = { .func = decode_classifier_type_value }, { - .name = "value", + .name = "mac address", + .offset = offsetof(struct spp_command, + spec.classifier_table.mac), + .func = decode_mac_addr_str_value + }, + { + .name = "port", .offset = offsetof(struct spp_command, spec.classifier_table), - .func = decode_classifier_value_value + .func = decode_classifier_port_value + }, + DECODE_PARAMETER_LIST_EMPTY, + }, + { /* classifier_table(VLAN) */ + { + .name = "action", + .offset = offsetof(struct spp_command, + spec.classifier_table.action), + .func = decode_classifier_action_value + }, + { + .name = "type", + .offset = offsetof(struct spp_command, + spec.classifier_table.type), + .func = decode_classifier_type_value + }, + { + .name = "vlan id", + .offset = offsetof(struct spp_command, + spec.classifier_table.vid), + .func = decode_classifier_vid_value + }, + { + .name = "mac address", + .offset = offsetof(struct spp_command, + spec.classifier_table.mac), + .func = decode_mac_addr_str_value }, { .name = "port", @@ -747,7 +782,9 @@ struct decode_command_list { /* command list */ static struct decode_command_list command_list[] = { { "classifier_table", 5, 5, decode_command_parameter_in_list }, - /* classifier_table */ + /* classifier_table(mac) */ + { "classifier_table", 6, 6, decode_command_parameter_in_list }, + /* classifier_table(vlan) */ { "flush", 1, 1, NULL }, /* flush */ { "_get_client_id", 1, 1, NULL }, /* _get_client_id */ { "status", 1, 1, NULL }, /* status */ @@ -767,6 +804,7 @@ decode_command_in_list(struct spp_command_request *request, struct spp_command_decode_error *error) { int ret = 0; + int command_name_check = 0; struct decode_command_list *list = NULL; int i = 0; int argc = 0; @@ -792,11 +830,8 @@ decode_command_in_list(struct spp_command_request *request, if (unlikely(argc < list->param_min) || unlikely(list->param_max < argc)) { - RTE_LOG(ERR, SPP_COMMAND_PROC, - "Parameter number out of range." - "request_str=%s\n", request_str); - return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, - NULL); + command_name_check = 1; + continue; } request->commands[0].type = i; @@ -806,6 +841,12 @@ decode_command_in_list(struct spp_command_request *request, return 0; } + if (command_name_check != 0) { + RTE_LOG(ERR, SPP_COMMAND_PROC, "Parameter number out of range." + "request_str=%s\n", request_str); + return set_decode_error(error, SPP_CMD_DERR_BAD_FORMAT, NULL); + } + RTE_LOG(ERR, SPP_COMMAND_PROC, "Unknown command. command=%s, request_str=%s\n", argv[0], request_str); diff --git a/src/vf/command_dec.h b/src/vf/command_dec.h index f919b16..9f7bada 100644 --- a/src/vf/command_dec.h +++ b/src/vf/command_dec.h @@ -74,14 +74,32 @@ enum spp_command_decode_error_code { * defined in command_dec.c */ enum spp_command_type { - SPP_CMDTYPE_CLASSIFIER_TABLE, /**< classifier_table command */ - SPP_CMDTYPE_FLUSH, /**< flush command */ - SPP_CMDTYPE_CLIENT_ID, /**< get_client_id command */ - SPP_CMDTYPE_STATUS, /**< status command */ - SPP_CMDTYPE_EXIT, /**< exit command */ - SPP_CMDTYPE_COMPONENT, /**< component command */ - SPP_CMDTYPE_PORT, /**< port command */ - SPP_CMDTYPE_CANCEL, /**< cancel command */ + /** classifier_table command(mac) */ + SPP_CMDTYPE_CLASSIFIER_TABLE_MAC, + + /** classifier_table command(VLAN) */ + SPP_CMDTYPE_CLASSIFIER_TABLE_VLAN, + + /** flush command */ + SPP_CMDTYPE_FLUSH, + + /** get_client_id command */ + SPP_CMDTYPE_CLIENT_ID, + + /** status command */ + SPP_CMDTYPE_STATUS, + + /** exit command */ + SPP_CMDTYPE_EXIT, + + /** component command */ + SPP_CMDTYPE_COMPONENT, + + /** port command */ + SPP_CMDTYPE_PORT, + + /** cancel command */ + SPP_CMDTYPE_CANCEL, }; /** "classifier_table" command specific parameters */ @@ -92,8 +110,11 @@ struct spp_command_classifier_table { /** Classify type (currently only for mac) */ enum spp_classifier_type type; - /** Value to be classified */ - char value[SPP_CMD_VALUE_BUFSZ]; + /** VLAN ID to be classified */ + int vid; + + /** MAC address to be classified */ + char mac[SPP_CMD_VALUE_BUFSZ]; /** Destination port type and number */ struct spp_port_index port; diff --git a/src/vf/command_proc.c b/src/vf/command_proc.c index a00181b..11c7cc3 100644 --- a/src/vf/command_proc.c +++ b/src/vf/command_proc.c @@ -102,6 +102,18 @@ const char *PORT_ABILITY_STATUS_STRINGS[] = { /* termination */ "", }; +/* + * classifier type string list + * do it same as the order of enum spp_classifier_type (spp_vf.h) + */ +const char *CLASSIFILER_TYPE_STATUS_STRINGS[] = { + "none", + "mac", + "vlan", + + /* termination */ "", +}; + /* append a comma for JSON format */ static int append_json_comma(char **output) @@ -226,13 +238,15 @@ execute_command(const struct spp_command *command) int ret = 0; switch (command->type) { - case SPP_CMDTYPE_CLASSIFIER_TABLE: + case SPP_CMDTYPE_CLASSIFIER_TABLE_MAC: + case SPP_CMDTYPE_CLASSIFIER_TABLE_VLAN: RTE_LOG(INFO, SPP_COMMAND_PROC, "Execute classifier_table command.\n"); ret = spp_update_classifier_table( command->spec.classifier_table.action, command->spec.classifier_table.type, - command->spec.classifier_table.value, + command->spec.classifier_table.vid, + command->spec.classifier_table.mac, &command->spec.classifier_table.port); break; @@ -688,13 +702,14 @@ append_core_value(const char *name, char **output, static int append_classifier_element_value( struct spp_iterate_classifier_table_params *params, - __rte_unused enum spp_classifier_type type, - const char *data, + enum spp_classifier_type type, + int vid, const char *mac, const struct spp_port_index *port) { int ret = -1; char *buff, *tmp_buff; char port_str[CMD_TAG_APPEND_SIZE]; + char value_str[SPP_MIN_STR_LEN]; buff = params->output; tmp_buff = spp_strbuf_allocate(CMD_RES_BUF_INIT_SIZE); if (unlikely(tmp_buff == NULL)) { @@ -705,11 +720,25 @@ append_classifier_element_value( spp_format_port_string(port_str, port->iface_type, port->iface_no); - ret = append_json_str_value("type", &tmp_buff, "mac"); + ret = append_json_str_value("type", &tmp_buff, + CLASSIFILER_TYPE_STATUS_STRINGS[type]); if (unlikely(ret < 0)) return ret; - ret = append_json_str_value("value", &tmp_buff, data); + memset(value_str, 0x00, SPP_MIN_STR_LEN); + switch (type) { + case SPP_CLASSIFIER_TYPE_MAC: + sprintf(value_str, "%s", mac); + break; + case SPP_CLASSIFIER_TYPE_VLAN: + sprintf(value_str, "%d/%s", vid, mac); + break; + default: + /* not used */ + break; + } + + ret = append_json_str_value("value", &tmp_buff, value_str); if (unlikely(ret < 0)) return ret; diff --git a/src/vf/spp_vf.c b/src/vf/spp_vf.c index 4463d41..ef75159 100644 --- a/src/vf/spp_vf.c +++ b/src/vf/spp_vf.c @@ -591,10 +591,12 @@ dump_interface_info(const struct iface_info *iface_info) continue; RTE_LOG(DEBUG, APP, "phy [%d] type=%d, no=%d, port=%d, " - "mac=%08lx(%s)\n", + "vid = %u, mac=%08lx(%s)\n", cnt, port->iface_type, port->iface_no, port->dpdk_port, - port->mac_addr, port->mac_addr_str); + port->class_id.vlantag.vid, + port->class_id.mac_addr, + port->class_id.mac_addr_str); } for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { port = &iface_info->vhost[cnt]; @@ -602,10 +604,12 @@ dump_interface_info(const struct iface_info *iface_info) continue; RTE_LOG(DEBUG, APP, "vhost[%d] type=%d, no=%d, port=%d, " - "mac=%08lx(%s)\n", + "vid = %u, mac=%08lx(%s)\n", cnt, port->iface_type, port->iface_no, port->dpdk_port, - port->mac_addr, port->mac_addr_str); + port->class_id.vlantag.vid, + port->class_id.mac_addr, + port->class_id.mac_addr_str); } for (cnt = 0; cnt < RTE_MAX_ETHPORTS; cnt++) { port = &iface_info->ring[cnt]; @@ -613,10 +617,12 @@ dump_interface_info(const struct iface_info *iface_info) continue; RTE_LOG(DEBUG, APP, "ring [%d] type=%d, no=%d, port=%d, " - "mac=%08lx(%s)\n", + "vid = %u, mac=%08lx(%s)\n", cnt, port->iface_type, port->iface_no, port->dpdk_port, - port->mac_addr, port->mac_addr_str); + port->class_id.vlantag.vid, + port->class_id.mac_addr, + port->class_id.mac_addr_str); } } @@ -712,15 +718,21 @@ init_iface_info(void) int port_cnt; /* increment ether ports */ memset(&g_iface_info, 0x00, sizeof(g_iface_info)); for (port_cnt = 0; port_cnt < RTE_MAX_ETHPORTS; port_cnt++) { - g_iface_info.nic[port_cnt].iface_type = UNDEF; - g_iface_info.nic[port_cnt].iface_no = port_cnt; - g_iface_info.nic[port_cnt].dpdk_port = -1; - g_iface_info.vhost[port_cnt].iface_type = UNDEF; - g_iface_info.vhost[port_cnt].iface_no = port_cnt; - g_iface_info.vhost[port_cnt].dpdk_port = -1; - g_iface_info.ring[port_cnt].iface_type = UNDEF; - g_iface_info.ring[port_cnt].iface_no = port_cnt; - g_iface_info.ring[port_cnt].dpdk_port = -1; + g_iface_info.nic[port_cnt].iface_type = UNDEF; + g_iface_info.nic[port_cnt].iface_no = port_cnt; + g_iface_info.nic[port_cnt].dpdk_port = -1; + g_iface_info.nic[port_cnt].class_id.vlantag.vid = + ETH_VLAN_ID_MAX; + g_iface_info.vhost[port_cnt].iface_type = UNDEF; + g_iface_info.vhost[port_cnt].iface_no = port_cnt; + g_iface_info.vhost[port_cnt].dpdk_port = -1; + g_iface_info.vhost[port_cnt].class_id.vlantag.vid = + ETH_VLAN_ID_MAX; + g_iface_info.ring[port_cnt].iface_type = UNDEF; + g_iface_info.ring[port_cnt].iface_no = port_cnt; + g_iface_info.ring[port_cnt].dpdk_port = -1; + g_iface_info.ring[port_cnt].class_id.vlantag.vid = + ETH_VLAN_ID_MAX; } } @@ -1098,13 +1110,13 @@ spp_get_client_id(void) * Check mac address used on the port for registering or removing */ int -spp_check_mac_used_port( - uint64_t mac_addr, - enum port_type iface_type, - int iface_no) +spp_check_classid_used_port( + int vid, uint64_t mac_addr, + enum port_type iface_type, int iface_no) { struct spp_port_info *port_info = get_iface_info(iface_type, iface_no); - return (mac_addr == port_info->mac_addr); + return ((mac_addr == port_info->class_id.mac_addr) && + (vid == port_info->class_id.vlantag.vid)); } /* @@ -1190,62 +1202,78 @@ set_component_change_port(struct spp_port_info *port, enum spp_port_rxtx rxtx) int spp_update_classifier_table( enum spp_command_action action, - enum spp_classifier_type type, - const char *data, + enum spp_classifier_type type __attribute__ ((unused)), + int vid, + const char *mac_addr_str, const struct spp_port_index *port) { struct spp_port_info *port_info = NULL; int64_t ret_mac = 0; uint64_t mac_addr = 0; - if (type == SPP_CLASSIFIER_TYPE_MAC) { - RTE_LOG(DEBUG, APP, "update_classifier_table ( type = mac, data = %s, port = %d:%d )\n", - data, port->iface_type, port->iface_no); + RTE_LOG(DEBUG, APP, "update_classifier_table ( type = mac, mac addr = %s, port = %d:%d )\n", + mac_addr_str, port->iface_type, port->iface_no); + + ret_mac = spp_change_mac_str_to_int64(mac_addr_str); + if (unlikely(ret_mac == -1)) { + RTE_LOG(ERR, APP, "MAC address format error. ( mac = %s )\n", + mac_addr_str); + return SPP_RET_NG; + } + mac_addr = (uint64_t)ret_mac; + + port_info = get_iface_info(port->iface_type, port->iface_no); + if (unlikely(port_info == NULL)) { + RTE_LOG(ERR, APP, "No port. ( port = %d:%d )\n", + port->iface_type, port->iface_no); + return SPP_RET_NG; + } + if (unlikely(port_info->iface_type == UNDEF)) { + RTE_LOG(ERR, APP, "Port not added. ( port = %d:%d )\n", + port->iface_type, port->iface_no); + return SPP_RET_NG; + } - ret_mac = spp_change_mac_str_to_int64(data); - if (unlikely(ret_mac == -1)) { - RTE_LOG(ERR, APP, "MAC address format error. ( mac = %s )\n", - data); + if (action == SPP_CMD_ACTION_DEL) { + /* Delete */ + if ((port_info->class_id.vlantag.vid != 0) && + unlikely(port_info->class_id.vlantag.vid != + vid)) { + RTE_LOG(ERR, APP, "VLAN ID is different. ( vid = %d )\n", + vid); + return SPP_RET_NG; + } + if ((port_info->class_id.mac_addr != 0) && + unlikely(port_info->class_id.mac_addr != + mac_addr)) { + RTE_LOG(ERR, APP, "MAC address is different. ( mac = %s )\n", + mac_addr_str); return SPP_RET_NG; } - mac_addr = (uint64_t)ret_mac; - port_info = get_iface_info(port->iface_type, port->iface_no); - if (unlikely(port_info == NULL)) { - RTE_LOG(ERR, APP, "No port. ( port = %d:%d )\n", - port->iface_type, port->iface_no); + port_info->class_id.vlantag.vid = ETH_VLAN_ID_MAX; + port_info->class_id.mac_addr = 0; + memset(port_info->class_id.mac_addr_str, 0x00, SPP_MIN_STR_LEN); + } else if (action == SPP_CMD_ACTION_ADD) { + /* Setting */ + if (unlikely(port_info->class_id.vlantag.vid != + ETH_VLAN_ID_MAX)) { + RTE_LOG(ERR, APP, "Port in used. ( port = %d:%d, vlan = %d != %d )\n", + port->iface_type, port->iface_no, + port_info->class_id.vlantag.vid, vid); return SPP_RET_NG; } - if (unlikely(port_info->iface_type == UNDEF)) { - RTE_LOG(ERR, APP, "Port not added. ( port = %d:%d )\n", - port->iface_type, port->iface_no); + if (unlikely(port_info->class_id.mac_addr != 0)) { + RTE_LOG(ERR, APP, "Port in used. ( port = %d:%d, mac = %s != %s )\n", + port->iface_type, port->iface_no, + port_info->class_id.mac_addr_str, + mac_addr_str); return SPP_RET_NG; } - if (action == SPP_CMD_ACTION_DEL) { - /* Delete */ - if ((port_info->mac_addr != 0) && - unlikely(port_info->mac_addr != - mac_addr)) { - RTE_LOG(ERR, APP, "MAC address is different. ( mac = %s )\n", - data); - return SPP_RET_NG; - } - - port_info->mac_addr = 0; - memset(port_info->mac_addr_str, 0x00, SPP_MIN_STR_LEN); - } else if (action == SPP_CMD_ACTION_ADD) { - /* Setting */ - if (unlikely(port_info->mac_addr != 0)) { - RTE_LOG(ERR, APP, "Port in used. ( port = %d:%d )\n", - port->iface_type, - port->iface_no); - return SPP_RET_NG; - } - - port_info->mac_addr = mac_addr; - strcpy(port_info->mac_addr_str, data); - } + port_info->class_id.vlantag.vid = vid; + port_info->class_id.mac_addr = mac_addr; + strcpy(port_info->class_id.mac_addr_str, mac_addr_str); } set_component_change_port(port_info, SPP_PORT_RXTX_TX); diff --git a/src/vf/spp_vf.h b/src/vf/spp_vf.h index e51cd1a..fa01b85 100644 --- a/src/vf/spp_vf.h +++ b/src/vf/spp_vf.h @@ -85,8 +85,8 @@ /** Maximum number of port abilities available */ #define SPP_PORT_ABILITY_MAX 4 -/** Maximum VLAN ID */ -#define SPP_VLAN_VID_MAX 4096 +/** Number of VLAN ID */ +#define SPP_NUM_VLAN_VID 4096 /** Maximum VLAN PCP */ #define SPP_VLAN_PCP_MAX 7 @@ -118,7 +118,8 @@ enum spp_component_type { */ enum spp_classifier_type { SPP_CLASSIFIER_TYPE_NONE, /**< Type none */ - SPP_CLASSIFIER_TYPE_MAC /**< MAC address */ + SPP_CLASSIFIER_TYPE_MAC, /**< MAC address */ + SPP_CLASSIFIER_TYPE_VLAN /**< VLAN ID */ }; /** @@ -181,15 +182,22 @@ struct spp_port_ability { union spp_ability_data data; /**< Port ability data */ }; +/** Port class identifier for classifying */ +struct spp_port_class_identifier { + uint64_t mac_addr; /**< Mac address (binary) */ + char mac_addr_str[SPP_MIN_STR_LEN]; /**< Mac address (text) */ + struct spp_vlantag_info vlantag; /**< VLAN tag information */ +}; + /** * Port info */ struct spp_port_info { - enum port_type iface_type; /**< Interface type (phy/vhost/ring) */ - int iface_no; /**< Interface number */ - int dpdk_port; /**< DPDK port number */ - uint64_t mac_addr; /**< Mac address for classifying */ - char mac_addr_str[SPP_MIN_STR_LEN]; /**< Mac address */ + enum port_type iface_type; /**< Interface type (phy/vhost/ring) */ + int iface_no; /**< Interface number */ + int dpdk_port; /**< DPDK port number */ + struct spp_port_class_identifier class_id; + /**< Port class identifier */ struct spp_port_ability ability[SPP_PORT_ABILITY_MAX]; /**< Port ability */ }; @@ -235,7 +243,8 @@ int spp_get_client_id(void); int spp_update_classifier_table( enum spp_command_action action, enum spp_classifier_type type, - const char *data, + int vid, + const char *mac, const struct spp_port_index *port); /** @@ -331,7 +340,7 @@ struct spp_iterate_classifier_table_params; typedef int (*spp_iterate_classifier_element_proc)( struct spp_iterate_classifier_table_params *params, enum spp_classifier_type type, - const char *data, + int vid, const char *mac, const struct spp_port_index *port); /** iterate classifier table parameters */ @@ -423,6 +432,8 @@ int spp_get_component_id(const char *name); /** * Check mac address used on the port for registering or removing * + * @param vid + * VLAN ID to be validated. * @param mac_addr * Mac address to be validated. * @param iface_type @@ -431,12 +442,12 @@ int spp_get_component_id(const char *name); * Interface number to be validated. * * @return - * True if target MAC address matches MAC address of port. + * True if target identifier(VLAN ID, MAC address) + * matches identifier(VLAN ID, MAC address) of port. */ -int spp_check_mac_used_port( - uint64_t mac_addr, - enum port_type iface_type, - int iface_no); +int spp_check_classid_used_port( + int vid, uint64_t mac_addr, + enum port_type iface_type, int iface_no); /** * Check if port has been added. -- 2.7.4