DPDK patches and discussions
 help / color / mirror / Atom feed
From: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
To: dev@dpdk.org
Cc: nirranjan@chelsio.com, kaara.satwik@chelsio.com
Subject: [dpdk-dev] [PATCH 1/9] net/cxgbe: add rte_flow support for matching Q-in-Q VLAN
Date: Wed, 11 Mar 2020 14:35:43 +0530	[thread overview]
Message-ID: <67a7f133daaa4dae254208bc86c9c2b999688715.1583906144.git.kaara.satwik@chelsio.com> (raw)
In-Reply-To: <cover.1583906144.git.kaara.satwik@chelsio.com>
In-Reply-To: <cover.1583906144.git.kaara.satwik@chelsio.com>

From: Karra Satwik <kaara.satwik@chelsio.com>

Add support to match fields in 802.1ad Q-in-Q VLAN packets.
Relax check for repeated pattern items for RTE_FLOW_ITEM_TYPE_VLAN
item, since the same item is used to represent both QinQ and VLAN
packets.

When QinQ match is enabled, the ethertype field in the hardware
spec must contain the innermost VLAN header's ethertype field,
and not the Ethernet header's ethertype field. The hardware
automatically searches for ethertype 0x88A8/0x8100 in Ethernet
header, when parsing incoming packet against QinQ/VLAN pattern,
respectively.

Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 drivers/net/cxgbe/base/t4_hw.c   |   7 ---
 drivers/net/cxgbe/base/t4_regs.h |   4 ++
 drivers/net/cxgbe/cxgbe_filter.c |  26 +++++++-
 drivers/net/cxgbe/cxgbe_flow.c   | 102 +++++++++++++++++--------------
 4 files changed, 82 insertions(+), 57 deletions(-)

diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c
index 71ad1cb0f..f6bf57c75 100644
--- a/drivers/net/cxgbe/base/t4_hw.c
+++ b/drivers/net/cxgbe/base/t4_hw.c
@@ -5254,13 +5254,6 @@ int t4_init_tp_params(struct adapter *adap)
 	adap->params.tp.macmatch_shift = t4_filter_field_shift(adap,
 							       F_MACMATCH);
 
-	/*
-	 * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
-	 * represents the presense of an Outer VLAN instead of a VNIC ID.
-	 */
-	if ((adap->params.tp.ingress_config & F_VNIC) == 0)
-		adap->params.tp.vnic_shift = -1;
-
 	v = t4_read_reg(adap, LE_3_DB_HASH_MASK_GEN_IPV4_T6_A);
 	adap->params.tp.hash_filter_mask = v;
 	v = t4_read_reg(adap, LE_4_DB_HASH_MASK_GEN_IPV4_T6_A);
diff --git a/drivers/net/cxgbe/base/t4_regs.h b/drivers/net/cxgbe/base/t4_regs.h
index af8c741e2..97cf49a48 100644
--- a/drivers/net/cxgbe/base/t4_regs.h
+++ b/drivers/net/cxgbe/base/t4_regs.h
@@ -572,6 +572,10 @@
 
 #define A_TP_INGRESS_CONFIG 0x141
 
+#define S_USE_ENC_IDX    13
+#define V_USE_ENC_IDX(x) ((x) << S_USE_ENC_IDX)
+#define F_USE_ENC_IDX    V_USE_ENC_IDX(1U)
+
 #define S_VNIC    11
 #define V_VNIC(x) ((x) << S_VNIC)
 #define F_VNIC    V_VNIC(1U)
diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c
index b9d9d5d39..d26be3cd7 100644
--- a/drivers/net/cxgbe/cxgbe_filter.c
+++ b/drivers/net/cxgbe/cxgbe_filter.c
@@ -56,13 +56,15 @@ int cxgbe_init_hash_filter(struct adapter *adap)
 int cxgbe_validate_filter(struct adapter *adapter,
 			  struct ch_filter_specification *fs)
 {
-	u32 fconf;
+	u32 fconf, iconf;
 
 	/*
 	 * Check for unconfigured fields being used.
 	 */
 	fconf = adapter->params.tp.vlan_pri_map;
 
+	iconf = adapter->params.tp.ingress_config;
+
 #define S(_field) \
 	(fs->val._field || fs->mask._field)
 #define U(_mask, _field) \
@@ -70,7 +72,15 @@ int cxgbe_validate_filter(struct adapter *adapter,
 
 	if (U(F_PORT, iport) || U(F_ETHERTYPE, ethtype) ||
 	    U(F_PROTOCOL, proto) || U(F_MACMATCH, macidx) ||
-	    U(F_VLAN, ivlan_vld))
+	    U(F_VLAN, ivlan_vld) || U(F_VNIC_ID, ovlan_vld))
+		return -EOPNOTSUPP;
+
+	/* Ensure OVLAN match is enabled in hardware */
+	if (S(ovlan_vld) && (iconf & F_VNIC))
+		return -EOPNOTSUPP;
+
+	/* To use OVLAN, L4 encapsulation match must not be enabled */
+	if (S(ovlan_vld) && (iconf & F_USE_ENC_IDX))
 		return -EOPNOTSUPP;
 
 #undef S
@@ -296,6 +306,12 @@ static u64 hash_filter_ntuple(const struct filter_entry *f)
 	if (tp->vlan_shift >= 0 && f->fs.mask.ivlan)
 		ntuple |= (u64)(F_FT_VLAN_VLD | f->fs.val.ivlan) <<
 			  tp->vlan_shift;
+	if (tp->vnic_shift >= 0) {
+		if (!(adap->params.tp.ingress_config & F_VNIC) &&
+		    f->fs.mask.ovlan_vld)
+			ntuple |= (u64)(f->fs.val.ovlan_vld << 16 |
+					f->fs.val.ovlan) << tp->vnic_shift;
+	}
 
 	return ntuple;
 }
@@ -775,7 +791,9 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
 	fwr->ethtypem = cpu_to_be16(f->fs.mask.ethtype);
 	fwr->frag_to_ovlan_vldm =
 		(V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) |
-		 V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld));
+		 V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) |
+		 V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) |
+		 V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));
 	fwr->smac_sel = 0;
 	fwr->rx_chan_rx_rpl_iq =
 		cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |
@@ -790,6 +808,8 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
 	fwr->ptclm = f->fs.mask.proto;
 	fwr->ivlan = cpu_to_be16(f->fs.val.ivlan);
 	fwr->ivlanm = cpu_to_be16(f->fs.mask.ivlan);
+	fwr->ovlan = cpu_to_be16(f->fs.val.ovlan);
+	fwr->ovlanm = cpu_to_be16(f->fs.mask.ovlan);
 	rte_memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip));
 	rte_memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm));
 	rte_memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip));
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index 9070f4960..cd833d095 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -87,6 +87,15 @@ cxgbe_tweak_filter_spec(struct adapter *adap,
 				fs->mask.ethtype = 0;
 			}
 			break;
+		case RTE_ETHER_TYPE_QINQ:
+			if (adap->params.tp.ethertype_shift < 0 &&
+			    adap->params.tp.vnic_shift >= 0) {
+				fs->val.ovlan_vld = 1;
+				fs->mask.ovlan_vld = 1;
+				fs->val.ethtype = 0;
+				fs->mask.ethtype = 0;
+			}
+			break;
 		default:
 			break;
 		}
@@ -145,6 +154,9 @@ cxgbe_fill_filter_region(struct adapter *adap,
 	if (tp->vlan_shift >= 0 && fs->mask.ivlan_vld)
 		ntuple_mask |= (u64)(F_FT_VLAN_VLD | fs->mask.ivlan) <<
 			       tp->vlan_shift;
+	if (tp->vnic_shift >= 0 && fs->mask.ovlan_vld)
+		ntuple_mask |= (u64)(F_FT_VLAN_VLD | fs->mask.ovlan) <<
+			       tp->vnic_shift;
 
 	if (ntuple_mask != hash_filter_mask)
 		return;
@@ -167,22 +179,6 @@ ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
 	if (!spec)
 		return 0;
 
-	/* Chelsio hardware supports matching on only one ethertype
-	 * (i.e. either the outer or inner ethertype, but not both). If
-	 * we already encountered VLAN item, then ensure that the outer
-	 * ethertype is VLAN (0x8100) and don't overwrite the inner
-	 * ethertype stored during VLAN item parsing. Note that if
-	 * 'ivlan_vld' bit is set in Chelsio filter spec, then the
-	 * hardware automatically only matches packets with outer
-	 * ethertype having VLAN (0x8100).
-	 */
-	if (fs->mask.ivlan_vld &&
-	    be16_to_cpu(spec->type) != RTE_ETHER_TYPE_VLAN)
-		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
-					  item,
-					  "Already encountered VLAN item,"
-					  " but outer ethertype is not 0x8100");
-
 	/* we don't support SRC_MAC filtering*/
 	if (!rte_is_zero_ether_addr(&mask->src))
 		return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
@@ -206,13 +202,9 @@ ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
 		CXGBE_FILL_FS(idx, 0x1ff, macidx);
 	}
 
-	/* Only set outer ethertype, if we didn't encounter VLAN item yet.
-	 * Otherwise, the inner ethertype set by VLAN item will get
-	 * overwritten.
-	 */
-	if (!fs->mask.ivlan_vld)
-		CXGBE_FILL_FS(be16_to_cpu(spec->type),
-			      be16_to_cpu(mask->type), ethtype);
+	CXGBE_FILL_FS(be16_to_cpu(spec->type),
+		      be16_to_cpu(mask->type), ethtype);
+
 	return 0;
 }
 
@@ -249,32 +241,48 @@ ch_rte_parsetype_vlan(const void *dmask, const struct rte_flow_item *item,
 	/* If user has not given any mask, then use chelsio supported mask. */
 	mask = umask ? umask : (const struct rte_flow_item_vlan *)dmask;
 
-	CXGBE_FILL_FS(1, 1, ivlan_vld);
-	if (!spec)
-		return 0; /* Wildcard, match all VLAN */
-
-	/* Chelsio hardware supports matching on only one ethertype
-	 * (i.e. either the outer or inner ethertype, but not both).
-	 * If outer ethertype is already set and is not VLAN (0x8100),
-	 * then don't proceed further. Otherwise, reset the outer
-	 * ethertype, so that it can be replaced by inner ethertype.
-	 * Note that the hardware will automatically match on outer
-	 * ethertype 0x8100, if 'ivlan_vld' bit is set in Chelsio
-	 * filter spec.
+	if (!fs->mask.ethtype)
+		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+					  item,
+					  "Can't parse VLAN item without knowing ethertype");
+
+	/* If ethertype is already set and is not VLAN (0x8100) or
+	 * QINQ(0x88A8), then don't proceed further. Otherwise,
+	 * reset the outer ethertype, so that it can be replaced by
+	 * innermost ethertype. Note that hardware will automatically
+	 * match against VLAN or QINQ packets, based on 'ivlan_vld' or
+	 * 'ovlan_vld' bit set in Chelsio filter spec, respectively.
 	 */
 	if (fs->mask.ethtype) {
-		if (fs->val.ethtype != RTE_ETHER_TYPE_VLAN)
+		if (fs->val.ethtype != RTE_ETHER_TYPE_VLAN &&
+		    fs->val.ethtype != RTE_ETHER_TYPE_QINQ)
 			return rte_flow_error_set(e, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  item,
-						  "Outer ethertype not 0x8100");
+						  "Ethertype must be 0x8100 or 0x88a8");
+	}
 
-		fs->val.ethtype = 0;
-		fs->mask.ethtype = 0;
+	if (fs->val.ethtype == RTE_ETHER_TYPE_QINQ) {
+		CXGBE_FILL_FS(1, 1, ovlan_vld);
+		if (spec) {
+			CXGBE_FILL_FS(be16_to_cpu(spec->tci),
+				      be16_to_cpu(mask->tci), ovlan);
+
+			fs->mask.ethtype = 0;
+			fs->val.ethtype = 0;
+		}
+	} else if (fs->val.ethtype == RTE_ETHER_TYPE_VLAN) {
+		CXGBE_FILL_FS(1, 1, ivlan_vld);
+		if (spec) {
+			CXGBE_FILL_FS(be16_to_cpu(spec->tci),
+				      be16_to_cpu(mask->tci), ivlan);
+
+			fs->mask.ethtype = 0;
+			fs->val.ethtype = 0;
+		}
 	}
 
-	CXGBE_FILL_FS(be16_to_cpu(spec->tci), be16_to_cpu(mask->tci), ivlan);
-	if (spec->inner_type)
+	if (spec)
 		CXGBE_FILL_FS(be16_to_cpu(spec->inner_type),
 			      be16_to_cpu(mask->inner_type), ethtype);
 
@@ -351,8 +359,7 @@ ch_rte_parsetype_ipv4(const void *dmask, const struct rte_flow_item *item,
 					  item, "ttl/tos are not supported");
 
 	if (fs->mask.ethtype &&
-	    (fs->val.ethtype != RTE_ETHER_TYPE_VLAN &&
-	     fs->val.ethtype != RTE_ETHER_TYPE_IPV4))
+	    (fs->val.ethtype != RTE_ETHER_TYPE_IPV4))
 		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
 					  item,
 					  "Couldn't find IPv4 ethertype");
@@ -385,8 +392,7 @@ ch_rte_parsetype_ipv6(const void *dmask, const struct rte_flow_item *item,
 					  "tc/flow/hop are not supported");
 
 	if (fs->mask.ethtype &&
-	    (fs->val.ethtype != RTE_ETHER_TYPE_VLAN &&
-	     fs->val.ethtype != RTE_ETHER_TYPE_IPV6))
+	    (fs->val.ethtype != RTE_ETHER_TYPE_IPV6))
 		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
 					  item,
 					  "Couldn't find IPv6 ethertype");
@@ -907,10 +913,12 @@ cxgbe_rtef_parse_items(struct rte_flow *flow,
 			continue;
 		default:
 			/* check if item is repeated */
-			if (repeat[i->type])
+			if (repeat[i->type] &&
+			    i->type != RTE_FLOW_ITEM_TYPE_VLAN)
 				return rte_flow_error_set(e, ENOTSUP,
 						RTE_FLOW_ERROR_TYPE_ITEM, i,
-						"parse items cannot be repeated (except void)");
+						"parse items cannot be repeated(except void/vlan)");
+
 			repeat[i->type] = 1;
 
 			/* No spec found for this pattern item. Skip it */
-- 
2.25.0


  reply	other threads:[~2020-03-11  9:16 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-11  9:05 [dpdk-dev] [PATCH 0/9] net/cxgbe: updates for rte_flow support Rahul Lakkireddy
2020-03-11  9:05 ` Rahul Lakkireddy [this message]
2020-03-11  9:05 ` [dpdk-dev] [PATCH 2/9] net/cxgbe: add rte_flow support for matching IP TOS Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 3/9] net/cxgbe: add rte_flow support for matching all packets on PF Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 4/9] net/cxgbe: add rte_flow support for matching all packets on VF Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 5/9] net/cxgbe: add rte_flow support for overwriting destination MAC Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 6/9] net/cxgbe: add Source MAC Table (SMT) support Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 7/9] net/cxgbe: add rte_flow support for Source MAC Rewrite Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 8/9] net/cxgbe: use firmware API for validating filter spec Rahul Lakkireddy
2020-03-11  9:05 ` [dpdk-dev] [PATCH 9/9] net/cxgbe: add devargs to control filtermode and filtermask values Rahul Lakkireddy
2020-03-11 13:11 ` [dpdk-dev] [PATCH 0/9] net/cxgbe: updates for rte_flow support Ferruh Yigit
2020-03-18 12:09 ` Thomas Monjalon
2020-03-18 13:06   ` Rahul Lakkireddy
2020-03-18 15:07     ` Thomas Monjalon
2020-03-19  7:58       ` Rahul Lakkireddy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=67a7f133daaa4dae254208bc86c9c2b999688715.1583906144.git.kaara.satwik@chelsio.com \
    --to=rahul.lakkireddy@chelsio.com \
    --cc=dev@dpdk.org \
    --cc=kaara.satwik@chelsio.com \
    --cc=nirranjan@chelsio.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).