[dpdk-stable] [PATCH 18.11 3/3] net/enic: fix VLAN inner type matching for old hardware

Hyong Youb Kim hyonkim at cisco.com
Fri Apr 26 09:05:20 CEST 2019


[ upstream commit 6e54c8ac5c15935d42d47950a55406c7f5517117 ]

The vlan pattern handler currently assumes the NIC always strips vlan
header from the L2 buffer, regardless of the vlan strip setting. But,
with older VIC models, the vlan header is actually present in the L2
buffer if stripping is disabled. So in this case, the inner ether type
needs to be shifted by that much.

Fixes: 6ced137607d0 ("net/enic: flow API for NICs with advanced filters enabled")

Signed-off-by: Hyong Youb Kim <hyonkim at cisco.com>
Reviewed-by: John Daley <johndale at cisco.com>
---
 drivers/net/enic/enic_flow.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/enic/enic_flow.c b/drivers/net/enic/enic_flow.c
index ab6783f67..dbc8de839 100644
--- a/drivers/net/enic/enic_flow.c
+++ b/drivers/net/enic/enic_flow.c
@@ -39,6 +39,7 @@ struct copy_item_args {
 	uint8_t *inner_ofst;
 	uint8_t l2_proto_off;
 	uint8_t l3_proto_off;
+	struct enic *enic;
 };
 
 /* functions for copying items into enic filters */
@@ -698,12 +699,26 @@ enic_copy_item_vlan_v2(struct copy_item_args *arg)
 	if (eth_mask->ether_type)
 		return ENOTSUP;
 	/*
+	 * For recent models:
 	 * When packet matching, the VIC always compares vlan-stripped
 	 * L2, regardless of vlan stripping settings. So, the inner type
 	 * from vlan becomes the ether type of the eth header.
+	 *
+	 * Older models w/o hardware vxlan parser have a different
+	 * behavior when vlan stripping is disabled. In this case,
+	 * vlan tag remains in the L2 buffer.
 	 */
-	eth_mask->ether_type = mask->inner_type;
-	eth_val->ether_type = spec->inner_type;
+	if (!arg->enic->vxlan && !arg->enic->ig_vlan_strip_en) {
+		struct vlan_hdr *vlan;
+
+		vlan = (struct vlan_hdr *)(eth_mask + 1);
+		vlan->eth_proto = mask->inner_type;
+		vlan = (struct vlan_hdr *)(eth_val + 1);
+		vlan->eth_proto = spec->inner_type;
+	} else {
+		eth_mask->ether_type = mask->inner_type;
+		eth_val->ether_type = spec->inner_type;
+	}
 	/* For TCI, use the vlan mask/val fields (little endian). */
 	gp->mask_vlan = rte_be_to_cpu_16(mask->tci);
 	gp->val_vlan = rte_be_to_cpu_16(spec->tci);
@@ -1009,6 +1024,7 @@ enic_copy_filter(const struct rte_flow_item pattern[],
 
 	args.filter = enic_filter;
 	args.inner_ofst = &inner_ofst;
+	args.enic = enic;
 	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
 		/* Get info about how to validate and copy the item. If NULL
 		 * is returned the nic does not support the item.
-- 
2.16.2



More information about the stable mailing list