summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroyuki Nakamura <nakamura.hioryuki@po.ntt-tx.co.jp>2018-02-27 21:34:27 +0900
committerFerruh Yigit <ferruh.yigit@intel.com>2018-03-02 17:14:34 +0000
commitc5c76b19c991caf69dcaeb13f3eb35919873d647 (patch)
treebf28573496185663840cca4318adf137e4b2a896
parent63e4a5f3f1ed57768f0db3523cc24c9e116f5c62 (diff)
downloadspp-c5c76b19c991caf69dcaeb13f3eb35919873d647.zip
spp-c5c76b19c991caf69dcaeb13f3eb35919873d647.tar.gz
spp-c5c76b19c991caf69dcaeb13f3eb35919873d647.tar.xz
vf: add VID classification to the classifier
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 <yamashita.daiki.z01@as.ntt-tx.co.jp> Signed-off-by: Naoki Takada <takada.naoki@lab.ntt.co.jp>
-rw-r--r--src/vf/classifier_mac.c656
-rw-r--r--src/vf/command_dec.c87
-rw-r--r--src/vf/command_dec.h41
-rw-r--r--src/vf/command_proc.c41
-rw-r--r--src/vf/spp_vf.c150
-rw-r--r--src/vf/spp_vf.h41
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),
+ &eth->d_addr);
+ ether_format_addr(mac_addr_str[1], sizeof(mac_addr_str),
+ &eth->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),
+ &eth->d_addr);
+ ether_format_addr(mac_addr_str[1], sizeof(mac_addr_str),
+ &eth->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(&eth_addr, &tx_port->mac_addr, ETHER_ADDR_LEN);
+ rte_memcpy(&eth_addr, &tx_port->class_id.mac_addr,
+ ETHER_ADDR_LEN);
ether_format_addr(mac_addr_str, sizeof(mac_addr_str),
&eth_addr);
- ret = rte_hash_add_key_data(*classifier_table,
+ ret = rte_hash_add_key_data(mac_cls->classification_tab,
(void *)&eth_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 *)&eth->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(&eth->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 *)&eth->d_addr, &lookup_data);
- if (ret < 0) {
- /* L2 multicast(include broadcast) ? */
- if (unlikely(is_multicast_ether_addr(&eth->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),
- &eth->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.