DPDK patches and discussions
 help / color / mirror / Atom feed
From: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
To: dev@dpdk.org
Cc: nirranjan@chelsio.com
Subject: [dpdk-dev] [PATCH 11/12] net/cxgbe: add rte_flow support for matching VLAN
Date: Sat,  7 Sep 2019 03:22:32 +0530	[thread overview]
Message-ID: <6002c525615f002dcbca9560463d3fc2f687bed3.1567799552.git.rahul.lakkireddy@chelsio.com> (raw)
In-Reply-To: <cover.1567799552.git.rahul.lakkireddy@chelsio.com>
In-Reply-To: <cover.1567799552.git.rahul.lakkireddy@chelsio.com>

Add support for matching VLAN fields via rte_flow API.

When matching VLAN pattern, the ethertype field in hardware
filter specification must contain VLAN header's ethertype, and
not Ethernet header's ethertype. The hardware automatically
searches for ethertype 0x8100 in Ethernet header, when
parsing incoming packet against VLAN pattern.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
---
 drivers/net/cxgbe/base/t4_regs_values.h |   9 ++
 drivers/net/cxgbe/cxgbe_filter.c        |  11 +-
 drivers/net/cxgbe/cxgbe_flow.c          | 145 +++++++++++++++++++++++-
 drivers/net/cxgbe/cxgbe_main.c          |  10 +-
 4 files changed, 162 insertions(+), 13 deletions(-)

diff --git a/drivers/net/cxgbe/base/t4_regs_values.h b/drivers/net/cxgbe/base/t4_regs_values.h
index a9414d202..e3f549e51 100644
--- a/drivers/net/cxgbe/base/t4_regs_values.h
+++ b/drivers/net/cxgbe/base/t4_regs_values.h
@@ -143,4 +143,13 @@
 #define W_FT_MPSHITTYPE			3
 #define W_FT_FRAGMENTATION		1
 
+/*
+ * Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD			16
+#define V_FT_VLAN_VLD(x)		((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD			V_FT_VLAN_VLD(1U)
+
 #endif /* __T4_REGS_VALUES_H__ */
diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c
index 33b95a69a..b9d9d5d39 100644
--- a/drivers/net/cxgbe/cxgbe_filter.c
+++ b/drivers/net/cxgbe/cxgbe_filter.c
@@ -69,7 +69,8 @@ int cxgbe_validate_filter(struct adapter *adapter,
 	(!(fconf & (_mask)) && S(_field))
 
 	if (U(F_PORT, iport) || U(F_ETHERTYPE, ethtype) ||
-	    U(F_PROTOCOL, proto) || U(F_MACMATCH, macidx))
+	    U(F_PROTOCOL, proto) || U(F_MACMATCH, macidx) ||
+	    U(F_VLAN, ivlan_vld))
 		return -EOPNOTSUPP;
 
 #undef S
@@ -292,6 +293,9 @@ static u64 hash_filter_ntuple(const struct filter_entry *f)
 		ntuple |= (u64)(f->fs.val.ethtype) << tp->ethertype_shift;
 	if (tp->macmatch_shift >= 0 && f->fs.mask.macidx)
 		ntuple |= (u64)(f->fs.val.macidx) << tp->macmatch_shift;
+	if (tp->vlan_shift >= 0 && f->fs.mask.ivlan)
+		ntuple |= (u64)(F_FT_VLAN_VLD | f->fs.val.ivlan) <<
+			  tp->vlan_shift;
 
 	return ntuple;
 }
@@ -769,6 +773,9 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
 			    V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
 	fwr->ethtype = cpu_to_be16(f->fs.val.ethtype);
 	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));
 	fwr->smac_sel = 0;
 	fwr->rx_chan_rx_rpl_iq =
 		cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) |
@@ -781,6 +788,8 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
 			    V_FW_FILTER_WR_PORTM(f->fs.mask.iport));
 	fwr->ptcl = f->fs.val.proto;
 	fwr->ptclm = f->fs.mask.proto;
+	fwr->ivlan = cpu_to_be16(f->fs.val.ivlan);
+	fwr->ivlanm = cpu_to_be16(f->fs.mask.ivlan);
 	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 4c8553039..4b72e6422 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -46,6 +46,53 @@ cxgbe_validate_item(const struct rte_flow_item *i, struct rte_flow_error *e)
 	return 0;
 }
 
+/**
+ * Apart from the 4-tuple IPv4/IPv6 - TCP/UDP information,
+ * there's only 40-bits available to store match fields.
+ * So, to save space, optimize filter spec for some common
+ * known fields that hardware can parse against incoming
+ * packets automatically.
+ */
+static void
+cxgbe_tweak_filter_spec(struct adapter *adap,
+			struct ch_filter_specification *fs)
+{
+	/* Save 16-bit ethertype field space, by setting corresponding
+	 * 1-bit flags in the filter spec for common known ethertypes.
+	 * When hardware sees these flags, it automatically infers and
+	 * matches incoming packets against the corresponding ethertype.
+	 */
+	if (fs->mask.ethtype == 0xffff) {
+		switch (fs->val.ethtype) {
+		case RTE_ETHER_TYPE_IPV4:
+			if (adap->params.tp.ethertype_shift < 0) {
+				fs->type = FILTER_TYPE_IPV4;
+				fs->val.ethtype = 0;
+				fs->mask.ethtype = 0;
+			}
+			break;
+		case RTE_ETHER_TYPE_IPV6:
+			if (adap->params.tp.ethertype_shift < 0) {
+				fs->type = FILTER_TYPE_IPV6;
+				fs->val.ethtype = 0;
+				fs->mask.ethtype = 0;
+			}
+			break;
+		case RTE_ETHER_TYPE_VLAN:
+			if (adap->params.tp.ethertype_shift < 0 &&
+			    adap->params.tp.vlan_shift >= 0) {
+				fs->val.ivlan_vld = 1;
+				fs->mask.ivlan_vld = 1;
+				fs->val.ethtype = 0;
+				fs->mask.ethtype = 0;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 static void
 cxgbe_fill_filter_region(struct adapter *adap,
 			 struct ch_filter_specification *fs)
@@ -95,6 +142,9 @@ cxgbe_fill_filter_region(struct adapter *adap,
 		ntuple_mask |= (u64)fs->mask.iport << tp->port_shift;
 	if (tp->macmatch_shift >= 0)
 		ntuple_mask |= (u64)fs->mask.macidx << tp->macmatch_shift;
+	if (tp->vlan_shift >= 0 && fs->mask.ivlan_vld)
+		ntuple_mask |= (u64)(F_FT_VLAN_VLD | fs->mask.ivlan) <<
+			       tp->vlan_shift;
 
 	if (ntuple_mask != hash_filter_mask)
 		return;
@@ -114,6 +164,25 @@ ch_rte_parsetype_eth(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_eth *)dmask;
 
+	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,
@@ -137,8 +206,13 @@ ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
 		CXGBE_FILL_FS(idx, 0x1ff, macidx);
 	}
 
-	CXGBE_FILL_FS(be16_to_cpu(spec->type),
-		      be16_to_cpu(mask->type), ethtype);
+	/* 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);
 	return 0;
 }
 
@@ -163,6 +237,50 @@ ch_rte_parsetype_port(const void *dmask, const struct rte_flow_item *item,
 	return 0;
 }
 
+static int
+ch_rte_parsetype_vlan(const void *dmask, const struct rte_flow_item *item,
+		      struct ch_filter_specification *fs,
+		      struct rte_flow_error *e)
+{
+	const struct rte_flow_item_vlan *spec = item->spec;
+	const struct rte_flow_item_vlan *umask = item->mask;
+	const struct rte_flow_item_vlan *mask;
+
+	/* 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) {
+		if (fs->val.ethtype != RTE_ETHER_TYPE_VLAN)
+			return rte_flow_error_set(e, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  item,
+						  "Outer ethertype not 0x8100");
+
+		fs->val.ethtype = 0;
+		fs->mask.ethtype = 0;
+	}
+
+	CXGBE_FILL_FS(be16_to_cpu(spec->tci), be16_to_cpu(mask->tci), ivlan);
+	if (spec->inner_type)
+		CXGBE_FILL_FS(be16_to_cpu(spec->inner_type),
+			      be16_to_cpu(mask->inner_type), ethtype);
+
+	return 0;
+}
+
 static int
 ch_rte_parsetype_udp(const void *dmask, const struct rte_flow_item *item,
 		     struct ch_filter_specification *fs,
@@ -232,8 +350,13 @@ ch_rte_parsetype_ipv4(const void *dmask, const struct rte_flow_item *item,
 		return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_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))
+		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+					  item,
+					  "Couldn't find IPv4 ethertype");
 	fs->type = FILTER_TYPE_IPV4;
-	CXGBE_FILL_FS(RTE_ETHER_TYPE_IPV4, 0xffff, ethtype);
 	if (!val)
 		return 0; /* ipv4 wild card */
 
@@ -261,8 +384,13 @@ ch_rte_parsetype_ipv6(const void *dmask, const struct rte_flow_item *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))
+		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+					  item,
+					  "Couldn't find IPv6 ethertype");
 	fs->type = FILTER_TYPE_IPV6;
-	CXGBE_FILL_FS(RTE_ETHER_TYPE_IPV6, 0xffff, ethtype);
 	if (!val)
 		return 0; /* ipv6 wild card */
 
@@ -700,6 +828,14 @@ static struct chrte_fparse parseitem[] = {
 		}
 	},
 
+	[RTE_FLOW_ITEM_TYPE_VLAN] = {
+		.fptr = ch_rte_parsetype_vlan,
+		.dmask = &(const struct rte_flow_item_vlan){
+			.tci = 0xffff,
+			.inner_type = 0xffff,
+		}
+	},
+
 	[RTE_FLOW_ITEM_TYPE_IPV4] = {
 		.fptr  = ch_rte_parsetype_ipv4,
 		.dmask = &rte_flow_item_ipv4_mask,
@@ -773,6 +909,7 @@ cxgbe_rtef_parse_items(struct rte_flow *flow,
 	}
 
 	cxgbe_fill_filter_region(adap, &flow->fs);
+	cxgbe_tweak_filter_spec(adap, &flow->fs);
 
 	return 0;
 }
diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c
index 4701518a6..f6967a3e4 100644
--- a/drivers/net/cxgbe/cxgbe_main.c
+++ b/drivers/net/cxgbe/cxgbe_main.c
@@ -753,12 +753,6 @@ static void configure_vlan_types(struct adapter *adapter)
 				 V_OVLAN_ETYPE(M_OVLAN_ETYPE),
 				 V_OVLAN_MASK(M_OVLAN_MASK) |
 				 V_OVLAN_ETYPE(0x9100));
-		/* OVLAN Type 0x8100 */
-		t4_set_reg_field(adapter, MPS_PORT_RX_OVLAN_REG(i, A_RX_OVLAN2),
-				 V_OVLAN_MASK(M_OVLAN_MASK) |
-				 V_OVLAN_ETYPE(M_OVLAN_ETYPE),
-				 V_OVLAN_MASK(M_OVLAN_MASK) |
-				 V_OVLAN_ETYPE(0x8100));
 
 		/* IVLAN 0X8100 */
 		t4_set_reg_field(adapter, MPS_PORT_RX_IVLAN(i),
@@ -767,9 +761,9 @@ static void configure_vlan_types(struct adapter *adapter)
 
 		t4_set_reg_field(adapter, MPS_PORT_RX_CTL(i),
 				 F_OVLAN_EN0 | F_OVLAN_EN1 |
-				 F_OVLAN_EN2 | F_IVLAN_EN,
+				 F_IVLAN_EN,
 				 F_OVLAN_EN0 | F_OVLAN_EN1 |
-				 F_OVLAN_EN2 | F_IVLAN_EN);
+				 F_IVLAN_EN);
 	}
 
 	t4_tp_wr_bits_indirect(adapter, A_TP_INGRESS_CONFIG, V_RM_OVLAN(1),
-- 
2.18.0


  parent reply	other threads:[~2019-09-06 22:01 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-06 21:52 [dpdk-dev] [PATCH 00/12] net/cxgbe: bug fixes and updates for CXGBE/CXGBEVF PMD Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 01/12] net/cxgbe: add cxgbe_ prefix to global functions Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 02/12] net/cxgbe: fix NULL access when allocating CLIP entry Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 03/12] net/cxgbe: fix slot allocation for IPv6 flows Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 04/12] net/cxgbe: fix parsing VLAN ID rewrite action Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 05/12] net/cxgbe: fix prefetch for non-coalesced Tx packets Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 06/12] net/cxgbe: avoid polling link status before device start Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 07/12] net/cxgbe: use dynamic logging for debug prints Rahul Lakkireddy
2019-09-27 14:37   ` Ferruh Yigit
2019-09-27 19:55     ` Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 08/12] net/cxgbe: separate VF only devargs Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 09/12] net/cxgbe: add devarg to control Tx coalescing Rahul Lakkireddy
2019-09-06 21:52 ` [dpdk-dev] [PATCH 10/12] net/cxgbe: fetch max Tx coalesce limit from firmware Rahul Lakkireddy
2019-09-06 21:52 ` Rahul Lakkireddy [this message]
2019-09-06 21:52 ` [dpdk-dev] [PATCH 12/12] net/cxgbe: add rte_flow support for setting VLAN PCP Rahul Lakkireddy
2019-09-27 14:41 ` [dpdk-dev] [PATCH 00/12] net/cxgbe: bug fixes and updates for CXGBE/CXGBEVF PMD Ferruh Yigit
2019-09-27 20:30 ` [dpdk-dev] [PATCH v2 " Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 01/12] net/cxgbe: add cxgbe_ prefix to global functions Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 02/12] net/cxgbe: fix NULL access when allocating CLIP entry Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 03/12] net/cxgbe: fix slot allocation for IPv6 flows Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 04/12] net/cxgbe: fix parsing VLAN ID rewrite action Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 05/12] net/cxgbe: fix prefetch for non-coalesced Tx packets Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 06/12] net/cxgbe: avoid polling link status before device start Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 07/12] net/cxgbe: use dynamic logging for debug prints Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 08/12] net/cxgbe: separate VF only devargs Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 09/12] net/cxgbe: add devarg to control Tx coalescing Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 10/12] net/cxgbe: fetch max Tx coalesce limit from firmware Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 11/12] net/cxgbe: add rte_flow support for matching VLAN Rahul Lakkireddy
2019-09-27 20:30   ` [dpdk-dev] [PATCH v2 12/12] net/cxgbe: add rte_flow support for setting VLAN PCP Rahul Lakkireddy
2019-09-30 12:34   ` [dpdk-dev] [PATCH v2 00/12] net/cxgbe: bug fixes and updates for CXGBE/CXGBEVF PMD Ferruh Yigit

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=6002c525615f002dcbca9560463d3fc2f687bed3.1567799552.git.rahul.lakkireddy@chelsio.com \
    --to=rahul.lakkireddy@chelsio.com \
    --cc=dev@dpdk.org \
    --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).