All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] enable MPLS cloud filter
@ 2017-03-03  9:43 Beilei Xing
  2017-03-03  9:43 ` [PATCH 1/3] app/testpmd: support MPLS for generic filter Beilei Xing
                   ` (3 more replies)
  0 siblings, 4 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-03  9:43 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patchset enables MPLSoUDP & MPLSoGRE
cloud filter.
This function depends on PPP function and
replace filter AQ command.

Beilei Xing (3):
  app/testpmd: support MPLS for generic filter
  net/i40e: add MPLS parsing function
  net/i40e: enable cloud filter for MPLS

 app/test-pmd/cmdline_flow.c    |  55 ++++++++
 app/test-pmd/config.c          |   2 +
 drivers/net/i40e/i40e_ethdev.c |  44 +++++-
 drivers/net/i40e/i40e_ethdev.h |  10 ++
 drivers/net/i40e/i40e_flow.c   | 305 +++++++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h    |  40 ++++++
 6 files changed, 451 insertions(+), 5 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH 1/3] app/testpmd: support MPLS for generic filter
  2017-03-03  9:43 [PATCH 0/3] enable MPLS cloud filter Beilei Xing
@ 2017-03-03  9:43 ` Beilei Xing
  2017-03-03 11:09   ` Adrien Mazarguil
  2017-03-03  9:43 ` [PATCH 2/3] net/i40e: add MPLS parsing function Beilei Xing
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-03  9:43 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch adds MPLS support for generic filter
API.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 app/test-pmd/cmdline_flow.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c       |  2 ++
 lib/librte_ether/rte_flow.h | 40 +++++++++++++++++++++++++++++++++
 3 files changed, 97 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ff98690..241bda1 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -159,6 +159,11 @@ enum index {
 	ITEM_SCTP_CKSUM,
 	ITEM_VXLAN,
 	ITEM_VXLAN_VNI,
+	ITEM_MPLS,
+	ITEM_MPLS_LABEL,
+	ITEM_GRE,
+	ITEM_GRE_FLAGS,
+	ITEM_GRE_PROTO,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -432,6 +437,8 @@ static const enum index next_item[] = {
 	ITEM_TCP,
 	ITEM_SCTP,
 	ITEM_VXLAN,
+	ITEM_MPLS,
+	ITEM_GRE,
 	ZERO,
 };
 
@@ -538,6 +545,19 @@ static const enum index item_vxlan[] = {
 	ZERO,
 };
 
+static const enum index item_mpls[] = {
+	ITEM_MPLS_LABEL,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_gre[] = {
+	ITEM_GRE_FLAGS,
+	ITEM_GRE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1279,6 +1299,41 @@ static const struct token token_list[] = {
 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
 	},
+	[ITEM_MPLS] = {
+		.name = "mpls",
+		.help = "match MPLS header",
+		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+		.next = NEXT(item_mpls),
+		.call = parse_vc,
+	},
+	[ITEM_MPLS_LABEL] = {
+		.name = "label",
+		.help = "MPLS label",
+		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls,
+					     label_tc_s_ttl)),
+	},
+	[ITEM_GRE] = {
+		.name = "gre",
+		.help = "match GRE header",
+		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+		.next = NEXT(item_gre),
+		.call = parse_vc,
+	},
+	[ITEM_GRE_FLAGS] = {
+		.name = "c_rsvd0_ver",
+		.help = "GRE c_rsvd0_ver",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     c_rsvd0_ver)),
+	},
+	[ITEM_GRE_PROTO] = {
+		.name = "protocol",
+		.help = "GRE protocol type",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     protocol)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 80491fc..c042765 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -963,6 +963,8 @@ static const struct {
 	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
 	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
 	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 171a569..c845953 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -282,6 +282,20 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_nvgre.
 	 */
 	RTE_FLOW_ITEM_TYPE_NVGRE,
+
+	/**
+	 * Matches a MPLS header.
+	 *
+	 * See struct rte_flow_item_mpls.
+	 */
+	RTE_FLOW_ITEM_TYPE_MPLS,
+
+	/**
+	 * Matches a GRE header.
+	 *
+	 * See struct rte_flow_item_gre.
+	 */
+	RTE_FLOW_ITEM_TYPE_GRE,
 };
 
 /**
@@ -599,6 +613,32 @@ struct rte_flow_item_nvgre {
 };
 
 /**
+ * RTE_FLOW_ITEM_TYPE_MPLS.
+ *
+ * Matches a MPLS header.
+ */
+	struct rte_flow_item_mpls {
+		/**
+		 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
+		 */
+		uint32_t label_tc_s_ttl;
+	};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_GRE.
+ *
+ * Matches a GRE header.
+ */
+struct rte_flow_item_gre {
+	/**
+	 * Checksum (1b), reserved 0 (12b), version (3b).
+	 * Refer to RFC 2784.
+	 */
+	uint16_t c_rsvd0_ver;
+	uint16_t protocol; /**< Protocol type. */
+};
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 2/3] net/i40e: add MPLS parsing function
  2017-03-03  9:43 [PATCH 0/3] enable MPLS cloud filter Beilei Xing
  2017-03-03  9:43 ` [PATCH 1/3] app/testpmd: support MPLS for generic filter Beilei Xing
@ 2017-03-03  9:43 ` Beilei Xing
  2017-03-03  9:43 ` [PATCH 3/3] net/i40e: enable cloud filter for MPLS Beilei Xing
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
  3 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-03  9:43 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch adds MPLS parsing function to support
MPLSoUDP & MPLSoGRE cloud filter.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |   5 +
 drivers/net/i40e/i40e_flow.c   | 217 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 222 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 3e9b129..dd9d709 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -499,6 +499,9 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
+
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
 	I40E_TUNNEL_IPTYPE_IPV6,
@@ -541,6 +544,8 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_MPLSoUDP,
+	I40E_TUNNEL_TYPE_MPLSoGRE,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 3e8c63a..9ca3189 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -57,6 +57,7 @@
 #define I40E_IPV6_FRAG_HEADER	44
 #define I40E_TENANT_ARRAY_NUM	3
 #define I40E_TCI_MASK		0xFFFF
+#define I40E_MPLS_LABEL_MASK	0xFFFFF
 
 static int i40e_flow_validate(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -114,6 +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 					const struct rte_flow_action actions[],
 					struct rte_flow_error *error,
 					union i40e_filter_t *filter);
+static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+				       const struct rte_flow_attr *attr,
+				       const struct rte_flow_item pattern[],
+				       const struct rte_flow_action actions[],
+				       struct rte_flow_error *error,
+				       union i40e_filter_t *filter);
 static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
 				      struct i40e_ethertype_filter *filter);
 static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
@@ -278,6 +285,39 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched MPLS */
+static enum rte_flow_item_type pattern_mpls_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
+	/* MPLSoUDP & MPLSoGRE */
+	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1515,6 +1560,166 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 	return ret;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: MPLS label.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
+			     const struct rte_flow_item *pattern,
+			     struct rte_flow_error *error,
+			     struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item *item = pattern;
+	const struct rte_flow_item_mpls *mpls_spec;
+	const struct rte_flow_item_mpls *mpls_mask;
+	enum rte_flow_item_type item_type;
+	bool is_mplsoudp; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
+	uint32_t mpls_cpu;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = RTE_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = RTE_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			/* UDP is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid UDP item");
+				return -rte_errno;
+			}
+			is_mplsoudp = 1;
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			/* GRE is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid GRE item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			mpls_spec =
+				(const struct rte_flow_item_mpls *)item->spec;
+			mpls_mask =
+				(const struct rte_flow_item_mpls *)item->mask;
+
+			if (!mpls_spec || !mpls_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid VXLAN item");
+				return -rte_errno;
+			}
+
+			if ((mpls_mask->label_tc_s_ttl &
+			     rte_cpu_to_be_32(I40E_MPLS_LABEL_MASK)) !=
+			    rte_cpu_to_be_32(I40E_MPLS_LABEL_MASK)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid VXLAN mask");
+				return -rte_errno;
+			}
+
+			mpls_cpu = rte_be_to_cpu_32(mpls_spec->label_tc_s_ttl);
+			filter->tenant_id = mpls_cpu & I40E_MPLS_LABEL_MASK;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (is_mplsoudp)
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
+	else
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error,
+			    union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
+					   error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
@@ -1748,6 +1953,18 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
+	if (((filter->input.flags &
+	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
+	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
+	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
+	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
+	    ((filter->input.flags &
+	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
+	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
+	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
+	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
+		big_buffer = 1;
+
 	if (big_buffer)
 		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
 							      &cld_filter, 1);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-03  9:43 [PATCH 0/3] enable MPLS cloud filter Beilei Xing
  2017-03-03  9:43 ` [PATCH 1/3] app/testpmd: support MPLS for generic filter Beilei Xing
  2017-03-03  9:43 ` [PATCH 2/3] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-03  9:43 ` Beilei Xing
  2017-03-08 16:05   ` Ferruh Yigit
  2017-03-09 11:13   ` Iremonger, Bernard
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
  3 siblings, 2 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-03  9:43 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch enables MPLSoUDP and MPLSoGRE
cloud filter with replace cloud filter.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |   9 +++-
 drivers/net/i40e/i40e_flow.c   | 108 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 144 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 91bfd73..6044daf 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	i40e_replace_mpls_l1_filter(pf);
+	i40e_replace_mpls_cloud_filter(pf);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -6941,6 +6944,7 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *tunnel, *node;
 	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+	uint32_t teid_le;
 	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
@@ -6989,6 +6993,28 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	case I40E_TUNNEL_TYPE_IP_IN_GRE:
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
 		break;
+	case I40E_TUNNEL_TYPE_MPLSoUDP:
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x40;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+		break;
+	case I40E_TUNNEL_TYPE_MPLSoGRE:
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x0;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		return -EINVAL;
 	}
 
-	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-				       &pfilter->element.flags);
-	if (val < 0) {
-		rte_free(cld_filter);
-		return -EINVAL;
+	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else {
+		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+						&pfilter->element.flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
 	}
 
 	pfilter->element.flags |= rte_cpu_to_le_16(
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index dd9d709..f305baa 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
 
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
@@ -963,6 +966,8 @@ enum i40e_status_code i40e_aq_remove_cloud_filters_big_buffer(
 enum i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
 		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
 		    struct i40e_aqc_replace_cloud_filters_cmd_buf *cmd_buf);
+int i40e_replace_mpls_l1_filter(struct i40e_pf *pf);
+int i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 9ca3189..6bb2046 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
-	if (((filter->input.flags &
-	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
-	    ((filter->input.flags &
-	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
+	if ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
+	    (filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
 		big_buffer = 1;
 
 	if (big_buffer)
@@ -2255,3 +2249,97 @@ i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
 
 	return status;
 }
+
+int
+i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	int ret;
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	filter_replace.old_filter_type =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+	filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace.tr_bit = 0xFF;
+
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0xff;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[7] = 0xf0;
+	filter_replace_buf.data[8] = 0x48;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[10] = 0x4c;
+	filter_replace_buf.data[11] = 0x8c;
+
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					    &filter_replace_buf);
+	return ret;
+}
+
+int
+i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+	int ret;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+
+	/* For MPLSoUDP */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					    &filter_replace_buf);
+	if (ret < 0)
+		return ret;
+
+	/* For MPLSoGRE */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					    &filter_replace_buf);
+	return ret;
+}
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH 1/3] app/testpmd: support MPLS for generic filter
  2017-03-03  9:43 ` [PATCH 1/3] app/testpmd: support MPLS for generic filter Beilei Xing
@ 2017-03-03 11:09   ` Adrien Mazarguil
  2017-03-06  2:39     ` Xing, Beilei
  0 siblings, 1 reply; 43+ messages in thread
From: Adrien Mazarguil @ 2017-03-03 11:09 UTC (permalink / raw)
  To: Beilei Xing; +Cc: jingjing.wu, helin.zhang, dev

Hi Beilei,

I think the commit title should reflect that this commit adds support for
GRE and MPLS items to rte_flow, testpmd changes are only a consequence.

On Fri, Mar 03, 2017 at 05:43:54PM +0800, Beilei Xing wrote:
> This patch adds MPLS support for generic filter
> API.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  app/test-pmd/cmdline_flow.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
>  app/test-pmd/config.c       |  2 ++
>  lib/librte_ether/rte_flow.h | 40 +++++++++++++++++++++++++++++++++
>  3 files changed, 97 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index ff98690..241bda1 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -159,6 +159,11 @@ enum index {
>  	ITEM_SCTP_CKSUM,
>  	ITEM_VXLAN,
>  	ITEM_VXLAN_VNI,
> +	ITEM_MPLS,
> +	ITEM_MPLS_LABEL,
> +	ITEM_GRE,
> +	ITEM_GRE_FLAGS,
> +	ITEM_GRE_PROTO,
>  
>  	/* Validate/create actions. */
>  	ACTIONS,
> @@ -432,6 +437,8 @@ static const enum index next_item[] = {
>  	ITEM_TCP,
>  	ITEM_SCTP,
>  	ITEM_VXLAN,
> +	ITEM_MPLS,
> +	ITEM_GRE,
>  	ZERO,
>  };
>  
> @@ -538,6 +545,19 @@ static const enum index item_vxlan[] = {
>  	ZERO,
>  };
>  
> +static const enum index item_mpls[] = {
> +	ITEM_MPLS_LABEL,
> +	ITEM_NEXT,
> +	ZERO,
> +};
> +
> +static const enum index item_gre[] = {
> +	ITEM_GRE_FLAGS,
> +	ITEM_GRE_PROTO,
> +	ITEM_NEXT,
> +	ZERO,
> +};
> +
>  static const enum index next_action[] = {
>  	ACTION_END,
>  	ACTION_VOID,
> @@ -1279,6 +1299,41 @@ static const struct token token_list[] = {
>  		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
>  		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
>  	},
> +	[ITEM_MPLS] = {
> +		.name = "mpls",
> +		.help = "match MPLS header",
> +		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> +		.next = NEXT(item_mpls),
> +		.call = parse_vc,
> +	},
> +	[ITEM_MPLS_LABEL] = {
> +		.name = "label",
> +		.help = "MPLS label",
> +		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls,
> +					     label_tc_s_ttl)),
> +	},
> +	[ITEM_GRE] = {
> +		.name = "gre",
> +		.help = "match GRE header",
> +		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> +		.next = NEXT(item_gre),
> +		.call = parse_vc,
> +	},
> +	[ITEM_GRE_FLAGS] = {
> +		.name = "c_rsvd0_ver",
> +		.help = "GRE c_rsvd0_ver",
> +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> +					     c_rsvd0_ver)),
> +	},
> +	[ITEM_GRE_PROTO] = {
> +		.name = "protocol",
> +		.help = "GRE protocol type",
> +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> +					     protocol)),
> +	},

Testpmd documentation must be updated accordingly, see:

 doc/guides/testpmd_app_ug/testpmd_funcs.rst

>  	/* Validate/create actions. */
>  	[ACTIONS] = {
>  		.name = "actions",
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 80491fc..c042765 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -963,6 +963,8 @@ static const struct {
>  	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
>  	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
>  	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
> +	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> +	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
>  };
>  
>  /** Compute storage space needed by item specification. */
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 171a569..c845953 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -282,6 +282,20 @@ enum rte_flow_item_type {
>  	 * See struct rte_flow_item_nvgre.
>  	 */
>  	RTE_FLOW_ITEM_TYPE_NVGRE,
> +
> +	/**
> +	 * Matches a MPLS header.
> +	 *
> +	 * See struct rte_flow_item_mpls.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +
> +	/**
> +	 * Matches a GRE header.
> +	 *
> +	 * See struct rte_flow_item_gre.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_GRE,
>  };

API documentation must be updated accordingly, see:

 doc/guides/prog_guide/rte_flow.rst

Same comments about RTE_FLOW_ITEM_TYPE_NVGRE added by another series. You
should mention there's a dependency between them.

>  
>  /**
> @@ -599,6 +613,32 @@ struct rte_flow_item_nvgre {
>  };
>  
>  /**
> + * RTE_FLOW_ITEM_TYPE_MPLS.
> + *
> + * Matches a MPLS header.
> + */
> +	struct rte_flow_item_mpls {
> +		/**
> +		 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
> +		 */
> +		uint32_t label_tc_s_ttl;
> +	};

Wrong indentation.

> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_GRE.
> + *
> + * Matches a GRE header.
> + */
> +struct rte_flow_item_gre {
> +	/**
> +	 * Checksum (1b), reserved 0 (12b), version (3b).
> +	 * Refer to RFC 2784.
> +	 */
> +	uint16_t c_rsvd0_ver;
> +	uint16_t protocol; /**< Protocol type. */
> +};
> +
> +/**
>   * Matching pattern item definition.
>   *
>   * A pattern is formed by stacking items starting from the lowest protocol
> -- 
> 2.5.5
> 

This patch looks otherwise good.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 1/3] app/testpmd: support MPLS for generic filter
  2017-03-03 11:09   ` Adrien Mazarguil
@ 2017-03-06  2:39     ` Xing, Beilei
  0 siblings, 0 replies; 43+ messages in thread
From: Xing, Beilei @ 2017-03-06  2:39 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: Wu, Jingjing, Zhang, Helin, dev

Hi Adrien,

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Friday, March 3, 2017 7:09 PM
> To: Xing, Beilei <beilei.xing@intel.com>
> Cc: Wu, Jingjing <jingjing.wu@intel.com>; Zhang, Helin
> <helin.zhang@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 1/3] app/testpmd: support MPLS for generic
> filter
> 
> Hi Beilei,
> 
> I think the commit title should reflect that this commit adds support for GRE
> and MPLS items to rte_flow, testpmd changes are only a consequence.

Thanks for the comments. I will change the title in the next version.

> 
> On Fri, Mar 03, 2017 at 05:43:54PM +0800, Beilei Xing wrote:
> > This patch adds MPLS support for generic filter API.
> >
> > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > ---
> >  app/test-pmd/cmdline_flow.c | 55
> +++++++++++++++++++++++++++++++++++++++++++++
> >  app/test-pmd/config.c       |  2 ++
> >  lib/librte_ether/rte_flow.h | 40
> +++++++++++++++++++++++++++++++++
> >  3 files changed, 97 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > index ff98690..241bda1 100644
> > --- a/app/test-pmd/cmdline_flow.c
> > +++ b/app/test-pmd/cmdline_flow.c
> > @@ -159,6 +159,11 @@ enum index {
> >  	ITEM_SCTP_CKSUM,
> >  	ITEM_VXLAN,
> >  	ITEM_VXLAN_VNI,
> > +	ITEM_MPLS,
> > +	ITEM_MPLS_LABEL,
> > +	ITEM_GRE,
> > +	ITEM_GRE_FLAGS,
> > +	ITEM_GRE_PROTO,
> >
> >  	/* Validate/create actions. */
> >  	ACTIONS,
> > @@ -432,6 +437,8 @@ static const enum index next_item[] = {
> >  	ITEM_TCP,
> >  	ITEM_SCTP,
> >  	ITEM_VXLAN,
> > +	ITEM_MPLS,
> > +	ITEM_GRE,
> >  	ZERO,
> >  };
> >
> > @@ -538,6 +545,19 @@ static const enum index item_vxlan[] = {
> >  	ZERO,
> >  };
> >
> > +static const enum index item_mpls[] = {
> > +	ITEM_MPLS_LABEL,
> > +	ITEM_NEXT,
> > +	ZERO,
> > +};
> > +
> > +static const enum index item_gre[] = {
> > +	ITEM_GRE_FLAGS,
> > +	ITEM_GRE_PROTO,
> > +	ITEM_NEXT,
> > +	ZERO,
> > +};
> > +
> >  static const enum index next_action[] = {
> >  	ACTION_END,
> >  	ACTION_VOID,
> > @@ -1279,6 +1299,41 @@ static const struct token token_list[] = {
> >  		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED),
> item_param),
> >  		.args = ARGS(ARGS_ENTRY_HTON(struct
> rte_flow_item_vxlan, vni)),
> >  	},
> > +	[ITEM_MPLS] = {
> > +		.name = "mpls",
> > +		.help = "match MPLS header",
> > +		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > +		.next = NEXT(item_mpls),
> > +		.call = parse_vc,
> > +	},
> > +	[ITEM_MPLS_LABEL] = {
> > +		.name = "label",
> > +		.help = "MPLS label",
> > +		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED),
> item_param),
> > +		.args = ARGS(ARGS_ENTRY_HTON(struct
> rte_flow_item_mpls,
> > +					     label_tc_s_ttl)),
> > +	},
> > +	[ITEM_GRE] = {
> > +		.name = "gre",
> > +		.help = "match GRE header",
> > +		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> > +		.next = NEXT(item_gre),
> > +		.call = parse_vc,
> > +	},
> > +	[ITEM_GRE_FLAGS] = {
> > +		.name = "c_rsvd0_ver",
> > +		.help = "GRE c_rsvd0_ver",
> > +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED),
> item_param),
> > +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> > +					     c_rsvd0_ver)),
> > +	},
> > +	[ITEM_GRE_PROTO] = {
> > +		.name = "protocol",
> > +		.help = "GRE protocol type",
> > +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED),
> item_param),
> > +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> > +					     protocol)),
> > +	},
> 
> Testpmd documentation must be updated accordingly, see:
> 
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst
> 
> >  	/* Validate/create actions. */
> >  	[ACTIONS] = {
> >  		.name = "actions",
> > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index
> > 80491fc..c042765 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -963,6 +963,8 @@ static const struct {
> >  	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
> >  	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
> >  	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
> > +	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > +	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> >  };
> >
> >  /** Compute storage space needed by item specification. */ diff --git
> > a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h index
> > 171a569..c845953 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -282,6 +282,20 @@ enum rte_flow_item_type {
> >  	 * See struct rte_flow_item_nvgre.
> >  	 */
> >  	RTE_FLOW_ITEM_TYPE_NVGRE,
> > +
> > +	/**
> > +	 * Matches a MPLS header.
> > +	 *
> > +	 * See struct rte_flow_item_mpls.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +
> > +	/**
> > +	 * Matches a GRE header.
> > +	 *
> > +	 * See struct rte_flow_item_gre.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_GRE,
> >  };
> 
> API documentation must be updated accordingly, see:
> 
>  doc/guides/prog_guide/rte_flow.rst
> 
> Same comments about RTE_FLOW_ITEM_TYPE_NVGRE added by another
> series. You should mention there's a dependency between them.
> 
> >
> >  /**
> > @@ -599,6 +613,32 @@ struct rte_flow_item_nvgre {  };
> >
> >  /**
> > + * RTE_FLOW_ITEM_TYPE_MPLS.
> > + *
> > + * Matches a MPLS header.
> > + */
> > +	struct rte_flow_item_mpls {
> > +		/**
> > +		 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
> > +		 */
> > +		uint32_t label_tc_s_ttl;
> > +	};
> 
> Wrong indentation.
> 
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_GRE.
> > + *
> > + * Matches a GRE header.
> > + */
> > +struct rte_flow_item_gre {
> > +	/**
> > +	 * Checksum (1b), reserved 0 (12b), version (3b).
> > +	 * Refer to RFC 2784.
> > +	 */
> > +	uint16_t c_rsvd0_ver;
> > +	uint16_t protocol; /**< Protocol type. */ };
> > +
> > +/**
> >   * Matching pattern item definition.
> >   *
> >   * A pattern is formed by stacking items starting from the lowest
> > protocol
> > --
> > 2.5.5
> >
> 
> This patch looks otherwise good.
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-03  9:43 ` [PATCH 3/3] net/i40e: enable cloud filter for MPLS Beilei Xing
@ 2017-03-08 16:05   ` Ferruh Yigit
  2017-03-09  3:57     ` Xing, Beilei
  2017-03-09 11:13   ` Iremonger, Bernard
  1 sibling, 1 reply; 43+ messages in thread
From: Ferruh Yigit @ 2017-03-08 16:05 UTC (permalink / raw)
  To: Beilei Xing, jingjing.wu; +Cc: helin.zhang, dev

On 3/3/2017 9:43 AM, Beilei Xing wrote:
> This patch enables MPLSoUDP and MPLSoGRE
> cloud filter with replace cloud filter.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>

<...>

> @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
>  	if (ret < 0)
>  		goto err_init_fdir_filter_list;
>  
> +	i40e_replace_mpls_l1_filter(pf);
> +	i40e_replace_mpls_cloud_filter(pf);

Hi Beilei,

Can you please help me to understand what has been replaced here, and why?

Thanks,
ferruh

<...>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-08 16:05   ` Ferruh Yigit
@ 2017-03-09  3:57     ` Xing, Beilei
  0 siblings, 0 replies; 43+ messages in thread
From: Xing, Beilei @ 2017-03-09  3:57 UTC (permalink / raw)
  To: Yigit, Ferruh, Wu, Jingjing; +Cc: Zhang, Helin, dev



> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, March 9, 2017 12:06 AM
> To: Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for MPLS
> 
> On 3/3/2017 9:43 AM, Beilei Xing wrote:
> > This patch enables MPLSoUDP and MPLSoGRE cloud filter with replace
> > cloud filter.
> >
> > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> 
> <...>
> 
> > @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  	if (ret < 0)
> >  		goto err_init_fdir_filter_list;
> >
> > +	i40e_replace_mpls_l1_filter(pf);
> > +	i40e_replace_mpls_cloud_filter(pf);
> 
> Hi Beilei,
> 
> Can you please help me to understand what has been replaced here, and
> why?

* Cloud filters type is a combination of up to 3 L1 filters.
* L1 filter depends on Type Rule index.

First, there's no MPLS label as L1 filter currently, so we need to add MPLS label by replacing some existing L1 filter, here we replace IMAC.
Second, there's no MPLS label as cloud filter currently, So here we add a new cloud filter type TEID_MPLS (0x11) to replace Inner MAC filter(0xA).

According to datasheet, the following filter types are supported by cloud filter.
6:0: Filter type:
* 0x0: Reserved
* 0x1: Reserved 
* 0x2: Reserved 
* 0x3: Inner MAC, Inner VLAN (for NVGRE, VXLAN or, Geneve or VXLAN-GPE packets)
* 0x4: Inner MAC, Inner VLAN, Tenant ID (for NVGRE, VXLAN, or Geneve or VXLAN-GPE
packets)
* 0x5: Reserved 
* 0x6: {Inner MAC, Tenant ID} (NVGRE packet, or VXLAN, /Geneve or VXLAN-GPE packets).
* 0x7: Reserved 
* 0x8: Reserved 
* 0x9: Outer MAC L2 filter
* 0xA: Inner MAC filter
* 0xB: Outer MAC, Tenant ID, Inner MAC
* 0xC: Application Destination IP
* 0xD: Application Source-IP, Inner MAC.
* 0xE - 0x3F: Reserved.

> 
> Thanks,
> ferruh
> 
> <...>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-03  9:43 ` [PATCH 3/3] net/i40e: enable cloud filter for MPLS Beilei Xing
  2017-03-08 16:05   ` Ferruh Yigit
@ 2017-03-09 11:13   ` Iremonger, Bernard
  2017-03-09 11:39     ` Xing, Beilei
  1 sibling, 1 reply; 43+ messages in thread
From: Iremonger, Bernard @ 2017-03-09 11:13 UTC (permalink / raw)
  To: Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, dev

Hi Beilei,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Beilei Xing
> Sent: Friday, March 3, 2017 9:44 AM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for MPLS
> 
> This patch enables MPLSoUDP and MPLSoGRE cloud filter with replace cloud
> filter.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
>  drivers/net/i40e/i40e_ethdev.h |   9 +++-
>  drivers/net/i40e/i40e_flow.c   | 108
> +++++++++++++++++++++++++++++++++++++----
>  3 files changed, 144 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 91bfd73..6044daf 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
>  	if (ret < 0)
>  		goto err_init_fdir_filter_list;
> 
> +	i40e_replace_mpls_l1_filter(pf);
> +	i40e_replace_mpls_cloud_filter(pf);
> +
>  	return 0;
> 
>  err_init_fdir_filter_list:
> @@ -6941,6 +6944,7 @@ i40e_dev_consistent_tunnel_filter_set(struct
> i40e_pf *pf,
>  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
>  	struct i40e_tunnel_filter *tunnel, *node;
>  	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
> +	uint32_t teid_le;
>  	bool big_buffer = 0;
> 
>  	cld_filter = rte_zmalloc("tunnel_filter", @@ -6989,6 +6993,28 @@
> i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
>  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
>  		break;
> +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> +			teid_le >> 4;
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +			(teid_le & 0xF) << 12;
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> +			0x40;
> +		big_buffer = 1;
> +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
> +		break;
> +	case I40E_TUNNEL_TYPE_MPLSoGRE:
> +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> +			teid_le >> 4;
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +			(teid_le & 0xF) << 12;
> +		pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> +			0x0;
> +		big_buffer = 1;
> +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
> +		break;
>  	default:
>  		/* Other tunnel types is not supported. */
>  		PMD_DRV_LOG(ERR, "tunnel type is not supported."); @@ -
> 6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf
> *pf,
>  		return -EINVAL;
>  	}
> 
> -	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> -				       &pfilter->element.flags);
> -	if (val < 0) {
> -		rte_free(cld_filter);
> -		return -EINVAL;
> +	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
> +		pfilter->element.flags =
> +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> +	else if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_MPLSoGRE)
> +		pfilter->element.flags =
> +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> +	else {
> +		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> +						&pfilter->element.flags);
> +		if (val < 0) {
> +			rte_free(cld_filter);
> +			return -EINVAL;
> +		}
>  	}
> 
>  	pfilter->element.flags |= rte_cpu_to_le_16( diff --git
> a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index
> dd9d709..f305baa 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
>  /* Tunnel filter number HW supports */
>  #define I40E_MAX_TUNNEL_FILTER_NUM 400
> 
> -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11 -#define
> I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
> +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define
> +I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 #define
> +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define
> +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define
> +I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
> 
>  enum i40e_tunnel_iptype {
>  	I40E_TUNNEL_IPTYPE_IPV4,
> @@ -963,6 +966,8 @@ enum i40e_status_code
> i40e_aq_remove_cloud_filters_big_buffer(
>  enum i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
>  		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
>  		    struct i40e_aqc_replace_cloud_filters_cmd_buf
> *cmd_buf);
> +int i40e_replace_mpls_l1_filter(struct i40e_pf *pf); int
> +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
> 
>  #define I40E_DEV_TO_PCI(eth_dev) \
>  	RTE_DEV_TO_PCI((eth_dev)->device)
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index 9ca3189..6bb2046 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf
> *pf,
>  		   filter->input.general_fields,
>  		   sizeof(cld_filter.general_fields));
> 
> -	if (((filter->input.flags &
> -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
> -	    ((filter->input.flags &
> -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
> +	if ((filter->input.flags &
> I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
> +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
> +	    (filter->input.flags &
> I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
> +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
>  		big_buffer = 1;
> 
>  	if (big_buffer)
> @@ -2255,3 +2249,97 @@ i40e_status_code
> i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
> 
>  	return status;
>  }
> +
> +int
> +i40e_replace_mpls_l1_filter(struct i40e_pf *pf) {
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	int ret;
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	/* create L1 filter */
> +	filter_replace.old_filter_type =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;

I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC = 12 (0x0C)
Should the old_filter_type  macro be I40E_AQC_ADD_CLOUD_FILTER_IIP = 0x0C ?

> +	filter_replace.new_filter_type =
> I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> +	filter_replace.tr_bit = 0xFF;
> +
> +	/* Prepare the buffer, 3 entries */
> +	filter_replace_buf.data[0] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[2] = 0xff;
> +	filter_replace_buf.data[3] = 0xff;
> +	filter_replace_buf.data[4] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[7] = 0xf0;
> +	filter_replace_buf.data[8] = 0x48;
> +	filter_replace_buf.data[8] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[10] = 0x4c;
> +	filter_replace_buf.data[11] = 0x8c;
> +
> +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					    &filter_replace_buf);
> +	return ret;
> +}
> +
> +int
> +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf) {
> +	int ret;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +
> +	/* For MPLSoUDP */
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> +	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
> +	filter_replace.new_filter_type =
> +		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> +	/* Prepare the buffer, 2 entries */
> +	filter_replace_buf.data[0] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					    &filter_replace_buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* For MPLSoGRE */
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> +	filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
> +	filter_replace.new_filter_type =
> +		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> +	/* Prepare the buffer, 2 entries */
> +	filter_replace_buf.data[0] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +
> +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					    &filter_replace_buf);
> +	return ret;
> +}
> --
> 2.5.5

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-09 11:13   ` Iremonger, Bernard
@ 2017-03-09 11:39     ` Xing, Beilei
  2017-03-09 11:53       ` Iremonger, Bernard
  0 siblings, 1 reply; 43+ messages in thread
From: Xing, Beilei @ 2017-03-09 11:39 UTC (permalink / raw)
  To: Iremonger, Bernard, Wu, Jingjing; +Cc: Zhang, Helin, dev

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, March 9, 2017 7:13 PM
> To: Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for MPLS
> 
> Hi Beilei,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Beilei Xing
> > Sent: Friday, March 3, 2017 9:44 AM
> > To: Wu, Jingjing <jingjing.wu@intel.com>
> > Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for MPLS
> >
> > This patch enables MPLSoUDP and MPLSoGRE cloud filter with replace
> > cloud filter.
> >
> > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
> >  drivers/net/i40e/i40e_ethdev.h |   9 +++-
> >  drivers/net/i40e/i40e_flow.c   | 108
> > +++++++++++++++++++++++++++++++++++++----
> >  3 files changed, 144 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 91bfd73..6044daf 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  	if (ret < 0)
> >  		goto err_init_fdir_filter_list;
> >
> > +	i40e_replace_mpls_l1_filter(pf);
> > +	i40e_replace_mpls_cloud_filter(pf);
> > +
> >  	return 0;
> >
> >  err_init_fdir_filter_list:
> > @@ -6941,6 +6944,7 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > i40e_pf *pf,
> >  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
> >  	struct i40e_tunnel_filter *tunnel, *node;
> >  	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
> > +	uint32_t teid_le;
> >  	bool big_buffer = 0;
> >
> >  	cld_filter = rte_zmalloc("tunnel_filter", @@ -6989,6 +6993,28 @@
> > i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
> >  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
> >  		break;
> > +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > +			teid_le >> 4;
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +			(teid_le & 0xF) << 12;
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > +			0x40;
> > +		big_buffer = 1;
> > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
> > +		break;
> > +	case I40E_TUNNEL_TYPE_MPLSoGRE:
> > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > +			teid_le >> 4;
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +			(teid_le & 0xF) << 12;
> > +		pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > +			0x0;
> > +		big_buffer = 1;
> > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
> > +		break;
> >  	default:
> >  		/* Other tunnel types is not supported. */
> >  		PMD_DRV_LOG(ERR, "tunnel type is not supported."); @@ -
> > 6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > i40e_pf *pf,
> >  		return -EINVAL;
> >  	}
> >
> > -	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > -				       &pfilter->element.flags);
> > -	if (val < 0) {
> > -		rte_free(cld_filter);
> > -		return -EINVAL;
> > +	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
> > +		pfilter->element.flags =
> > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> > +	else if (tunnel_filter->tunnel_type ==
> > I40E_TUNNEL_TYPE_MPLSoGRE)
> > +		pfilter->element.flags =
> > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> > +	else {
> > +		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > +						&pfilter->element.flags);
> > +		if (val < 0) {
> > +			rte_free(cld_filter);
> > +			return -EINVAL;
> > +		}
> >  	}
> >
> >  	pfilter->element.flags |= rte_cpu_to_le_16( diff --git
> > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> > index dd9d709..f305baa 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
> >  /* Tunnel filter number HW supports */  #define
> > I40E_MAX_TUNNEL_FILTER_NUM 400
> >
> > -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11 -#define
> > I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
> > +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define
> > +I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 #define
> > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define
> > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define
> > +I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
> >
> >  enum i40e_tunnel_iptype {
> >  	I40E_TUNNEL_IPTYPE_IPV4,
> > @@ -963,6 +966,8 @@ enum i40e_status_code
> > i40e_aq_remove_cloud_filters_big_buffer(
> >  enum i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw
> *hw,
> >  		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
> >  		    struct i40e_aqc_replace_cloud_filters_cmd_buf
> > *cmd_buf);
> > +int i40e_replace_mpls_l1_filter(struct i40e_pf *pf); int
> > +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
> >
> >  #define I40E_DEV_TO_PCI(eth_dev) \
> >  	RTE_DEV_TO_PCI((eth_dev)->device)
> > diff --git a/drivers/net/i40e/i40e_flow.c
> > b/drivers/net/i40e/i40e_flow.c index 9ca3189..6bb2046 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> > @@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf
> > *pf,
> >  		   filter->input.general_fields,
> >  		   sizeof(cld_filter.general_fields));
> >
> > -	if (((filter->input.flags &
> > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
> > -	    ((filter->input.flags &
> > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
> > +	if ((filter->input.flags &
> > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
> > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
> > +	    (filter->input.flags &
> > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
> > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
> >  		big_buffer = 1;
> >
> >  	if (big_buffer)
> > @@ -2255,3 +2249,97 @@ i40e_status_code
> > i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
> >
> >  	return status;
> >  }
> > +
> > +int
> > +i40e_replace_mpls_l1_filter(struct i40e_pf *pf) {
> > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > +	int ret;
> > +
> > +	memset(&filter_replace, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +	memset(&filter_replace_buf, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +	/* create L1 filter */
> > +	filter_replace.old_filter_type =
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
> 
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC = 12 (0x0C) Should the
> old_filter_type  macro be I40E_AQC_ADD_CLOUD_FILTER_IIP = 0x0C ?

No, I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC is L1 filter, but the I40E_AQC_ADD_CLOUD_FILTER_IIP is cloud filter.
We should replace L1 filter here.

> 
> > +	filter_replace.new_filter_type =
> > I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> > +	filter_replace.tr_bit = 0xFF;
> > +
> > +	/* Prepare the buffer, 3 entries */
> > +	filter_replace_buf.data[0] =
> > +
> > 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
> > +	filter_replace_buf.data[0] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[2] = 0xff;
> > +	filter_replace_buf.data[3] = 0xff;
> > +	filter_replace_buf.data[4] =
> > +
> > 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
> > +	filter_replace_buf.data[4] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[7] = 0xf0;
> > +	filter_replace_buf.data[8] = 0x48;
> > +	filter_replace_buf.data[8] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[10] = 0x4c;
> > +	filter_replace_buf.data[11] = 0x8c;
> > +
> > +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +					    &filter_replace_buf);
> > +	return ret;
> > +}
> > +
> > +int
> > +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf) {
> > +	int ret;
> > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > +
> > +	/* For MPLSoUDP */
> > +	memset(&filter_replace, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +	memset(&filter_replace_buf, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> > +	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
> > +	filter_replace.new_filter_type =
> > +		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> > +	/* Prepare the buffer, 2 entries */
> > +	filter_replace_buf.data[0] =
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> > +	filter_replace_buf.data[0] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> > +	filter_replace_buf.data[4] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +					    &filter_replace_buf);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/* For MPLSoGRE */
> > +	memset(&filter_replace, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +	memset(&filter_replace_buf, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> > +	filter_replace.old_filter_type =
> > I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
> > +	filter_replace.new_filter_type =
> > +		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> > +	/* Prepare the buffer, 2 entries */
> > +	filter_replace_buf.data[0] =
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> > +	filter_replace_buf.data[0] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
> > +	filter_replace_buf.data[4] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +
> > +	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +					    &filter_replace_buf);
> > +	return ret;
> > +}
> > --
> > 2.5.5
> 
> Regards,
> 
> Bernard.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-09 11:39     ` Xing, Beilei
@ 2017-03-09 11:53       ` Iremonger, Bernard
  2017-03-09 12:06         ` Xing, Beilei
  0 siblings, 1 reply; 43+ messages in thread
From: Iremonger, Bernard @ 2017-03-09 11:53 UTC (permalink / raw)
  To: Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, dev

Hi Beilei,
 <snip>

> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Beilei Xing
> > > Sent: Friday, March 3, 2017 9:44 AM
> > > To: Wu, Jingjing <jingjing.wu@intel.com>
> > > Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> > > Subject: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for
> > > MPLS
> > >
> > > This patch enables MPLSoUDP and MPLSoGRE cloud filter with replace
> > > cloud filter.
> > >
> > > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > > ---
> > >  drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
> > >  drivers/net/i40e/i40e_ethdev.h |   9 +++-
> > >  drivers/net/i40e/i40e_flow.c   | 108
> > > +++++++++++++++++++++++++++++++++++++----
> > >  3 files changed, 144 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > > b/drivers/net/i40e/i40e_ethdev.c index 91bfd73..6044daf 100644
> > > --- a/drivers/net/i40e/i40e_ethdev.c
> > > +++ b/drivers/net/i40e/i40e_ethdev.c
> > > @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
> > >  	if (ret < 0)
> > >  		goto err_init_fdir_filter_list;
> > >
> > > +	i40e_replace_mpls_l1_filter(pf);
> > > +	i40e_replace_mpls_cloud_filter(pf);
> > > +
> > >  	return 0;
> > >
> > >  err_init_fdir_filter_list:
> > > @@ -6941,6 +6944,7 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > > i40e_pf *pf,
> > >  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
> > >  	struct i40e_tunnel_filter *tunnel, *node;
> > >  	struct i40e_tunnel_filter check_filter; /* Check if filter exists
> > > */
> > > +	uint32_t teid_le;
> > >  	bool big_buffer = 0;
> > >
> > >  	cld_filter = rte_zmalloc("tunnel_filter", @@ -6989,6 +6993,28 @@
> > > i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> > >  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
> > >  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
> > >  		break;
> > > +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> > > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > +			teid_le >> 4;
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > +			(teid_le & 0xF) << 12;
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > +			0x40;
> > > +		big_buffer = 1;
> > > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
> > > +		break;
> > > +	case I40E_TUNNEL_TYPE_MPLSoGRE:
> > > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > +			teid_le >> 4;
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > +			(teid_le & 0xF) << 12;
> > > +		pfilter-
> > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > +			0x0;
> > > +		big_buffer = 1;
> > > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
> > > +		break;
> > >  	default:
> > >  		/* Other tunnel types is not supported. */
> > >  		PMD_DRV_LOG(ERR, "tunnel type is not supported."); @@ -
> > > 6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > > i40e_pf *pf,
> > >  		return -EINVAL;
> > >  	}
> > >
> > > -	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > > -				       &pfilter->element.flags);
> > > -	if (val < 0) {
> > > -		rte_free(cld_filter);
> > > -		return -EINVAL;
> > > +	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
> > > +		pfilter->element.flags =
> > > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> > > +	else if (tunnel_filter->tunnel_type ==
> > > I40E_TUNNEL_TYPE_MPLSoGRE)
> > > +		pfilter->element.flags =
> > > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> > > +	else {
> > > +		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > > +						&pfilter->element.flags);
> > > +		if (val < 0) {
> > > +			rte_free(cld_filter);
> > > +			return -EINVAL;
> > > +		}
> > >  	}
> > >
> > >  	pfilter->element.flags |= rte_cpu_to_le_16( diff --git
> > > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> > > index dd9d709..f305baa 100644
> > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > @@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
> > >  /* Tunnel filter number HW supports */  #define
> > > I40E_MAX_TUNNEL_FILTER_NUM 400
> > >
> > > -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11 -#define
> > > I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
> > > +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define
> > > +I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 #define
> > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define
> > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define
> > > +I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
> > >
> > >  enum i40e_tunnel_iptype {
> > >  	I40E_TUNNEL_IPTYPE_IPV4,
> > > @@ -963,6 +966,8 @@ enum i40e_status_code
> > > i40e_aq_remove_cloud_filters_big_buffer(
> > >  enum i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw
> > *hw,
> > >  		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
> > >  		    struct i40e_aqc_replace_cloud_filters_cmd_buf
> > > *cmd_buf);
> > > +int i40e_replace_mpls_l1_filter(struct i40e_pf *pf); int
> > > +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
> > >
> > >  #define I40E_DEV_TO_PCI(eth_dev) \
> > >  	RTE_DEV_TO_PCI((eth_dev)->device)
> > > diff --git a/drivers/net/i40e/i40e_flow.c
> > > b/drivers/net/i40e/i40e_flow.c index 9ca3189..6bb2046 100644
> > > --- a/drivers/net/i40e/i40e_flow.c
> > > +++ b/drivers/net/i40e/i40e_flow.c
> > > @@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct
> > > i40e_pf *pf,
> > >  		   filter->input.general_fields,
> > >  		   sizeof(cld_filter.general_fields));
> > >
> > > -	if (((filter->input.flags &
> > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
> > > -	    ((filter->input.flags &
> > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
> > > +	if ((filter->input.flags &
> > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
> > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
> > > +	    (filter->input.flags &
> > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
> > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
> > >  		big_buffer = 1;
> > >
> > >  	if (big_buffer)
> > > @@ -2255,3 +2249,97 @@ i40e_status_code
> > > i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
> > >
> > >  	return status;
> > >  }
> > > +
> > > +int
> > > +i40e_replace_mpls_l1_filter(struct i40e_pf *pf) {
> > > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > > +	int ret;
> > > +
> > > +	memset(&filter_replace, 0,
> > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > > +	memset(&filter_replace_buf, 0,
> > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > > +
> > > +	/* create L1 filter */
> > > +	filter_replace.old_filter_type =
> > > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
> >
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC = 12 (0x0C) Should
> the
> > old_filter_type  macro be I40E_AQC_ADD_CLOUD_FILTER_IIP = 0x0C ?
> 
> No, I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC is L1 filter, but the
> I40E_AQC_ADD_CLOUD_FILTER_IIP is cloud filter.
> We should replace L1 filter here.

The I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC macro  (value 12) is an index into the Field Vector, it is not a filter type macro.
Should a filter type macro be used to set filter_replace.old_filter_type ?

Regards,

Bernard

<snip> 

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-09 11:53       ` Iremonger, Bernard
@ 2017-03-09 12:06         ` Xing, Beilei
  2017-03-09 13:48           ` Iremonger, Bernard
  0 siblings, 1 reply; 43+ messages in thread
From: Xing, Beilei @ 2017-03-09 12:06 UTC (permalink / raw)
  To: Iremonger, Bernard, Wu, Jingjing; +Cc: Zhang, Helin, dev



> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, March 9, 2017 7:54 PM
> To: Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for MPLS
> 
> Hi Beilei,
>  <snip>
> 
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Beilei Xing
> > > > Sent: Friday, March 3, 2017 9:44 AM
> > > > To: Wu, Jingjing <jingjing.wu@intel.com>
> > > > Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> > > > Subject: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter for
> > > > MPLS
> > > >
> > > > This patch enables MPLSoUDP and MPLSoGRE cloud filter with replace
> > > > cloud filter.
> > > >
> > > > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > > > ---
> > > >  drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
> > > >  drivers/net/i40e/i40e_ethdev.h |   9 +++-
> > > >  drivers/net/i40e/i40e_flow.c   | 108
> > > > +++++++++++++++++++++++++++++++++++++----
> > > >  3 files changed, 144 insertions(+), 17 deletions(-)
> > > >
> > > > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > > > b/drivers/net/i40e/i40e_ethdev.c index 91bfd73..6044daf 100644
> > > > --- a/drivers/net/i40e/i40e_ethdev.c
> > > > +++ b/drivers/net/i40e/i40e_ethdev.c
> > > > @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
> > > >  	if (ret < 0)
> > > >  		goto err_init_fdir_filter_list;
> > > >
> > > > +	i40e_replace_mpls_l1_filter(pf);
> > > > +	i40e_replace_mpls_cloud_filter(pf);
> > > > +
> > > >  	return 0;
> > > >
> > > >  err_init_fdir_filter_list:
> > > > @@ -6941,6 +6944,7 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > > > i40e_pf *pf,
> > > >  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
> > > >  	struct i40e_tunnel_filter *tunnel, *node;
> > > >  	struct i40e_tunnel_filter check_filter; /* Check if filter
> > > > exists */
> > > > +	uint32_t teid_le;
> > > >  	bool big_buffer = 0;
> > > >
> > > >  	cld_filter = rte_zmalloc("tunnel_filter", @@ -6989,6 +6993,28 @@
> > > > i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> > > >  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
> > > >  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
> > > >  		break;
> > > > +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> > > > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > > +			teid_le >> 4;
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > > +			(teid_le & 0xF) << 12;
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > > +			0x40;
> > > > +		big_buffer = 1;
> > > > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
> > > > +		break;
> > > > +	case I40E_TUNNEL_TYPE_MPLSoGRE:
> > > > +		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > > +			teid_le >> 4;
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > > +			(teid_le & 0xF) << 12;
> > > > +		pfilter-
> > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > > +			0x0;
> > > > +		big_buffer = 1;
> > > > +		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
> > > > +		break;
> > > >  	default:
> > > >  		/* Other tunnel types is not supported. */
> > > >  		PMD_DRV_LOG(ERR, "tunnel type is not supported."); @@ -
> > > > 6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > > > i40e_pf *pf,
> > > >  		return -EINVAL;
> > > >  	}
> > > >
> > > > -	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > > > -				       &pfilter->element.flags);
> > > > -	if (val < 0) {
> > > > -		rte_free(cld_filter);
> > > > -		return -EINVAL;
> > > > +	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
> > > > +		pfilter->element.flags =
> > > > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> > > > +	else if (tunnel_filter->tunnel_type ==
> > > > I40E_TUNNEL_TYPE_MPLSoGRE)
> > > > +		pfilter->element.flags =
> > > > +			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> > > > +	else {
> > > > +		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > > > +						&pfilter->element.flags);
> > > > +		if (val < 0) {
> > > > +			rte_free(cld_filter);
> > > > +			return -EINVAL;
> > > > +		}
> > > >  	}
> > > >
> > > >  	pfilter->element.flags |= rte_cpu_to_le_16( diff --git
> > > > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> > > > index dd9d709..f305baa 100644
> > > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > > @@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
> > > >  /* Tunnel filter number HW supports */  #define
> > > > I40E_MAX_TUNNEL_FILTER_NUM 400
> > > >
> > > > -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11 -#define
> > > > I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
> > > > +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define
> > > > +I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 #define
> > > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define
> > > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define
> > > > +I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
> > > >
> > > >  enum i40e_tunnel_iptype {
> > > >  	I40E_TUNNEL_IPTYPE_IPV4,
> > > > @@ -963,6 +966,8 @@ enum i40e_status_code
> > > > i40e_aq_remove_cloud_filters_big_buffer(
> > > >  enum i40e_status_code i40e_aq_replace_cloud_filters(struct
> > > > i40e_hw
> > > *hw,
> > > >  		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
> > > >  		    struct i40e_aqc_replace_cloud_filters_cmd_buf
> > > > *cmd_buf);
> > > > +int i40e_replace_mpls_l1_filter(struct i40e_pf *pf); int
> > > > +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
> > > >
> > > >  #define I40E_DEV_TO_PCI(eth_dev) \
> > > >  	RTE_DEV_TO_PCI((eth_dev)->device) diff --git
> > > > a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> > > > index 9ca3189..6bb2046 100644
> > > > --- a/drivers/net/i40e/i40e_flow.c
> > > > +++ b/drivers/net/i40e/i40e_flow.c
> > > > @@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct
> > > > i40e_pf *pf,
> > > >  		   filter->input.general_fields,
> > > >  		   sizeof(cld_filter.general_fields));
> > > >
> > > > -	if (((filter->input.flags &
> > > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
> > > > -	    ((filter->input.flags &
> > > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
> > > > +	if ((filter->input.flags &
> > > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
> > > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
> > > > +	    (filter->input.flags &
> > > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
> > > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
> > > >  		big_buffer = 1;
> > > >
> > > >  	if (big_buffer)
> > > > @@ -2255,3 +2249,97 @@ i40e_status_code
> > > > i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
> > > >
> > > >  	return status;
> > > >  }
> > > > +
> > > > +int
> > > > +i40e_replace_mpls_l1_filter(struct i40e_pf *pf) {
> > > > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > > > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > > > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > > > +	int ret;
> > > > +
> > > > +	memset(&filter_replace, 0,
> > > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > > > +	memset(&filter_replace_buf, 0,
> > > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > > > +
> > > > +	/* create L1 filter */
> > > > +	filter_replace.old_filter_type =
> > > > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
> > >
> > > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC = 12 (0x0C) Should
> > the
> > > old_filter_type  macro be I40E_AQC_ADD_CLOUD_FILTER_IIP = 0x0C ?
> >
> > No, I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC is L1 filter, but
> the
> > I40E_AQC_ADD_CLOUD_FILTER_IIP is cloud filter.
> > We should replace L1 filter here.
> 
> The I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC macro  (value 12) is
> an index into the Field Vector, it is not a filter type macro.
> Should a filter type macro be used to set filter_replace.old_filter_type ?

I think we can check with firmware guy for the detail.

Beilei

> 
> Regards,
> 
> Bernard
> 
> <snip>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 3/3] net/i40e: enable cloud filter for MPLS
  2017-03-09 12:06         ` Xing, Beilei
@ 2017-03-09 13:48           ` Iremonger, Bernard
  0 siblings, 0 replies; 43+ messages in thread
From: Iremonger, Bernard @ 2017-03-09 13:48 UTC (permalink / raw)
  To: Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, dev

Hi Beilei,

 <snip>
> > > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Beilei Xing
> > > > > Sent: Friday, March 3, 2017 9:44 AM
> > > > > To: Wu, Jingjing <jingjing.wu@intel.com>
> > > > > Cc: Zhang, Helin <helin.zhang@intel.com>; dev@dpdk.org
> > > > > Subject: [dpdk-dev] [PATCH 3/3] net/i40e: enable cloud filter
> > > > > for MPLS
> > > > >
> > > > > This patch enables MPLSoUDP and MPLSoGRE cloud filter with
> > > > > replace cloud filter.
> > > > >
> > > > > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > > > > ---
> > > > >  drivers/net/i40e/i40e_ethdev.c |  44 +++++++++++++++--
> > > > >  drivers/net/i40e/i40e_ethdev.h |   9 +++-
> > > > >  drivers/net/i40e/i40e_flow.c   | 108
> > > > > +++++++++++++++++++++++++++++++++++++----
> > > > >  3 files changed, 144 insertions(+), 17 deletions(-)
> > > > >
> > > > > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > > > > b/drivers/net/i40e/i40e_ethdev.c index 91bfd73..6044daf 100644
> > > > > --- a/drivers/net/i40e/i40e_ethdev.c
> > > > > +++ b/drivers/net/i40e/i40e_ethdev.c
> > > > > @@ -1286,6 +1286,9 @@ eth_i40e_dev_init(struct rte_eth_dev
> *dev)
> > > > >  	if (ret < 0)
> > > > >  		goto err_init_fdir_filter_list;
> > > > >
> > > > > +	i40e_replace_mpls_l1_filter(pf);
> > > > > +	i40e_replace_mpls_cloud_filter(pf);
> > > > > +
> > > > >  	return 0;
> > > > >
> > > > >  err_init_fdir_filter_list:
> > > > > @@ -6941,6 +6944,7 @@
> > > > > i40e_dev_consistent_tunnel_filter_set(struct
> > > > > i40e_pf *pf,
> > > > >  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
> > > > >  	struct i40e_tunnel_filter *tunnel, *node;
> > > > >  	struct i40e_tunnel_filter check_filter; /* Check if filter
> > > > > exists */
> > > > > +	uint32_t teid_le;
> > > > >  	bool big_buffer = 0;
> > > > >
> > > > >  	cld_filter = rte_zmalloc("tunnel_filter", @@ -6989,6 +6993,28
> > > > > @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> > > > >  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
> > > > >  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
> > > > >  		break;
> > > > > +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> > > > > +		teid_le = rte_cpu_to_le_32(tunnel_filter-
> >tenant_id);
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > > > +			teid_le >> 4;
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > > > +			(teid_le & 0xF) << 12;
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > > > +			0x40;
> > > > > +		big_buffer = 1;
> > > > > +		tun_type =
> I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
> > > > > +		break;
> > > > > +	case I40E_TUNNEL_TYPE_MPLSoGRE:
> > > > > +		teid_le = rte_cpu_to_le_32(tunnel_filter-
> >tenant_id);
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > > > > +			teid_le >> 4;
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > > > > +			(teid_le & 0xF) << 12;
> > > > > +		pfilter-
> > > > > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > > > > +			0x0;
> > > > > +		big_buffer = 1;
> > > > > +		tun_type =
> I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
> > > > > +		break;
> > > > >  	default:
> > > > >  		/* Other tunnel types is not supported. */
> > > > >  		PMD_DRV_LOG(ERR, "tunnel type is not
> supported."); @@ -
> > > > > 6996,11 +7022,19 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > > > > i40e_pf *pf,
> > > > >  		return -EINVAL;
> > > > >  	}
> > > > >
> > > > > -	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> > > > > -				       &pfilter->element.flags);
> > > > > -	if (val < 0) {
> > > > > -		rte_free(cld_filter);
> > > > > -		return -EINVAL;
> > > > > +	if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_MPLSoUDP)
> > > > > +		pfilter->element.flags =
> > > > > +
> 	I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
> > > > > +	else if (tunnel_filter->tunnel_type ==
> > > > > I40E_TUNNEL_TYPE_MPLSoGRE)
> > > > > +		pfilter->element.flags =
> > > > > +
> 	I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
> > > > > +	else {
> > > > > +		val = i40e_dev_get_filter_type(tunnel_filter-
> >filter_type,
> > > > > +						&pfilter-
> >element.flags);
> > > > > +		if (val < 0) {
> > > > > +			rte_free(cld_filter);
> > > > > +			return -EINVAL;
> > > > > +		}
> > > > >  	}
> > > > >
> > > > >  	pfilter->element.flags |= rte_cpu_to_le_16( diff --git
> > > > > a/drivers/net/i40e/i40e_ethdev.h
> > > > > b/drivers/net/i40e/i40e_ethdev.h index dd9d709..f305baa 100644
> > > > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > > > @@ -499,8 +499,11 @@ struct i40e_ethertype_rule {
> > > > >  /* Tunnel filter number HW supports */  #define
> > > > > I40E_MAX_TUNNEL_FILTER_NUM 400
> > > > >
> > > > > -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11 -
> #define
> > > > > I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
> > > > > +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8 #define
> > > > > +I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9 #define
> > > > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11 #define
> > > > > +I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12 #define
> > > > > +I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
> > > > >
> > > > >  enum i40e_tunnel_iptype {
> > > > >  	I40E_TUNNEL_IPTYPE_IPV4,
> > > > > @@ -963,6 +966,8 @@ enum i40e_status_code
> > > > > i40e_aq_remove_cloud_filters_big_buffer(
> > > > >  enum i40e_status_code i40e_aq_replace_cloud_filters(struct
> > > > > i40e_hw
> > > > *hw,
> > > > >  		    struct i40e_aqc_replace_cloud_filters_cmd *filters,
> > > > >  		    struct i40e_aqc_replace_cloud_filters_cmd_buf
> > > > > *cmd_buf);
> > > > > +int i40e_replace_mpls_l1_filter(struct i40e_pf *pf); int
> > > > > +i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
> > > > >
> > > > >  #define I40E_DEV_TO_PCI(eth_dev) \
> > > > >  	RTE_DEV_TO_PCI((eth_dev)->device) diff --git
> > > > > a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> > > > > index 9ca3189..6bb2046 100644
> > > > > --- a/drivers/net/i40e/i40e_flow.c
> > > > > +++ b/drivers/net/i40e/i40e_flow.c
> > > > > @@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct
> > > > > i40e_pf *pf,
> > > > >  		   filter->input.general_fields,
> > > > >  		   sizeof(cld_filter.general_fields));
> > > > >
> > > > > -	if (((filter->input.flags &
> > > > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
> > > > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
> > > > > -	    ((filter->input.flags &
> > > > > -	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > > > -	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
> > > > > -	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
> > > > > -	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
> > > > > +	if ((filter->input.flags &
> > > > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
> > > > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
> > > > > +	    (filter->input.flags &
> > > > > I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
> > > > > +	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
> > > > >  		big_buffer = 1;
> > > > >
> > > > >  	if (big_buffer)
> > > > > @@ -2255,3 +2249,97 @@ i40e_status_code
> > > > > i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
> > > > >
> > > > >  	return status;
> > > > >  }
> > > > > +
> > > > > +int
> > > > > +i40e_replace_mpls_l1_filter(struct i40e_pf *pf) {
> > > > > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > > > > +	struct i40e_aqc_replace_cloud_filters_cmd_buf
> filter_replace_buf;
> > > > > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > > > > +	int ret;
> > > > > +
> > > > > +	memset(&filter_replace, 0,
> > > > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > > > > +	memset(&filter_replace_buf, 0,
> > > > > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > > > > +
> > > > > +	/* create L1 filter */
> > > > > +	filter_replace.old_filter_type =
> > > > > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
> > > >
> > > > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC = 12 (0x0C)
> Should
> > > the
> > > > old_filter_type  macro be I40E_AQC_ADD_CLOUD_FILTER_IIP = 0x0C ?
> > >
> > > No, I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC is L1 filter, but
> > the
> > > I40E_AQC_ADD_CLOUD_FILTER_IIP is cloud filter.
> > > We should replace L1 filter here.
> >
> > The I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC macro  (value 12)
> is an
> > index into the Field Vector, it is not a filter type macro.
> > Should a filter type macro be used to set filter_replace.old_filter_type ?
> 
> I think we can check with firmware guy for the detail.
> 
> Beilei

I have checked with firmware, the patch is correct.

Regards,

Bernard.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v2 0/3] add support for MPLS tunnel filter
  2017-03-03  9:43 [PATCH 0/3] enable MPLS cloud filter Beilei Xing
                   ` (2 preceding siblings ...)
  2017-03-03  9:43 ` [PATCH 3/3] net/i40e: enable cloud filter for MPLS Beilei Xing
@ 2017-03-23 10:57 ` Beilei Xing
  2017-03-23 10:57   ` [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items Beilei Xing
                     ` (3 more replies)
  3 siblings, 4 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-23 10:57 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patchset adds support for MPLSoGRE and MPLSoUDP
tunnel filters.
I40e NICs can't recongnize MPLS tunnel packets by
default, so need to load a profile to FW first, then
MPLS tunnel packets can be recongnized with packet
type 61 and 63.
It depends on pipeline personalization profile support
and changes of tunnel filter function.

Beilei Xing (3):
  app/testpmd: add support for MPLS and GRE items
  net/i40e: add MPLS parsing function
  net/i40e: enable tunnel filter for MPLS

 app/test-pmd/cmdline_flow.c                 |  46 +++++
 app/test-pmd/config.c                       |   2 +
 doc/guides/prog_guide/rte_flow.rst          |  20 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c              |  45 +++-
 drivers/net/i40e/i40e_ethdev.h              |  12 ++
 drivers/net/i40e/i40e_flow.c                | 307 ++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h                 |  45 ++++
 8 files changed, 478 insertions(+), 7 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
@ 2017-03-23 10:57   ` Beilei Xing
  2017-03-23 19:39     ` Adrien Mazarguil
  2017-03-23 10:57   ` [PATCH v2 2/3] net/i40e: add MPLS parsing function Beilei Xing
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-23 10:57 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch adds sopport for MPLS and GRE items to generic filter
API.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 46 +++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  2 ++
 doc/guides/prog_guide/rte_flow.rst          | 20 +++++++++++--
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
 lib/librte_ether/rte_flow.h                 | 45 ++++++++++++++++++++++++++++
 5 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ff98690..ff1e47c 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -159,6 +159,10 @@ enum index {
 	ITEM_SCTP_CKSUM,
 	ITEM_VXLAN,
 	ITEM_VXLAN_VNI,
+	ITEM_MPLS,
+	ITEM_MPLS_LABEL,
+	ITEM_GRE,
+	ITEM_GRE_PROTO,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -432,6 +436,8 @@ static const enum index next_item[] = {
 	ITEM_TCP,
 	ITEM_SCTP,
 	ITEM_VXLAN,
+	ITEM_MPLS,
+	ITEM_GRE,
 	ZERO,
 };
 
@@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
 	ZERO,
 };
 
+static const enum index item_mpls[] = {
+	ITEM_MPLS_LABEL,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_gre[] = {
+	ITEM_GRE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1279,6 +1297,34 @@ static const struct token token_list[] = {
 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
 	},
+	[ITEM_MPLS] = {
+		.name = "mpls",
+		.help = "match MPLS header",
+		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+		.next = NEXT(item_mpls),
+		.call = parse_vc,
+	},
+	[ITEM_MPLS_LABEL] = {
+		.name = "label",
+		.help = "MPLS label",
+		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls,
+					     label_tc_s_ttl)),
+	},
+	[ITEM_GRE] = {
+		.name = "gre",
+		.help = "match GRE header",
+		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+		.next = NEXT(item_gre),
+		.call = parse_vc,
+	},
+	[ITEM_GRE_PROTO] = {
+		.name = "protocol",
+		.help = "GRE protocol type",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     protocol)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index eb3d572..90d153e 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -963,6 +963,8 @@ static const struct {
 	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
 	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
 	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3bf8871..45897cd 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -187,8 +187,8 @@ Pattern item
 Pattern items fall in two categories:
 
 - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN, IPV4,
-  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated with a
-  specification structure.
+  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
+  associated with a specification structure.
 
 - Matching meta-data or affecting pattern processing (END, VOID, INVERT, PF,
   VF, PORT and so on), often without a specification structure.
@@ -863,6 +863,22 @@ Matches a VXLAN header (RFC 7348).
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``MPLS``
+^^^^^^^^^^^^^^
+
+Matches a MPLS header.
+
+- ``label_tc_s_ttl``: Lable, TC, Bottom of Stack and TTL.
+- Default ``mask`` matches label only.
+
+Item: ``GRE``
+^^^^^^^^^^^^^^
+
+Matches a GRE header.
+
+- ``c_rsvd0_ver``: Checksum, reserved 0 and version.
+- ``protocol``: Protocol type.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index bdc6a14..f9fa5d6 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2453,6 +2453,14 @@ This section lists supported pattern items and their attributes, if any.
 
   - ``vni {unsigned}``: VXLAN identifier.
 
+- ``mpls``: match MPLS header.
+
+  - ``label {unsigned}``: MPLS label.
+
+- ``gre``: match GRE header.
+
+    - ``protocol {unsigned}``: Protocol type.
+
 Actions list
 ^^^^^^^^^^^^
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 171a569..f855090 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -282,6 +282,20 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_nvgre.
 	 */
 	RTE_FLOW_ITEM_TYPE_NVGRE,
+
+	/**
+	 * Matches a MPLS header.
+	 *
+	 * See struct rte_flow_item_mpls.
+	 */
+	RTE_FLOW_ITEM_TYPE_MPLS,
+
+	/**
+	 * Matches a GRE header.
+	 *
+	 * See struct rte_flow_item_gre.
+	 */
+	RTE_FLOW_ITEM_TYPE_GRE,
 };
 
 /**
@@ -599,6 +613,37 @@ struct rte_flow_item_nvgre {
 };
 
 /**
+ * RTE_FLOW_ITEM_TYPE_MPLS.
+ *
+ * Matches a MPLS header.
+ */
+struct rte_flow_item_mpls {
+	/**
+	 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
+	 */
+	uint32_t label_tc_s_ttl;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
+static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
+	.label_tc_s_ttl = 0xfffff,
+};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_GRE.
+ *
+ * Matches a GRE header.
+ */
+struct rte_flow_item_gre {
+	/**
+	 * Checksum (1b), reserved 0 (12b), version (3b).
+	 * Refer to RFC 2784.
+	 */
+	uint16_t c_rsvd0_ver;
+	uint16_t protocol; /**< Protocol type. */
+};
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 2/3] net/i40e: add MPLS parsing function
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
  2017-03-23 10:57   ` [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items Beilei Xing
@ 2017-03-23 10:57   ` Beilei Xing
  2017-03-23 10:57   ` [PATCH v2 3/3] net/i40e: enable tunnel filter for MPLS Beilei Xing
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
  3 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-23 10:57 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch add MPLS parsing function to support
MPLS filtering.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |   5 +
 drivers/net/i40e/i40e_flow.c   | 217 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 222 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 7d86ca2..df345b1 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -500,6 +500,9 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
+
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
 	I40E_TUNNEL_IPTYPE_IPV6,
@@ -542,6 +545,8 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_MPLSoUDP,
+	I40E_TUNNEL_TYPE_MPLSoGRE,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index ffc14a9..eefb15b 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -57,6 +57,7 @@
 #define I40E_IPV6_FRAG_HEADER	44
 #define I40E_TENANT_ARRAY_NUM	3
 #define I40E_TCI_MASK		0xFFFF
+#define I40E_MPLS_LABEL_MASK	0xFFFFF
 
 static int i40e_flow_validate(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -114,6 +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 					const struct rte_flow_action actions[],
 					struct rte_flow_error *error,
 					union i40e_filter_t *filter);
+static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+				       const struct rte_flow_attr *attr,
+				       const struct rte_flow_item pattern[],
+				       const struct rte_flow_action actions[],
+				       struct rte_flow_error *error,
+				       union i40e_filter_t *filter);
 static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
 				      struct i40e_ethertype_filter *filter);
 static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
@@ -278,6 +285,39 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched MPLS */
+static enum rte_flow_item_type pattern_mpls_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
+	/* MPLSoUDP & MPLSoGRE */
+	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1515,6 +1560,166 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 	return ret;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: MPLS label.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
+			     const struct rte_flow_item *pattern,
+			     struct rte_flow_error *error,
+			     struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item *item = pattern;
+	const struct rte_flow_item_mpls *mpls_spec;
+	const struct rte_flow_item_mpls *mpls_mask;
+	enum rte_flow_item_type item_type;
+	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
+	uint32_t mpls_cpu;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = RTE_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = RTE_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			/* UDP is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid UDP item");
+				return -rte_errno;
+			}
+			is_mplsoudp = 1;
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			/* GRE is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid GRE item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			mpls_spec =
+				(const struct rte_flow_item_mpls *)item->spec;
+			mpls_mask =
+				(const struct rte_flow_item_mpls *)item->mask;
+
+			if (!mpls_spec || !mpls_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid VXLAN item");
+				return -rte_errno;
+			}
+
+			if ((mpls_mask->label_tc_s_ttl &
+			     rte_cpu_to_be_32(I40E_MPLS_LABEL_MASK)) !=
+			    rte_cpu_to_be_32(I40E_MPLS_LABEL_MASK)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid VXLAN mask");
+				return -rte_errno;
+			}
+
+			mpls_cpu = rte_be_to_cpu_32(mpls_spec->label_tc_s_ttl);
+			filter->tenant_id = mpls_cpu & I40E_MPLS_LABEL_MASK;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (is_mplsoudp)
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
+	else
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error,
+			    union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
+					   error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
@@ -1748,6 +1953,18 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
+	if (((filter->input.flags &
+	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
+	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
+	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
+	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
+	    ((filter->input.flags &
+	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
+	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
+	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
+	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
+		big_buffer = 1;
+
 	if (big_buffer)
 		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
 							      &cld_filter, 1);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v2 3/3] net/i40e: enable tunnel filter for MPLS
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
  2017-03-23 10:57   ` [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items Beilei Xing
  2017-03-23 10:57   ` [PATCH v2 2/3] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-23 10:57   ` Beilei Xing
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
  3 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-23 10:57 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, dev

This patch enables MPLS tunnel filter by replacing
inner_mac filter.
This configuration will be set when adding MPLSoUDP
and MPLSoGRE filter rules, and it will be invalid
only by NIC core reset.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c |  45 +++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  11 ++++-
 drivers/net/i40e/i40e_flow.c   | 110 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 149 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 506b957..5e6e2f5 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6954,6 +6954,7 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *tunnel, *node;
 	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+	uint32_t teid_le;
 	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
@@ -7002,6 +7003,32 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	case I40E_TUNNEL_TYPE_IP_IN_GRE:
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
 		break;
+	case I40E_TUNNEL_TYPE_MPLSoUDP:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x40;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+		break;
+	case I40E_TUNNEL_TYPE_MPLSoGRE:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x0;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7009,11 +7036,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		return -EINVAL;
 	}
 
-	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-				       &pfilter->element.flags);
-	if (val < 0) {
-		rte_free(cld_filter);
-		return -EINVAL;
+	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else {
+		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+						&pfilter->element.flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
 	}
 
 	pfilter->element.flags |= rte_cpu_to_le_16(
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index df345b1..934c679 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -500,8 +500,13 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 0x11
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 0x12
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
 
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
@@ -863,6 +868,8 @@ int i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 				  struct i40e_tunnel_filter_conf *tunnel_filter,
 				  uint8_t add);
 int i40e_fdir_flush(struct rte_eth_dev *dev);
+enum i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf);
+enum i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index eefb15b..8d7765a 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1953,16 +1953,10 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
-	if (((filter->input.flags &
-	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP <<
-	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ||
-	    ((filter->input.flags &
-	      (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-	       I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)) ==
-	     (I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE <<
-	      I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT)))
+	if ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP ||
+	    (filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE)
 		big_buffer = 1;
 
 	if (big_buffer)
@@ -2103,3 +2097,99 @@ i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)
 
 	return ret;
 }
+
+enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	filter_replace.old_filter_type =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+	filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace.tr_bit = 0xFF;
+
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0xff;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[7] = 0xf0;
+	filter_replace_buf.data[8] = 0x48;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[10] = 0x4c;
+	filter_replace_buf.data[11] = 0x8c;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
+enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	/* For MPLSoUDP */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (status < 0)
+		return status;
+
+	/* For MPLSoGRE */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items
  2017-03-23 10:57   ` [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items Beilei Xing
@ 2017-03-23 19:39     ` Adrien Mazarguil
  2017-03-24  2:17       ` Xing, Beilei
  0 siblings, 1 reply; 43+ messages in thread
From: Adrien Mazarguil @ 2017-03-23 19:39 UTC (permalink / raw)
  To: Beilei Xing; +Cc: jingjing.wu, helin.zhang, dev

Hi Beilei,

On Thu, Mar 23, 2017 at 06:57:47PM +0800, Beilei Xing wrote:
> This patch adds sopport for MPLS and GRE items to generic filter
> API.

Besides the typo, my previous comment about the title line still stands
("app/testpmd" is not accurate regarding the intent of this patch).

> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  app/test-pmd/cmdline_flow.c                 | 46 +++++++++++++++++++++++++++++
>  app/test-pmd/config.c                       |  2 ++
>  doc/guides/prog_guide/rte_flow.rst          | 20 +++++++++++--
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
>  lib/librte_ether/rte_flow.h                 | 45 ++++++++++++++++++++++++++++
>  5 files changed, 119 insertions(+), 2 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index ff98690..ff1e47c 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -159,6 +159,10 @@ enum index {
>  	ITEM_SCTP_CKSUM,
>  	ITEM_VXLAN,
>  	ITEM_VXLAN_VNI,
> +	ITEM_MPLS,
> +	ITEM_MPLS_LABEL,
> +	ITEM_GRE,
> +	ITEM_GRE_PROTO,
>  
>  	/* Validate/create actions. */
>  	ACTIONS,
> @@ -432,6 +436,8 @@ static const enum index next_item[] = {
>  	ITEM_TCP,
>  	ITEM_SCTP,
>  	ITEM_VXLAN,
> +	ITEM_MPLS,
> +	ITEM_GRE,
>  	ZERO,
>  };
>  
> @@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
>  	ZERO,
>  };
>  
> +static const enum index item_mpls[] = {
> +	ITEM_MPLS_LABEL,
> +	ITEM_NEXT,
> +	ZERO,
> +};
> +
> +static const enum index item_gre[] = {
> +	ITEM_GRE_PROTO,
> +	ITEM_NEXT,
> +	ZERO,
> +};
> +
>  static const enum index next_action[] = {
>  	ACTION_END,
>  	ACTION_VOID,
> @@ -1279,6 +1297,34 @@ static const struct token token_list[] = {
>  		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
>  		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
>  	},
> +	[ITEM_MPLS] = {
> +		.name = "mpls",
> +		.help = "match MPLS header",
> +		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> +		.next = NEXT(item_mpls),
> +		.call = parse_vc,
> +	},
> +	[ITEM_MPLS_LABEL] = {
> +		.name = "label",

I didn't catch this during my previous review, naming it "label" is wrong
because users will actually specify the entire "label_tc_s_ttl" field at
once.

If you really want to name it "label" with the intent of only assigning the
initial 20b, have a look at ITEM_IPV6_TC and ITEM_IPV6_FLOW entries in the
same array.

> +		.help = "MPLS label",
> +		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls,
> +					     label_tc_s_ttl)),
> +	},
> +	[ITEM_GRE] = {
> +		.name = "gre",
> +		.help = "match GRE header",
> +		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> +		.next = NEXT(item_gre),
> +		.call = parse_vc,
> +	},
> +	[ITEM_GRE_PROTO] = {
> +		.name = "protocol",
> +		.help = "GRE protocol type",
> +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> +					     protocol)),
> +	},
>  	/* Validate/create actions. */
>  	[ACTIONS] = {
>  		.name = "actions",
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index eb3d572..90d153e 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -963,6 +963,8 @@ static const struct {
>  	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
>  	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
>  	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
> +	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> +	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
>  };
>  
>  /** Compute storage space needed by item specification. */
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 3bf8871..45897cd 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -187,8 +187,8 @@ Pattern item
>  Pattern items fall in two categories:
>  
>  - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN, IPV4,
> -  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated with a
> -  specification structure.
> +  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
> +  associated with a specification structure.
>  
>  - Matching meta-data or affecting pattern processing (END, VOID, INVERT, PF,
>    VF, PORT and so on), often without a specification structure.
> @@ -863,6 +863,22 @@ Matches a VXLAN header (RFC 7348).
>  - ``rsvd1``: reserved, normally 0x00.
>  - Default ``mask`` matches VNI only.
>  
> +Item: ``MPLS``
> +^^^^^^^^^^^^^^
> +
> +Matches a MPLS header.
> +
> +- ``label_tc_s_ttl``: Lable, TC, Bottom of Stack and TTL.

Typo, "Lable". Also a minor comment, this word should be lower case since it
comes after a colon.

> +- Default ``mask`` matches label only.
> +
> +Item: ``GRE``
> +^^^^^^^^^^^^^^
> +
> +Matches a GRE header.
> +
> +- ``c_rsvd0_ver``: Checksum, reserved 0 and version.
> +- ``protocol``: Protocol type.

"Checksum" and "Protocol" should be lower case.

You must define a default mask as well.

> +[
>  Actions
>  ~~~~~~~
>  
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index bdc6a14..f9fa5d6 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -2453,6 +2453,14 @@ This section lists supported pattern items and their attributes, if any.
>  
>    - ``vni {unsigned}``: VXLAN identifier.
>  
> +- ``mpls``: match MPLS header.
> +
> +  - ``label {unsigned}``: MPLS label.
> +
> +- ``gre``: match GRE header.
> +
> +    - ``protocol {unsigned}``: Protocol type.
> +

Indentation issue, also "Protocol" should be lower case.

>  Actions list
>  ^^^^^^^^^^^^
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 171a569..f855090 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -282,6 +282,20 @@ enum rte_flow_item_type {
>  	 * See struct rte_flow_item_nvgre.
>  	 */
>  	RTE_FLOW_ITEM_TYPE_NVGRE,
> +
> +	/**
> +	 * Matches a MPLS header.
> +	 *
> +	 * See struct rte_flow_item_mpls.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +
> +	/**
> +	 * Matches a GRE header.
> +	 *
> +	 * See struct rte_flow_item_gre.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_GRE,
>  };
>  
>  /**
> @@ -599,6 +613,37 @@ struct rte_flow_item_nvgre {
>  };
>  
>  /**
> + * RTE_FLOW_ITEM_TYPE_MPLS.
> + *
> + * Matches a MPLS header.
> + */
> +struct rte_flow_item_mpls {
> +	/**
> +	 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).

Typo, "Lable".

> +	 */
> +	uint32_t label_tc_s_ttl;
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
> +static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
> +	.label_tc_s_ttl = 0xfffff,
> +};

This default mask is wrong, it has to be specified in network order (you can
include rte_byteorder.h if you need some #ifdef).

> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_GRE.
> + *
> + * Matches a GRE header.
> + */
> +struct rte_flow_item_gre {
> +	/**
> +	 * Checksum (1b), reserved 0 (12b), version (3b).
> +	 * Refer to RFC 2784.
> +	 */
> +	uint16_t c_rsvd0_ver;
> +	uint16_t protocol; /**< Protocol type. */
> +};

Default mask is missing, you must add one.

> +
> +/**
>   * Matching pattern item definition.
>   *
>   * A pattern is formed by stacking items starting from the lowest protocol
> -- 
> 2.5.5
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items
  2017-03-23 19:39     ` Adrien Mazarguil
@ 2017-03-24  2:17       ` Xing, Beilei
  2017-03-24 10:00         ` Adrien Mazarguil
  0 siblings, 1 reply; 43+ messages in thread
From: Xing, Beilei @ 2017-03-24  2:17 UTC (permalink / raw)
  To: Adrien Mazarguil; +Cc: Wu, Jingjing, Zhang, Helin, dev

Hi Adrien,

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Friday, March 24, 2017 3:39 AM
> To: Xing, Beilei <beilei.xing@intel.com>
> Cc: Wu, Jingjing <jingjing.wu@intel.com>; Zhang, Helin
> <helin.zhang@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 1/3] app/testpmd: add support for MPLS
> and GRE items
> 
> Hi Beilei,
> 
> On Thu, Mar 23, 2017 at 06:57:47PM +0800, Beilei Xing wrote:
> > This patch adds sopport for MPLS and GRE items to generic filter API.
> 
> Besides the typo, my previous comment about the title line still stands
> ("app/testpmd" is not accurate regarding the intent of this patch).
> 

OK, I see.
I think it's better to split this patch into two patches, one is for rte_flow, and the other is for testpmd, that'll be more clear.

> >
> > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > ---
> >  app/test-pmd/cmdline_flow.c                 | 46
> +++++++++++++++++++++++++++++
> >  app/test-pmd/config.c                       |  2 ++
> >  doc/guides/prog_guide/rte_flow.rst          | 20 +++++++++++--
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
> >  lib/librte_ether/rte_flow.h                 | 45
> ++++++++++++++++++++++++++++
> >  5 files changed, 119 insertions(+), 2 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > index ff98690..ff1e47c 100644
> > --- a/app/test-pmd/cmdline_flow.c
> > +++ b/app/test-pmd/cmdline_flow.c
> > @@ -159,6 +159,10 @@ enum index {
> >  	ITEM_SCTP_CKSUM,
> >  	ITEM_VXLAN,
> >  	ITEM_VXLAN_VNI,
> > +	ITEM_MPLS,
> > +	ITEM_MPLS_LABEL,
> > +	ITEM_GRE,
> > +	ITEM_GRE_PROTO,
> >
> >  	/* Validate/create actions. */
> >  	ACTIONS,
> > @@ -432,6 +436,8 @@ static const enum index next_item[] = {
> >  	ITEM_TCP,
> >  	ITEM_SCTP,
> >  	ITEM_VXLAN,
> > +	ITEM_MPLS,
> > +	ITEM_GRE,
> >  	ZERO,
> >  };
> >
> > @@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
> >  	ZERO,
> >  };
> >
> > +static const enum index item_mpls[] = {
> > +	ITEM_MPLS_LABEL,
> > +	ITEM_NEXT,
> > +	ZERO,
> > +};
> > +
> > +static const enum index item_gre[] = {
> > +	ITEM_GRE_PROTO,
> > +	ITEM_NEXT,
> > +	ZERO,
> > +};
> > +
> >  static const enum index next_action[] = {
> >  	ACTION_END,
> >  	ACTION_VOID,
> > @@ -1279,6 +1297,34 @@ static const struct token token_list[] = {
> >  		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED),
> item_param),
> >  		.args = ARGS(ARGS_ENTRY_HTON(struct
> rte_flow_item_vxlan, vni)),
> >  	},
> > +	[ITEM_MPLS] = {
> > +		.name = "mpls",
> > +		.help = "match MPLS header",
> > +		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > +		.next = NEXT(item_mpls),
> > +		.call = parse_vc,
> > +	},
> > +	[ITEM_MPLS_LABEL] = {
> > +		.name = "label",
> 
> I didn't catch this during my previous review, naming it "label" is wrong
> because users will actually specify the entire "label_tc_s_ttl" field at once.
> 
> If you really want to name it "label" with the intent of only assigning the initial
> 20b, have a look at ITEM_IPV6_TC and ITEM_IPV6_FLOW entries in the same
> array.
>

Agree, thanks.
 
> > +		.help = "MPLS label",
> > +		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED),
> item_param),
> > +		.args = ARGS(ARGS_ENTRY_HTON(struct
> rte_flow_item_mpls,
> > +					     label_tc_s_ttl)),
> > +	},
> > +	[ITEM_GRE] = {
> > +		.name = "gre",
> > +		.help = "match GRE header",
> > +		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> > +		.next = NEXT(item_gre),
> > +		.call = parse_vc,
> > +	},
> > +	[ITEM_GRE_PROTO] = {
> > +		.name = "protocol",
> > +		.help = "GRE protocol type",
> > +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED),
> item_param),
> > +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> > +					     protocol)),
> > +	},
> >  	/* Validate/create actions. */
> >  	[ACTIONS] = {
> >  		.name = "actions",
> > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index
> > eb3d572..90d153e 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -963,6 +963,8 @@ static const struct {
> >  	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
> >  	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
> >  	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
> > +	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > +	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> >  };
> >
> >  /** Compute storage space needed by item specification. */ diff --git
> > a/doc/guides/prog_guide/rte_flow.rst
> > b/doc/guides/prog_guide/rte_flow.rst
> > index 3bf8871..45897cd 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -187,8 +187,8 @@ Pattern item
> >  Pattern items fall in two categories:
> >
> >  - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN,
> > IPV4,
> > -  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated
> > with a
> > -  specification structure.
> > +  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
> > + associated with a specification structure.
> >
> >  - Matching meta-data or affecting pattern processing (END, VOID, INVERT,
> PF,
> >    VF, PORT and so on), often without a specification structure.
> > @@ -863,6 +863,22 @@ Matches a VXLAN header (RFC 7348).
> >  - ``rsvd1``: reserved, normally 0x00.
> >  - Default ``mask`` matches VNI only.
> >
> > +Item: ``MPLS``
> > +^^^^^^^^^^^^^^
> > +
> > +Matches a MPLS header.
> > +
> > +- ``label_tc_s_ttl``: Lable, TC, Bottom of Stack and TTL.
> 
> Typo, "Lable". Also a minor comment, this word should be lower case since it
> comes after a colon.
> 

Got it, thanks.

> > +- Default ``mask`` matches label only.
> > +
> > +Item: ``GRE``
> > +^^^^^^^^^^^^^^
> > +
> > +Matches a GRE header.
> > +
> > +- ``c_rsvd0_ver``: Checksum, reserved 0 and version.
> > +- ``protocol``: Protocol type.
> 
> "Checksum" and "Protocol" should be lower case.
> 
> You must define a default mask as well.

Yes.

> 
> > +[
> >  Actions
> >  ~~~~~~~
> >
> > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > index bdc6a14..f9fa5d6 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -2453,6 +2453,14 @@ This section lists supported pattern items and
> their attributes, if any.
> >
> >    - ``vni {unsigned}``: VXLAN identifier.
> >
> > +- ``mpls``: match MPLS header.
> > +
> > +  - ``label {unsigned}``: MPLS label.
> > +
> > +- ``gre``: match GRE header.
> > +
> > +    - ``protocol {unsigned}``: Protocol type.
> > +
> 
> Indentation issue, also "Protocol" should be lower case.

Yes.

> 
> >  Actions list
> >  ^^^^^^^^^^^^
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index 171a569..f855090 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -282,6 +282,20 @@ enum rte_flow_item_type {
> >  	 * See struct rte_flow_item_nvgre.
> >  	 */
> >  	RTE_FLOW_ITEM_TYPE_NVGRE,
> > +
> > +	/**
> > +	 * Matches a MPLS header.
> > +	 *
> > +	 * See struct rte_flow_item_mpls.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +
> > +	/**
> > +	 * Matches a GRE header.
> > +	 *
> > +	 * See struct rte_flow_item_gre.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_GRE,
> >  };
> >
> >  /**
> > @@ -599,6 +613,37 @@ struct rte_flow_item_nvgre {  };
> >
> >  /**
> > + * RTE_FLOW_ITEM_TYPE_MPLS.
> > + *
> > + * Matches a MPLS header.
> > + */
> > +struct rte_flow_item_mpls {
> > +	/**
> > +	 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
> 
> Typo, "Lable".
> 
> > +	 */
> > +	uint32_t label_tc_s_ttl;
> > +};
> > +
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */ static const struct
> > +rte_flow_item_mpls rte_flow_item_mpls_mask = {
> > +	.label_tc_s_ttl = 0xfffff,
> > +};
> 
> This default mask is wrong, it has to be specified in network order (you can
> include rte_byteorder.h if you need some #ifdef).

OK, will fix in next version.

> 
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_GRE.
> > + *
> > + * Matches a GRE header.
> > + */
> > +struct rte_flow_item_gre {
> > +	/**
> > +	 * Checksum (1b), reserved 0 (12b), version (3b).
> > +	 * Refer to RFC 2784.
> > +	 */
> > +	uint16_t c_rsvd0_ver;
> > +	uint16_t protocol; /**< Protocol type. */ };
> 
> Default mask is missing, you must add one.

OK.

> 
> > +
> > +/**
> >   * Matching pattern item definition.
> >   *
> >   * A pattern is formed by stacking items starting from the lowest
> > protocol
> > --
> > 2.5.5
> >
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items
  2017-03-24  2:17       ` Xing, Beilei
@ 2017-03-24 10:00         ` Adrien Mazarguil
  0 siblings, 0 replies; 43+ messages in thread
From: Adrien Mazarguil @ 2017-03-24 10:00 UTC (permalink / raw)
  To: Xing, Beilei; +Cc: Wu, Jingjing, Zhang, Helin, dev

On Fri, Mar 24, 2017 at 02:17:42AM +0000, Xing, Beilei wrote:
> Hi Adrien,
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Friday, March 24, 2017 3:39 AM
> > To: Xing, Beilei <beilei.xing@intel.com>
> > Cc: Wu, Jingjing <jingjing.wu@intel.com>; Zhang, Helin
> > <helin.zhang@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v2 1/3] app/testpmd: add support for MPLS
> > and GRE items
> > 
> > Hi Beilei,
> > 
> > On Thu, Mar 23, 2017 at 06:57:47PM +0800, Beilei Xing wrote:
> > > This patch adds sopport for MPLS and GRE items to generic filter API.
> > 
> > Besides the typo, my previous comment about the title line still stands
> > ("app/testpmd" is not accurate regarding the intent of this patch).
> > 
> 
> OK, I see.
> I think it's better to split this patch into two patches, one is for rte_flow, and the other is for testpmd, that'll be more clear.

I prefer having the new API stuff, documentation and testpmd implementation
at once especially since it's not a large patch, but it's your call.

> > >
> > > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > > ---
> > >  app/test-pmd/cmdline_flow.c                 | 46
> > +++++++++++++++++++++++++++++
> > >  app/test-pmd/config.c                       |  2 ++
> > >  doc/guides/prog_guide/rte_flow.rst          | 20 +++++++++++--
> > >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
> > >  lib/librte_ether/rte_flow.h                 | 45
> > ++++++++++++++++++++++++++++
> > >  5 files changed, 119 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > > index ff98690..ff1e47c 100644
> > > --- a/app/test-pmd/cmdline_flow.c
> > > +++ b/app/test-pmd/cmdline_flow.c
> > > @@ -159,6 +159,10 @@ enum index {
> > >  	ITEM_SCTP_CKSUM,
> > >  	ITEM_VXLAN,
> > >  	ITEM_VXLAN_VNI,
> > > +	ITEM_MPLS,
> > > +	ITEM_MPLS_LABEL,
> > > +	ITEM_GRE,
> > > +	ITEM_GRE_PROTO,
> > >
> > >  	/* Validate/create actions. */
> > >  	ACTIONS,
> > > @@ -432,6 +436,8 @@ static const enum index next_item[] = {
> > >  	ITEM_TCP,
> > >  	ITEM_SCTP,
> > >  	ITEM_VXLAN,
> > > +	ITEM_MPLS,
> > > +	ITEM_GRE,
> > >  	ZERO,
> > >  };
> > >
> > > @@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
> > >  	ZERO,
> > >  };
> > >
> > > +static const enum index item_mpls[] = {
> > > +	ITEM_MPLS_LABEL,
> > > +	ITEM_NEXT,
> > > +	ZERO,
> > > +};
> > > +
> > > +static const enum index item_gre[] = {
> > > +	ITEM_GRE_PROTO,
> > > +	ITEM_NEXT,
> > > +	ZERO,
> > > +};
> > > +
> > >  static const enum index next_action[] = {
> > >  	ACTION_END,
> > >  	ACTION_VOID,
> > > @@ -1279,6 +1297,34 @@ static const struct token token_list[] = {
> > >  		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED),
> > item_param),
> > >  		.args = ARGS(ARGS_ENTRY_HTON(struct
> > rte_flow_item_vxlan, vni)),
> > >  	},
> > > +	[ITEM_MPLS] = {
> > > +		.name = "mpls",
> > > +		.help = "match MPLS header",
> > > +		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > > +		.next = NEXT(item_mpls),
> > > +		.call = parse_vc,
> > > +	},
> > > +	[ITEM_MPLS_LABEL] = {
> > > +		.name = "label",
> > 
> > I didn't catch this during my previous review, naming it "label" is wrong
> > because users will actually specify the entire "label_tc_s_ttl" field at once.
> > 
> > If you really want to name it "label" with the intent of only assigning the initial
> > 20b, have a look at ITEM_IPV6_TC and ITEM_IPV6_FLOW entries in the same
> > array.
> >
> 
> Agree, thanks.
>  
> > > +		.help = "MPLS label",
> > > +		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED),
> > item_param),
> > > +		.args = ARGS(ARGS_ENTRY_HTON(struct
> > rte_flow_item_mpls,
> > > +					     label_tc_s_ttl)),
> > > +	},
> > > +	[ITEM_GRE] = {
> > > +		.name = "gre",
> > > +		.help = "match GRE header",
> > > +		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> > > +		.next = NEXT(item_gre),
> > > +		.call = parse_vc,
> > > +	},
> > > +	[ITEM_GRE_PROTO] = {
> > > +		.name = "protocol",
> > > +		.help = "GRE protocol type",
> > > +		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED),
> > item_param),
> > > +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
> > > +					     protocol)),
> > > +	},
> > >  	/* Validate/create actions. */
> > >  	[ACTIONS] = {
> > >  		.name = "actions",
> > > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index
> > > eb3d572..90d153e 100644
> > > --- a/app/test-pmd/config.c
> > > +++ b/app/test-pmd/config.c
> > > @@ -963,6 +963,8 @@ static const struct {
> > >  	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
> > >  	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
> > >  	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
> > > +	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
> > > +	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
> > >  };
> > >
> > >  /** Compute storage space needed by item specification. */ diff --git
> > > a/doc/guides/prog_guide/rte_flow.rst
> > > b/doc/guides/prog_guide/rte_flow.rst
> > > index 3bf8871..45897cd 100644
> > > --- a/doc/guides/prog_guide/rte_flow.rst
> > > +++ b/doc/guides/prog_guide/rte_flow.rst
> > > @@ -187,8 +187,8 @@ Pattern item
> > >  Pattern items fall in two categories:
> > >
> > >  - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN,
> > > IPV4,
> > > -  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated
> > > with a
> > > -  specification structure.
> > > +  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
> > > + associated with a specification structure.
> > >
> > >  - Matching meta-data or affecting pattern processing (END, VOID, INVERT,
> > PF,
> > >    VF, PORT and so on), often without a specification structure.
> > > @@ -863,6 +863,22 @@ Matches a VXLAN header (RFC 7348).
> > >  - ``rsvd1``: reserved, normally 0x00.
> > >  - Default ``mask`` matches VNI only.
> > >
> > > +Item: ``MPLS``
> > > +^^^^^^^^^^^^^^
> > > +
> > > +Matches a MPLS header.
> > > +
> > > +- ``label_tc_s_ttl``: Lable, TC, Bottom of Stack and TTL.
> > 
> > Typo, "Lable". Also a minor comment, this word should be lower case since it
> > comes after a colon.
> > 
> 
> Got it, thanks.
> 
> > > +- Default ``mask`` matches label only.
> > > +
> > > +Item: ``GRE``
> > > +^^^^^^^^^^^^^^
> > > +
> > > +Matches a GRE header.
> > > +
> > > +- ``c_rsvd0_ver``: Checksum, reserved 0 and version.
> > > +- ``protocol``: Protocol type.
> > 
> > "Checksum" and "Protocol" should be lower case.
> > 
> > You must define a default mask as well.
> 
> Yes.
> 
> > 
> > > +[
> > >  Actions
> > >  ~~~~~~~
> > >
> > > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > > index bdc6a14..f9fa5d6 100644
> > > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > > @@ -2453,6 +2453,14 @@ This section lists supported pattern items and
> > their attributes, if any.
> > >
> > >    - ``vni {unsigned}``: VXLAN identifier.
> > >
> > > +- ``mpls``: match MPLS header.
> > > +
> > > +  - ``label {unsigned}``: MPLS label.
> > > +
> > > +- ``gre``: match GRE header.
> > > +
> > > +    - ``protocol {unsigned}``: Protocol type.
> > > +
> > 
> > Indentation issue, also "Protocol" should be lower case.
> 
> Yes.
> 
> > 
> > >  Actions list
> > >  ^^^^^^^^^^^^
> > >
> > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > index 171a569..f855090 100644
> > > --- a/lib/librte_ether/rte_flow.h
> > > +++ b/lib/librte_ether/rte_flow.h
> > > @@ -282,6 +282,20 @@ enum rte_flow_item_type {
> > >  	 * See struct rte_flow_item_nvgre.
> > >  	 */
> > >  	RTE_FLOW_ITEM_TYPE_NVGRE,
> > > +
> > > +	/**
> > > +	 * Matches a MPLS header.
> > > +	 *
> > > +	 * See struct rte_flow_item_mpls.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > > +
> > > +	/**
> > > +	 * Matches a GRE header.
> > > +	 *
> > > +	 * See struct rte_flow_item_gre.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_GRE,
> > >  };
> > >
> > >  /**
> > > @@ -599,6 +613,37 @@ struct rte_flow_item_nvgre {  };
> > >
> > >  /**
> > > + * RTE_FLOW_ITEM_TYPE_MPLS.
> > > + *
> > > + * Matches a MPLS header.
> > > + */
> > > +struct rte_flow_item_mpls {
> > > +	/**
> > > +	 * Lable (20b), TC (3b), Bottom of Stack (1b), TTL (8b).
> > 
> > Typo, "Lable".
> > 
> > > +	 */
> > > +	uint32_t label_tc_s_ttl;
> > > +};
> > > +
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */ static const struct
> > > +rte_flow_item_mpls rte_flow_item_mpls_mask = {
> > > +	.label_tc_s_ttl = 0xfffff,
> > > +};
> > 
> > This default mask is wrong, it has to be specified in network order (you can
> > include rte_byteorder.h if you need some #ifdef).
> 
> OK, will fix in next version.

Another note, you could use uint8_t[] to mitigate the endianness issue,
e.g.:

 struct rte_flow_item_mpls {
     /**
      * Label (20b), TC (3b), Bottom of Stack (1b).
      */
     uint8_t label_tc_s[3];
     uint8_t ttl; /** Time-to-Live. */
 };

 /** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
 static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
     .label_tc_s = "\xff\xff\xf0",
 };

> 
> > 
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_GRE.
> > > + *
> > > + * Matches a GRE header.
> > > + */
> > > +struct rte_flow_item_gre {
> > > +	/**
> > > +	 * Checksum (1b), reserved 0 (12b), version (3b).
> > > +	 * Refer to RFC 2784.
> > > +	 */
> > > +	uint16_t c_rsvd0_ver;
> > > +	uint16_t protocol; /**< Protocol type. */ };
> > 
> > Default mask is missing, you must add one.
> 
> OK.
> 
> > 
> > > +
> > > +/**
> > >   * Matching pattern item definition.
> > >   *
> > >   * A pattern is formed by stacking items starting from the lowest
> > > protocol
> > > --
> > > 2.5.5
> > >
> > 
> > --
> > Adrien Mazarguil
> > 6WIND

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v3 0/4] add support for MPLS tunnel filter
  2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
                     ` (2 preceding siblings ...)
  2017-03-23 10:57   ` [PATCH v2 3/3] net/i40e: enable tunnel filter for MPLS Beilei Xing
@ 2017-03-28  6:40   ` Beilei Xing
  2017-03-28  6:40     ` [PATCH v3 1/4] ethdev: add MPLS and GRE items Beilei Xing
                       ` (4 more replies)
  3 siblings, 5 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-28  6:40 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patchset adds support for MPLSoGRE and MPLSoUDP
tunnel filters.
I40e NICs can't recongnize MPLS tunnel packets by
default, so need to load a profile to FW first, then
MPLS tunnel packets can be recongnized with packet
type 61 and 63.
It depends on pipeline personalization profile support
and changes of tunnel filter function.

v3 changes:
 Add big_buffer condition to this patchset.
 Change some descriptions for new MPLS and GRE items.
 Fix default mask error for MPLS label.

Beilei Xing (4):
  ethdev: add MPLS and GRE items
  app/testpmd: add MPLS and GRE fields to flow command
  net/i40e: add MPLS parsing function
  net/i40e: enable tunnel filter for MPLS

 app/test-pmd/cmdline_flow.c                 |  47 ++++++
 app/test-pmd/config.c                       |   2 +
 doc/guides/prog_guide/rte_flow.rst          |  21 ++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c              | 171 +++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h              |  10 ++
 drivers/net/i40e/i40e_flow.c                | 222 +++++++++++++++++++++++++++-
 lib/librte_ether/rte_flow.h                 |  51 +++++++
 8 files changed, 518 insertions(+), 14 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v3 1/4] ethdev: add MPLS and GRE items
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
@ 2017-03-28  6:40     ` Beilei Xing
  2017-03-28 12:28       ` Adrien Mazarguil
  2017-03-28  6:40     ` [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
                       ` (3 subsequent siblings)
  4 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-28  6:40 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch adds MPLS and GRE items to generic rte flow.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 21 ++++++++++++++--
 lib/librte_ether/rte_flow.h        | 51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3bf8871..5ee045e 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -187,8 +187,8 @@ Pattern item
 Pattern items fall in two categories:
 
 - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN, IPV4,
-  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated with a
-  specification structure.
+  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
+  associated with a specification structure.
 
 - Matching meta-data or affecting pattern processing (END, VOID, INVERT, PF,
   VF, PORT and so on), often without a specification structure.
@@ -863,6 +863,23 @@ Matches a VXLAN header (RFC 7348).
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``MPLS``
+^^^^^^^^^^^^^^
+
+Matches a MPLS header.
+
+- ``label_tc_s_ttl``: label, TC, Bottom of Stack and TTL.
+- Default ``mask`` matches label only.
+
+Item: ``GRE``
+^^^^^^^^^^^^^^
+
+Matches a GRE header.
+
+- ``c_rsvd0_ver``: checksum, reserved 0 and version.
+- ``protocol``: protocol type.
+- Default ``mask`` matches protocol only.
+
 Actions
 ~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 171a569..8013eca 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -282,6 +282,20 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_nvgre.
 	 */
 	RTE_FLOW_ITEM_TYPE_NVGRE,
+
+	/**
+	 * Matches a MPLS header.
+	 *
+	 * See struct rte_flow_item_mpls.
+	 */
+	RTE_FLOW_ITEM_TYPE_MPLS,
+
+	/**
+	 * Matches a GRE header.
+	 *
+	 * See struct rte_flow_item_gre.
+	 */
+	RTE_FLOW_ITEM_TYPE_GRE,
 };
 
 /**
@@ -599,6 +613,43 @@ struct rte_flow_item_nvgre {
 };
 
 /**
+ * RTE_FLOW_ITEM_TYPE_MPLS.
+ *
+ * Matches a MPLS header.
+ */
+struct rte_flow_item_mpls {
+	/**
+	 * Label (20b), TC (3b), Bottom of Stack (1b).
+	 */
+	uint8_t label_tc_s[3];
+	uint8_t ttl; /** Time-to-Live. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
+static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
+	.label_tc_s = "\xff\xff\xf0",
+};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_GRE.
+ *
+ * Matches a GRE header.
+ */
+struct rte_flow_item_gre {
+	/**
+	 * Checksum (1b), reserved 0 (12b), version (3b).
+	 * Refer to RFC 2784.
+	 */
+	uint16_t c_rsvd0_ver;
+	uint16_t protocol; /**< Protocol type. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_GRE. */
+static const struct rte_flow_item_gre rte_flow_item_gre_mask = {
+	.protocol = 0xffff,
+};
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-28  6:40     ` [PATCH v3 1/4] ethdev: add MPLS and GRE items Beilei Xing
@ 2017-03-28  6:40     ` Beilei Xing
  2017-03-28 12:29       ` Adrien Mazarguil
  2017-03-28  6:40     ` [PATCH v3 3/4] net/i40e: add MPLS parsing function Beilei Xing
                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-28  6:40 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

    This patch exposes the following item fields through the flow command:

    - MPLS label
    - GRE protocol

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 47 +++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  2 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
 3 files changed, 57 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ff98690..2149df4 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -159,6 +159,10 @@ enum index {
 	ITEM_SCTP_CKSUM,
 	ITEM_VXLAN,
 	ITEM_VXLAN_VNI,
+	ITEM_MPLS,
+	ITEM_MPLS_LABEL,
+	ITEM_GRE,
+	ITEM_GRE_PROTO,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -432,6 +436,8 @@ static const enum index next_item[] = {
 	ITEM_TCP,
 	ITEM_SCTP,
 	ITEM_VXLAN,
+	ITEM_MPLS,
+	ITEM_GRE,
 	ZERO,
 };
 
@@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
 	ZERO,
 };
 
+static const enum index item_mpls[] = {
+	ITEM_MPLS_LABEL,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_gre[] = {
+	ITEM_GRE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1279,6 +1297,35 @@ static const struct token token_list[] = {
 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
 	},
+	[ITEM_MPLS] = {
+		.name = "mpls",
+		.help = "match MPLS header",
+		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+		.next = NEXT(item_mpls),
+		.call = parse_vc,
+	},
+	[ITEM_MPLS_LABEL] = {
+		.name = "label",
+		.help = "MPLS label",
+		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+						  label_tc_s,
+						  "\xff\xff\xf0")),
+	},
+	[ITEM_GRE] = {
+		.name = "gre",
+		.help = "match GRE header",
+		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+		.next = NEXT(item_gre),
+		.call = parse_vc,
+	},
+	[ITEM_GRE_PROTO] = {
+		.name = "protocol",
+		.help = "GRE protocol type",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     protocol)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index eb3d572..90d153e 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -963,6 +963,8 @@ static const struct {
 	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
 	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
 	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index bdc6a14..1f4fd46 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2453,6 +2453,14 @@ This section lists supported pattern items and their attributes, if any.
 
   - ``vni {unsigned}``: VXLAN identifier.
 
+- ``mpls``: match MPLS header.
+
+  - ``label {unsigned}``: MPLS label.
+
+- ``gre``: match GRE header.
+
+  - ``protocol {unsigned}``: protocol type.
+
 Actions list
 ^^^^^^^^^^^^
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 3/4] net/i40e: add MPLS parsing function
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-28  6:40     ` [PATCH v3 1/4] ethdev: add MPLS and GRE items Beilei Xing
  2017-03-28  6:40     ` [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
@ 2017-03-28  6:40     ` Beilei Xing
  2017-03-28  6:40     ` [PATCH v3 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
  4 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-28  6:40 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch add MPLS parsing function to support
MPLS filtering.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |   2 +
 drivers/net/i40e/i40e_flow.c   | 234 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 235 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f917b0c..7cd80ff 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -542,6 +542,8 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_MPLSoUDP,
+	I40E_TUNNEL_TYPE_MPLSoGRE,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 148e519..c9b9b3b 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -57,6 +57,7 @@
 #define I40E_IPV6_FRAG_HEADER	44
 #define I40E_TENANT_ARRAY_NUM	3
 #define I40E_TCI_MASK		0xFFFF
+#define I40E_MPLS_LABEL_MASK	0xFFFFF
 
 static int i40e_flow_validate(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -114,6 +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 					const struct rte_flow_action actions[],
 					struct rte_flow_error *error,
 					union i40e_filter_t *filter);
+static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+				       const struct rte_flow_attr *attr,
+				       const struct rte_flow_item pattern[],
+				       const struct rte_flow_action actions[],
+				       struct rte_flow_error *error,
+				       union i40e_filter_t *filter);
 static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
 				      struct i40e_ethertype_filter *filter);
 static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
@@ -278,6 +285,39 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched MPLS */
+static enum rte_flow_item_type pattern_mpls_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
+	/* MPLSoUDP & MPLSoGRE */
+	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1516,6 +1561,193 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_check_label_mask(const uint8_t *mask)
+{
+	uint32_t j;
+	int is_masked = 0;
+
+	for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
+		if (*(mask + j) == 0) {
+			if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+				return -EINVAL;
+			is_masked = 1;
+		} else if (*(mask + j) == UINT8_MAX) {
+			if (j == 2)
+				return -EINVAL;
+		} else if (*(mask + j) == 0xF0) {
+			if (j != 2)
+				return -EINVAL;
+			is_masked = 0;
+		} else
+			return -EINVAL;
+	}
+
+	return is_masked;
+}
+
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: MPLS label.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
+			     const struct rte_flow_item *pattern,
+			     struct rte_flow_error *error,
+			     struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item *item = pattern;
+	const struct rte_flow_item_mpls *mpls_spec;
+	const struct rte_flow_item_mpls *mpls_mask;
+	enum rte_flow_item_type item_type;
+	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
+	int is_label_masked = 0;
+	uint32_t label_be = 0;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			/* UDP is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid UDP item");
+				return -rte_errno;
+			}
+			is_mplsoudp = 1;
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			/* GRE is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid GRE item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			mpls_spec =
+				(const struct rte_flow_item_mpls *)item->spec;
+			mpls_mask =
+				(const struct rte_flow_item_mpls *)item->mask;
+
+			if (!mpls_spec || !mpls_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS item");
+				return -rte_errno;
+			}
+
+			is_label_masked =
+				i40e_check_label_mask(mpls_mask->label_tc_s);
+
+			if (is_label_masked != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS label mask");
+				return -rte_errno;
+			}
+			rte_memcpy(((uint8_t *)&label_be + 1),
+				   mpls_spec->label_tc_s, 3);
+			filter->tenant_id = rte_be_to_cpu_32(label_be) >> 4;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (is_mplsoudp)
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
+	else
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error,
+			    union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
+					   error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
+static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
 		   const struct rte_flow_item pattern[],
@@ -1750,7 +1982,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 					   &cld_filter.element, 1);
 	if (ret < 0)
-		return ret;
+		return -ENOTSUP;
 
 	node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
 	if (!node)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
                       ` (2 preceding siblings ...)
  2017-03-28  6:40     ` [PATCH v3 3/4] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-28  6:40     ` Beilei Xing
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
  4 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-28  6:40 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch enables MPLS tunnel filter by replacing
inner_mac filter.
This configuration will be set when adding MPLSoUDP
and MPLSoGRE filter rules, and it will be invalid
only by NIC core reset.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c |  75 ++++++++++++++++++++++++----
 drivers/net/i40e/i40e_ethdev.h |  10 ++++
 drivers/net/i40e/i40e_flow.c   | 111 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 185 insertions(+), 11 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8f6d2d2..54f33d9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6945,6 +6945,8 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *tunnel, *node;
 	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+	uint32_t teid_le;
+	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
 			 sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
@@ -6992,6 +6994,32 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	case I40E_TUNNEL_TYPE_IP_IN_GRE:
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
 		break;
+	case I40E_TUNNEL_TYPE_MPLSoUDP:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x40;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+		break;
+	case I40E_TUNNEL_TYPE_MPLSoGRE:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x0;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -6999,11 +7027,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		return -EINVAL;
 	}
 
-	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-				       &pfilter->element.flags);
-	if (val < 0) {
-		rte_free(cld_filter);
-		return -EINVAL;
+	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else {
+		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+						&pfilter->element.flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
 	}
 
 	pfilter->element.flags |= rte_cpu_to_le_16(
@@ -7039,7 +7075,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	}
 
 	if (add) {
-		ret = i40e_aq_add_cloud_filters(hw,
+		if (big_buffer)
+			ret = i40e_aq_add_cloud_filters_big_buffer(hw,
+						   vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_add_cloud_filters(hw,
 					vsi->seid, &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
@@ -7049,7 +7089,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
 		ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
 	} else {
-		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+		if (big_buffer)
+			ret = i40e_aq_remove_cloud_filters_big_buffer(
+				hw, vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 						   &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
@@ -10435,6 +10479,7 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		*tunnel_list = &pf->tunnel.tunnel_list;
 	struct i40e_tunnel_filter *f;
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
+	bool big_buffer = 0;
 
 	TAILQ_FOREACH(f, tunnel_list, rules) {
 		memset(&cld_filter, 0, sizeof(cld_filter));
@@ -10450,8 +10495,20 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 			   f->input.general_fields,
 			   sizeof(f->input.general_fields));
 
-		i40e_aq_add_cloud_filters(hw, vsi->seid,
-					  &cld_filter.element, 1);
+		if (((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+			big_buffer = 1;
+
+		if (big_buffer)
+			i40e_aq_add_cloud_filters_big_buffer(hw,
+					     vsi->seid, &cld_filter, 1);
+		else
+			i40e_aq_add_cloud_filters(hw, vsi->seid,
+						  &cld_filter.element, 1);
 	}
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 7cd80ff..738d238 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -500,6 +500,14 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
+
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
 	I40E_TUNNEL_IPTYPE_IPV6,
@@ -855,6 +863,8 @@ int i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 				  struct i40e_tunnel_filter_conf *tunnel_filter,
 				  uint8_t add);
 int i40e_fdir_flush(struct rte_eth_dev *dev);
+enum i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf);
+enum i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index c9b9b3b..be243e1 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1964,6 +1964,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *node;
+	bool big_buffer = 0;
 	int ret = 0;
 
 	memset(&cld_filter, 0, sizeof(cld_filter));
@@ -1979,8 +1980,18 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
-	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
-					   &cld_filter.element, 1);
+	if (((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+	     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		big_buffer = 1;
+
+	if (big_buffer)
+		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
+							      &cld_filter, 1);
+	else
+		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+						   &cld_filter.element, 1);
 	if (ret < 0)
 		return -ENOTSUP;
 
@@ -2113,3 +2124,99 @@ i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)
 
 	return ret;
 }
+
+enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	filter_replace.old_filter_type =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+	filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace.tr_bit = 0xFF;
+
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0xff;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[7] = 0xf0;
+	filter_replace_buf.data[8] = 0x48;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[10] = 0x4c;
+	filter_replace_buf.data[11] = 0x8c;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
+enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	/* For MPLSoUDP */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (status < 0)
+		return status;
+
+	/* For MPLSoGRE */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 1/4] ethdev: add MPLS and GRE items
  2017-03-28  6:40     ` [PATCH v3 1/4] ethdev: add MPLS and GRE items Beilei Xing
@ 2017-03-28 12:28       ` Adrien Mazarguil
  0 siblings, 0 replies; 43+ messages in thread
From: Adrien Mazarguil @ 2017-03-28 12:28 UTC (permalink / raw)
  To: Beilei Xing; +Cc: jingjing.wu, helin.zhang, bernard.iremonger, dev

On Tue, Mar 28, 2017 at 02:40:05PM +0800, Beilei Xing wrote:
> This patch adds MPLS and GRE items to generic rte flow.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  doc/guides/prog_guide/rte_flow.rst | 21 ++++++++++++++--
>  lib/librte_ether/rte_flow.h        | 51 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+), 2 deletions(-)

Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command
  2017-03-28  6:40     ` [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
@ 2017-03-28 12:29       ` Adrien Mazarguil
  0 siblings, 0 replies; 43+ messages in thread
From: Adrien Mazarguil @ 2017-03-28 12:29 UTC (permalink / raw)
  To: Beilei Xing; +Cc: jingjing.wu, helin.zhang, bernard.iremonger, dev

On Tue, Mar 28, 2017 at 02:40:06PM +0800, Beilei Xing wrote:
>     This patch exposes the following item fields through the flow command:
> 
>     - MPLS label
>     - GRE protocol
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  app/test-pmd/cmdline_flow.c                 | 47 +++++++++++++++++++++++++++++
>  app/test-pmd/config.c                       |  2 ++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
>  3 files changed, 57 insertions(+)

Besides the strange indentation of the commit log,

Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v4 0/4] add support for MPLS tunnel filter
  2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
                       ` (3 preceding siblings ...)
  2017-03-28  6:40     ` [PATCH v3 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
@ 2017-03-30  4:07     ` Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 1/4] ethdev: add MPLS and GRE items Beilei Xing
                         ` (4 more replies)
  4 siblings, 5 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  4:07 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patchset adds support for MPLSoGRE and MPLSoUDP
tunnel filters.
I40e NICs can't recongnize MPLS tunnel packets by
default, so need to load a profile to FW first, then
MPLS tunnel packets can be recongnized with packet
type 61 and 63.
It depends on pipeline personalization profile support
and changes of tunnel filter function.

v4 changes:
 Move replace functions to i40e_ethdev.c.

v3 changes:
 Add big_buffer condition to this patchset.
 Change some descriptions for new MPLS and GRE items.
 Fix default mask error for MPLS label.

Beilei Xing (4):
  ethdev: add MPLS and GRE items
  app/testpmd: add MPLS and GRE fields to flow command
  net/i40e: add MPLS parsing function
  net/i40e: enable tunnel filter for MPLS

 app/test-pmd/cmdline_flow.c                 |  47 ++++++
 app/test-pmd/config.c                       |   2 +
 doc/guides/prog_guide/rte_flow.rst          |  21 ++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c              | 184 +++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h              |  10 ++
 drivers/net/i40e/i40e_flow.c                | 249 +++++++++++++++++++++++++++-
 lib/librte_ether/rte_flow.h                 |  51 ++++++
 8 files changed, 558 insertions(+), 14 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v4 1/4] ethdev: add MPLS and GRE items
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
@ 2017-03-30  4:07       ` Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  4:07 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch adds MPLS and GRE items to generic rte flow.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 doc/guides/prog_guide/rte_flow.rst | 21 ++++++++++++++--
 lib/librte_ether/rte_flow.h        | 51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3bf8871..5ee045e 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -187,8 +187,8 @@ Pattern item
 Pattern items fall in two categories:
 
 - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN, IPV4,
-  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated with a
-  specification structure.
+  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
+  associated with a specification structure.
 
 - Matching meta-data or affecting pattern processing (END, VOID, INVERT, PF,
   VF, PORT and so on), often without a specification structure.
@@ -863,6 +863,23 @@ Matches a VXLAN header (RFC 7348).
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``MPLS``
+^^^^^^^^^^^^^^
+
+Matches a MPLS header.
+
+- ``label_tc_s_ttl``: label, TC, Bottom of Stack and TTL.
+- Default ``mask`` matches label only.
+
+Item: ``GRE``
+^^^^^^^^^^^^^^
+
+Matches a GRE header.
+
+- ``c_rsvd0_ver``: checksum, reserved 0 and version.
+- ``protocol``: protocol type.
+- Default ``mask`` matches protocol only.
+
 Actions
 ~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 171a569..8013eca 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -282,6 +282,20 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_nvgre.
 	 */
 	RTE_FLOW_ITEM_TYPE_NVGRE,
+
+	/**
+	 * Matches a MPLS header.
+	 *
+	 * See struct rte_flow_item_mpls.
+	 */
+	RTE_FLOW_ITEM_TYPE_MPLS,
+
+	/**
+	 * Matches a GRE header.
+	 *
+	 * See struct rte_flow_item_gre.
+	 */
+	RTE_FLOW_ITEM_TYPE_GRE,
 };
 
 /**
@@ -599,6 +613,43 @@ struct rte_flow_item_nvgre {
 };
 
 /**
+ * RTE_FLOW_ITEM_TYPE_MPLS.
+ *
+ * Matches a MPLS header.
+ */
+struct rte_flow_item_mpls {
+	/**
+	 * Label (20b), TC (3b), Bottom of Stack (1b).
+	 */
+	uint8_t label_tc_s[3];
+	uint8_t ttl; /** Time-to-Live. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
+static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
+	.label_tc_s = "\xff\xff\xf0",
+};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_GRE.
+ *
+ * Matches a GRE header.
+ */
+struct rte_flow_item_gre {
+	/**
+	 * Checksum (1b), reserved 0 (12b), version (3b).
+	 * Refer to RFC 2784.
+	 */
+	uint16_t c_rsvd0_ver;
+	uint16_t protocol; /**< Protocol type. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_GRE. */
+static const struct rte_flow_item_gre rte_flow_item_gre_mask = {
+	.protocol = 0xffff,
+};
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v4 2/4] app/testpmd: add MPLS and GRE fields to flow command
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 1/4] ethdev: add MPLS and GRE items Beilei Xing
@ 2017-03-30  4:07       ` Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 3/4] net/i40e: add MPLS parsing function Beilei Xing
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  4:07 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch exposes the following item fields through the flow command:

 - MPLS label
 - GRE protocol

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 app/test-pmd/cmdline_flow.c                 | 47 +++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  2 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
 3 files changed, 57 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ff98690..2149df4 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -159,6 +159,10 @@ enum index {
 	ITEM_SCTP_CKSUM,
 	ITEM_VXLAN,
 	ITEM_VXLAN_VNI,
+	ITEM_MPLS,
+	ITEM_MPLS_LABEL,
+	ITEM_GRE,
+	ITEM_GRE_PROTO,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -432,6 +436,8 @@ static const enum index next_item[] = {
 	ITEM_TCP,
 	ITEM_SCTP,
 	ITEM_VXLAN,
+	ITEM_MPLS,
+	ITEM_GRE,
 	ZERO,
 };
 
@@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
 	ZERO,
 };
 
+static const enum index item_mpls[] = {
+	ITEM_MPLS_LABEL,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_gre[] = {
+	ITEM_GRE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1279,6 +1297,35 @@ static const struct token token_list[] = {
 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
 	},
+	[ITEM_MPLS] = {
+		.name = "mpls",
+		.help = "match MPLS header",
+		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+		.next = NEXT(item_mpls),
+		.call = parse_vc,
+	},
+	[ITEM_MPLS_LABEL] = {
+		.name = "label",
+		.help = "MPLS label",
+		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+						  label_tc_s,
+						  "\xff\xff\xf0")),
+	},
+	[ITEM_GRE] = {
+		.name = "gre",
+		.help = "match GRE header",
+		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+		.next = NEXT(item_gre),
+		.call = parse_vc,
+	},
+	[ITEM_GRE_PROTO] = {
+		.name = "protocol",
+		.help = "GRE protocol type",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     protocol)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 9865bf1..780ce6b 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -963,6 +963,8 @@ static const struct {
 	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
 	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
 	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f08a795..62478d6 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2481,6 +2481,14 @@ This section lists supported pattern items and their attributes, if any.
 
   - ``vni {unsigned}``: VXLAN identifier.
 
+- ``mpls``: match MPLS header.
+
+  - ``label {unsigned}``: MPLS label.
+
+- ``gre``: match GRE header.
+
+  - ``protocol {unsigned}``: protocol type.
+
 Actions list
 ^^^^^^^^^^^^
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v4 3/4] net/i40e: add MPLS parsing function
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 1/4] ethdev: add MPLS and GRE items Beilei Xing
  2017-03-30  4:07       ` [PATCH v4 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
@ 2017-03-30  4:07       ` Beilei Xing
  2017-03-30  6:04         ` Wu, Jingjing
  2017-03-30  4:07       ` [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
  4 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  4:07 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch add MPLS parsing function to support
MPLS filtering.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |   2 +
 drivers/net/i40e/i40e_flow.c   | 234 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 235 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 9aacff7..dec1bd6 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -543,6 +543,8 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_MPLSoUDP,
+	I40E_TUNNEL_TYPE_MPLSoGRE,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 148e519..c9b9b3b 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -57,6 +57,7 @@
 #define I40E_IPV6_FRAG_HEADER	44
 #define I40E_TENANT_ARRAY_NUM	3
 #define I40E_TCI_MASK		0xFFFF
+#define I40E_MPLS_LABEL_MASK	0xFFFFF
 
 static int i40e_flow_validate(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -114,6 +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 					const struct rte_flow_action actions[],
 					struct rte_flow_error *error,
 					union i40e_filter_t *filter);
+static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+				       const struct rte_flow_attr *attr,
+				       const struct rte_flow_item pattern[],
+				       const struct rte_flow_action actions[],
+				       struct rte_flow_error *error,
+				       union i40e_filter_t *filter);
 static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
 				      struct i40e_ethertype_filter *filter);
 static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
@@ -278,6 +285,39 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched MPLS */
+static enum rte_flow_item_type pattern_mpls_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
+	/* MPLSoUDP & MPLSoGRE */
+	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1516,6 +1561,193 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_check_label_mask(const uint8_t *mask)
+{
+	uint32_t j;
+	int is_masked = 0;
+
+	for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
+		if (*(mask + j) == 0) {
+			if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+				return -EINVAL;
+			is_masked = 1;
+		} else if (*(mask + j) == UINT8_MAX) {
+			if (j == 2)
+				return -EINVAL;
+		} else if (*(mask + j) == 0xF0) {
+			if (j != 2)
+				return -EINVAL;
+			is_masked = 0;
+		} else
+			return -EINVAL;
+	}
+
+	return is_masked;
+}
+
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: MPLS label.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
+			     const struct rte_flow_item *pattern,
+			     struct rte_flow_error *error,
+			     struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item *item = pattern;
+	const struct rte_flow_item_mpls *mpls_spec;
+	const struct rte_flow_item_mpls *mpls_mask;
+	enum rte_flow_item_type item_type;
+	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
+	int is_label_masked = 0;
+	uint32_t label_be = 0;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			/* UDP is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid UDP item");
+				return -rte_errno;
+			}
+			is_mplsoudp = 1;
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			/* GRE is used to describe protocol,
+			 * spec amd mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid GRE item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			mpls_spec =
+				(const struct rte_flow_item_mpls *)item->spec;
+			mpls_mask =
+				(const struct rte_flow_item_mpls *)item->mask;
+
+			if (!mpls_spec || !mpls_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS item");
+				return -rte_errno;
+			}
+
+			is_label_masked =
+				i40e_check_label_mask(mpls_mask->label_tc_s);
+
+			if (is_label_masked != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS label mask");
+				return -rte_errno;
+			}
+			rte_memcpy(((uint8_t *)&label_be + 1),
+				   mpls_spec->label_tc_s, 3);
+			filter->tenant_id = rte_be_to_cpu_32(label_be) >> 4;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (is_mplsoudp)
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
+	else
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error,
+			    union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
+					   error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
+static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
 		   const struct rte_flow_item pattern[],
@@ -1750,7 +1982,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 					   &cld_filter.element, 1);
 	if (ret < 0)
-		return ret;
+		return -ENOTSUP;
 
 	node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
 	if (!node)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
                         ` (2 preceding siblings ...)
  2017-03-30  4:07       ` [PATCH v4 3/4] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-30  4:07       ` Beilei Xing
  2017-03-30  6:16         ` Wu, Jingjing
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
  4 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  4:07 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

MPLSoUDP & MPLSoGRE is not supported by tunnel
filter due to limited resource of HW, this patch
enables MPLS tunnel filter by replacing inner_mac
filter.
This configuration will be set when adding MPLSoUDP
and MPLSoGRE filter rules, and it will be invalid
only by NIC core reset.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 184 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |   8 ++
 drivers/net/i40e/i40e_flow.c   |  15 +++-
 3 files changed, 196 insertions(+), 11 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 60926f0..700738f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6935,6 +6935,115 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 	return ret;
 }
 
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0 0x48
+#define I40E_TR_VXLAN_GRE_KEY_MASK		0x4
+#define I40E_TR_GENEVE_KEY_MASK			0x8
+#define I40E_TR_GENERIC_UDP_TUNNEL_MASK		0x40
+#define I40E_TR_GRE_KEY_MASK			0x400
+#define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
+#define I40E_TR_GRE_NO_KEY_MASK			0x8000
+
+static enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	filter_replace.old_filter_type =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+	filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace.tr_bit = 0xFF;
+
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0xFF;
+	filter_replace_buf.data[3] = 0xFF;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[7] = 0xF0;
+	filter_replace_buf.data[8]
+		= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[10] = I40E_TR_VXLAN_GRE_KEY_MASK |
+		I40E_TR_GENEVE_KEY_MASK |
+		I40E_TR_GENERIC_UDP_TUNNEL_MASK;
+	filter_replace_buf.data[11] = (I40E_TR_GRE_KEY_MASK |
+		I40E_TR_GRE_KEY_WITH_XSUM_MASK |
+		I40E_TR_GRE_NO_KEY_MASK) >> 8;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
+static enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	/* For MPLSoUDP */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (status < 0)
+		return status;
+
+	/* For MPLSoGRE */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -6954,6 +7063,8 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *tunnel, *node;
 	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+	uint32_t teid_le;
+	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
 			 sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
@@ -7001,6 +7112,32 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	case I40E_TUNNEL_TYPE_IP_IN_GRE:
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
 		break;
+	case I40E_TUNNEL_TYPE_MPLSoUDP:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x40;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+		break;
+	case I40E_TUNNEL_TYPE_MPLSoGRE:
+		i40e_replace_mpls_l1_filter(pf);
+		i40e_replace_mpls_cloud_filter(pf);
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x0;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7008,11 +7145,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		return -EINVAL;
 	}
 
-	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-				       &pfilter->element.flags);
-	if (val < 0) {
-		rte_free(cld_filter);
-		return -EINVAL;
+	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else {
+		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+						&pfilter->element.flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
 	}
 
 	pfilter->element.flags |= rte_cpu_to_le_16(
@@ -7048,7 +7193,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	}
 
 	if (add) {
-		ret = i40e_aq_add_cloud_filters(hw,
+		if (big_buffer)
+			ret = i40e_aq_add_cloud_filters_big_buffer(hw,
+						   vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_add_cloud_filters(hw,
 					vsi->seid, &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
@@ -7058,7 +7207,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
 		ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
 	} else {
-		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+		if (big_buffer)
+			ret = i40e_aq_remove_cloud_filters_big_buffer(
+				hw, vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 						   &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
@@ -10444,6 +10597,7 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		*tunnel_list = &pf->tunnel.tunnel_list;
 	struct i40e_tunnel_filter *f;
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
+	bool big_buffer = 0;
 
 	TAILQ_FOREACH(f, tunnel_list, rules) {
 		memset(&cld_filter, 0, sizeof(cld_filter));
@@ -10459,8 +10613,20 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 			   f->input.general_fields,
 			   sizeof(f->input.general_fields));
 
-		i40e_aq_add_cloud_filters(hw, vsi->seid,
-					  &cld_filter.element, 1);
+		if (((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+			big_buffer = 1;
+
+		if (big_buffer)
+			i40e_aq_add_cloud_filters_big_buffer(hw,
+					     vsi->seid, &cld_filter, 1);
+		else
+			i40e_aq_add_cloud_filters(hw, vsi->seid,
+						  &cld_filter.element, 1);
 	}
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index dec1bd6..bf3a943 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -501,6 +501,14 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
+
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
 	I40E_TUNNEL_IPTYPE_IPV6,
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index c9b9b3b..f4efa4a 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1964,6 +1964,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *node;
+	bool big_buffer = 0;
 	int ret = 0;
 
 	memset(&cld_filter, 0, sizeof(cld_filter));
@@ -1979,8 +1980,18 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
-	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
-					   &cld_filter.element, 1);
+	if (((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+	     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		big_buffer = 1;
+
+	if (big_buffer)
+		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
+							      &cld_filter, 1);
+	else
+		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+						   &cld_filter.element, 1);
 	if (ret < 0)
 		return -ENOTSUP;
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v4 3/4] net/i40e: add MPLS parsing function
  2017-03-30  4:07       ` [PATCH v4 3/4] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-30  6:04         ` Wu, Jingjing
  2017-03-30  6:35           ` Xing, Beilei
  0 siblings, 1 reply; 43+ messages in thread
From: Wu, Jingjing @ 2017-03-30  6:04 UTC (permalink / raw)
  To: Xing, Beilei; +Cc: Zhang, Helin, Iremonger, Bernard, dev



> -----Original Message-----
> From: Xing, Beilei
> Sent: Thursday, March 30, 2017 12:08 PM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: [PATCH v4 3/4] net/i40e: add MPLS parsing function
> 
> This patch add MPLS parsing function to support MPLS filtering.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.h |   2 +
>  drivers/net/i40e/i40e_flow.c   | 234
> ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 235 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> index 9aacff7..dec1bd6 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -543,6 +543,8 @@ enum i40e_tunnel_type {
>  	I40E_TUNNEL_TYPE_NVGRE,
>  	I40E_TUNNEL_TYPE_IP_IN_GRE,
>  	I40E_L2_TUNNEL_TYPE_E_TAG,
> +	I40E_TUNNEL_TYPE_MPLSoUDP,
> +	I40E_TUNNEL_TYPE_MPLSoGRE,
>  	I40E_TUNNEL_TYPE_MAX,
>  };
> 
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index
> 148e519..c9b9b3b 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -57,6 +57,7 @@
>  #define I40E_IPV6_FRAG_HEADER	44
>  #define I40E_TENANT_ARRAY_NUM	3
>  #define I40E_TCI_MASK		0xFFFF
> +#define I40E_MPLS_LABEL_MASK	0xFFFFF
> 
>  static int i40e_flow_validate(struct rte_eth_dev *dev,
>  			      const struct rte_flow_attr *attr, @@ -114,6
> +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
>  					const struct rte_flow_action actions[],
>  					struct rte_flow_error *error,
>  					union i40e_filter_t *filter);
> +static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
> +				       const struct rte_flow_attr *attr,
> +				       const struct rte_flow_item pattern[],
> +				       const struct rte_flow_action actions[],
> +				       struct rte_flow_error *error,
> +				       union i40e_filter_t *filter);
>  static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
>  				      struct i40e_ethertype_filter *filter);  static
> int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf, @@ -278,6 +285,39 @@
> static enum rte_flow_item_type pattern_vxlan_4[] = {
>  	RTE_FLOW_ITEM_TYPE_END,
>  };
> 
> +/* Pattern matched MPLS */
> +static enum rte_flow_item_type pattern_mpls_1[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_mpls_2[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_mpls_3[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_GRE,
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_mpls_4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_GRE,
> +	RTE_FLOW_ITEM_TYPE_MPLS,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
>  static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	/* Ethertype */
>  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -303,6
> +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
>  	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
>  	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
> +	/* MPLSoUDP & MPLSoGRE */
> +	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
> +	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
> +	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
> +	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
>  };
> 
>  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> @@ -1516,6 +1561,193 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev
> *dev,  }
> 
>  static int
> +i40e_check_label_mask(const uint8_t *mask) {
> +	uint32_t j;
> +	int is_masked = 0;
> +
> +	for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
> +		if (*(mask + j) == 0) {
> +			if (j > 0 && (*(mask + j) != *(mask + j - 1)))
> +				return -EINVAL;
> +			is_masked = 1;
> +		} else if (*(mask + j) == UINT8_MAX) {
> +			if (j == 2)
> +				return -EINVAL;
> +		} else if (*(mask + j) == 0xF0) {
> +			if (j != 2)
> +				return -EINVAL;
> +			is_masked = 0;
> +		} else
> +			return -EINVAL;
> +	}
Do you want to check if the mask is {00, 00, 00} or {FF, FF, F0}?
Why not just compare the mask with two constant array?
This function is difficult to understand.
> +	return is_masked;
> +}
> +
> +/* 1. Last in item should be NULL as range is not supported.
> + * 2. Supported filter types: MPLS label.
> + * 3. Mask of fields which need to be matched should be
> + *    filled with 1.
> + * 4. Mask of fields which needn't to be matched should be
> + *    filled with 0.
> + */
> +static int
> +i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
> +			     const struct rte_flow_item *pattern,
> +			     struct rte_flow_error *error,
> +			     struct i40e_tunnel_filter_conf *filter) {
> +	const struct rte_flow_item *item = pattern;
> +	const struct rte_flow_item_mpls *mpls_spec;
> +	const struct rte_flow_item_mpls *mpls_mask;
> +	enum rte_flow_item_type item_type;
> +	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
> +	int is_label_masked = 0;
> +	uint32_t label_be = 0;
> +
> +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> +		if (item->last) {
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Not support range");
> +			return -rte_errno;
> +		}
> +		item_type = item->type;
> +		switch (item_type) {
> +		case RTE_FLOW_ITEM_TYPE_ETH:
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ETH item");
> +				return -rte_errno;
> +			}
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV4:
> +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
> +			/* IPv4 is used to describe protocol,
> +			 * spec amd mask should be NULL.
Typo: amd->and
> +			 */
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid IPv4 item");
> +				return -rte_errno;
> +			}
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV6:
> +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
> +			/* IPv6 is used to describe protocol,
> +			 * spec amd mask should be NULL.
> +			 */
Typo: amd->and
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid IPv6 item");
> +				return -rte_errno;
> +			}
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_UDP:
> +			/* UDP is used to describe protocol,
> +			 * spec amd mask should be NULL.
> +			 */
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid UDP item");
> +				return -rte_errno;
> +			}
> +			is_mplsoudp = 1;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_GRE:
> +			/* GRE is used to describe protocol,
> +			 * spec amd mask should be NULL.
> +			 */
Typo: amd->and
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid GRE item");
> +				return -rte_errno;
> +			}
> +			break;

You are checking (item->spec || item->mask) in all above cases.
Can we merge them to:
case RTE_FLOW_ITEM_TYPE_ETH:
case RTE_FLOW_ITEM_TYPE_IPV4:
case RTE_FLOW_ITEM_TYPE_IPV6:
case RTE_FLOW_ITEM_TYPE_UDP:
case RTE_FLOW_ITEM_TYPE_GRE:
	if (item->spec || item->mask) {
		......
	}
	break;
> +		case RTE_FLOW_ITEM_TYPE_MPLS:
> +			mpls_spec =
> +				(const struct rte_flow_item_mpls *)item->spec;
> +			mpls_mask =
> +				(const struct rte_flow_item_mpls *)item-
> >mask;
> +
> +			if (!mpls_spec || !mpls_mask) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid MPLS item");
> +				return -rte_errno;
> +			}
> +
> +			is_label_masked =
> +				i40e_check_label_mask(mpls_mask-
> >label_tc_s);
> +
> +			if (is_label_masked != 0) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid MPLS label mask");
> +				return -rte_errno;
> +			}
> +			rte_memcpy(((uint8_t *)&label_be + 1),
> +				   mpls_spec->label_tc_s, 3);
> +			filter->tenant_id = rte_be_to_cpu_32(label_be) >> 4;
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +
> +	if (is_mplsoudp)
> +		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
> +	else
> +		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
> +			    const struct rte_flow_attr *attr,
> +			    const struct rte_flow_item pattern[],
> +			    const struct rte_flow_action actions[],
> +			    struct rte_flow_error *error,
> +			    union i40e_filter_t *filter)
> +{
> +	struct i40e_tunnel_filter_conf *tunnel_filter =
> +		&filter->consistent_tunnel_filter;
> +	int ret;
> +
> +	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
> +					   error, tunnel_filter);
> +	if (ret)
> +		return ret;
> +
> +	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
> +	if (ret)
> +		return ret;
> +
> +	ret = i40e_flow_parse_attr(attr, error);
> +	if (ret)
> +		return ret;
> +
> +	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
> +
> +	return ret;
> +}
> +
> +static int
>  i40e_flow_validate(struct rte_eth_dev *dev,
>  		   const struct rte_flow_attr *attr,
>  		   const struct rte_flow_item pattern[], @@ -1750,7 +1982,7
> @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
>  	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
>  					   &cld_filter.element, 1);
>  	if (ret < 0)
> -		return ret;
> +		return -ENOTSUP;
> 
>  	node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
>  	if (!node)
> --
> 2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-30  4:07       ` [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
@ 2017-03-30  6:16         ` Wu, Jingjing
  2017-03-30  6:20           ` Xing, Beilei
  0 siblings, 1 reply; 43+ messages in thread
From: Wu, Jingjing @ 2017-03-30  6:16 UTC (permalink / raw)
  To: Xing, Beilei; +Cc: Zhang, Helin, Iremonger, Bernard, dev

>  int
>  i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  		      struct i40e_tunnel_filter_conf *tunnel_filter, @@ -6954,6
> +7063,8 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
>  	struct i40e_tunnel_filter *tunnel, *node;
>  	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
> +	uint32_t teid_le;
> +	bool big_buffer = 0;
> 
>  	cld_filter = rte_zmalloc("tunnel_filter",
>  			 sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
> @@ -7001,6 +7112,32 @@ i40e_dev_consistent_tunnel_filter_set(struct
> i40e_pf *pf,
>  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
>  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
>  		break;
> +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> +		i40e_replace_mpls_l1_filter(pf);
> +		i40e_replace_mpls_cloud_filter(pf);
Do we need replace every time when add each rule?

Thanks
Jingjing

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-30  6:16         ` Wu, Jingjing
@ 2017-03-30  6:20           ` Xing, Beilei
  0 siblings, 0 replies; 43+ messages in thread
From: Xing, Beilei @ 2017-03-30  6:20 UTC (permalink / raw)
  To: Wu, Jingjing; +Cc: Zhang, Helin, Iremonger, Bernard, dev



> -----Original Message-----
> From: Wu, Jingjing
> Sent: Thursday, March 30, 2017 2:17 PM
> To: Xing, Beilei <beilei.xing@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: RE: [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS
> 
> >  int
> >  i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >  		      struct i40e_tunnel_filter_conf *tunnel_filter, @@ -6954,6
> > +7063,8 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >  	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
> >  	struct i40e_tunnel_filter *tunnel, *node;
> >  	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
> > +	uint32_t teid_le;
> > +	bool big_buffer = 0;
> >
> >  	cld_filter = rte_zmalloc("tunnel_filter",
> >  			 sizeof(struct
> i40e_aqc_add_rm_cloud_filt_elem_ext),
> > @@ -7001,6 +7112,32 @@ i40e_dev_consistent_tunnel_filter_set(struct
> > i40e_pf *pf,
> >  	case I40E_TUNNEL_TYPE_IP_IN_GRE:
> >  		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
> >  		break;
> > +	case I40E_TUNNEL_TYPE_MPLSoUDP:
> > +		i40e_replace_mpls_l1_filter(pf);
> > +		i40e_replace_mpls_cloud_filter(pf);
> Do we need replace every time when add each rule?

No, I will add a flag to distinguish it.

> 
> Thanks
> Jingjing

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v4 3/4] net/i40e: add MPLS parsing function
  2017-03-30  6:04         ` Wu, Jingjing
@ 2017-03-30  6:35           ` Xing, Beilei
  0 siblings, 0 replies; 43+ messages in thread
From: Xing, Beilei @ 2017-03-30  6:35 UTC (permalink / raw)
  To: Wu, Jingjing; +Cc: Zhang, Helin, Iremonger, Bernard, dev



> -----Original Message-----
> From: Wu, Jingjing
> Sent: Thursday, March 30, 2017 2:04 PM
> To: Xing, Beilei <beilei.xing@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: RE: [PATCH v4 3/4] net/i40e: add MPLS parsing function
> 
> 
> 
> > -----Original Message-----
> > From: Xing, Beilei
> > Sent: Thursday, March 30, 2017 12:08 PM
> > To: Wu, Jingjing <jingjing.wu@intel.com>
> > Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> > <bernard.iremonger@intel.com>; dev@dpdk.org
> > Subject: [PATCH v4 3/4] net/i40e: add MPLS parsing function
> >
> > This patch add MPLS parsing function to support MPLS filtering.
> >
> > Signed-off-by: Beilei Xing <beilei.xing@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.h |   2 +
> >  drivers/net/i40e/i40e_flow.c   | 234
> > ++++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 235 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index 9aacff7..dec1bd6 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -543,6 +543,8 @@ enum i40e_tunnel_type {
> >  	I40E_TUNNEL_TYPE_NVGRE,
> >  	I40E_TUNNEL_TYPE_IP_IN_GRE,
> >  	I40E_L2_TUNNEL_TYPE_E_TAG,
> > +	I40E_TUNNEL_TYPE_MPLSoUDP,
> > +	I40E_TUNNEL_TYPE_MPLSoGRE,
> >  	I40E_TUNNEL_TYPE_MAX,
> >  };
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c
> > b/drivers/net/i40e/i40e_flow.c index 148e519..c9b9b3b 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> > @@ -57,6 +57,7 @@
> >  #define I40E_IPV6_FRAG_HEADER	44
> >  #define I40E_TENANT_ARRAY_NUM	3
> >  #define I40E_TCI_MASK		0xFFFF
> > +#define I40E_MPLS_LABEL_MASK	0xFFFFF
> >
> >  static int i40e_flow_validate(struct rte_eth_dev *dev,
> >  			      const struct rte_flow_attr *attr, @@ -114,6
> > +115,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev
> > +*dev,
> >  					const struct rte_flow_action actions[],
> >  					struct rte_flow_error *error,
> >  					union i40e_filter_t *filter);
> > +static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
> > +				       const struct rte_flow_attr *attr,
> > +				       const struct rte_flow_item pattern[],
> > +				       const struct rte_flow_action actions[],
> > +				       struct rte_flow_error *error,
> > +				       union i40e_filter_t *filter);
> >  static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
> >  				      struct i40e_ethertype_filter *filter);  static
> int
> > i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf, @@ -278,6 +285,39
> > @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
> >  	RTE_FLOW_ITEM_TYPE_END,
> >  };
> >
> > +/* Pattern matched MPLS */
> > +static enum rte_flow_item_type pattern_mpls_1[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_IPV4,
> > +	RTE_FLOW_ITEM_TYPE_UDP,
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> > +static enum rte_flow_item_type pattern_mpls_2[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_IPV6,
> > +	RTE_FLOW_ITEM_TYPE_UDP,
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> > +static enum rte_flow_item_type pattern_mpls_3[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_IPV4,
> > +	RTE_FLOW_ITEM_TYPE_GRE,
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> > +static enum rte_flow_item_type pattern_mpls_4[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_IPV6,
> > +	RTE_FLOW_ITEM_TYPE_GRE,
> > +	RTE_FLOW_ITEM_TYPE_MPLS,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> >  static struct i40e_valid_pattern i40e_supported_patterns[] = {
> >  	/* Ethertype */
> >  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -303,6
> > +343,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[]
> > += {
> >  	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
> >  	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
> >  	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
> > +	/* MPLSoUDP & MPLSoGRE */
> > +	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
> > +	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
> > +	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
> > +	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
> >  };
> >
> >  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> > @@ -1516,6 +1561,193 @@ i40e_flow_parse_vxlan_filter(struct
> > rte_eth_dev *dev,  }
> >
> >  static int
> > +i40e_check_label_mask(const uint8_t *mask) {
> > +	uint32_t j;
> > +	int is_masked = 0;
> > +
> > +	for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
> > +		if (*(mask + j) == 0) {
> > +			if (j > 0 && (*(mask + j) != *(mask + j - 1)))
> > +				return -EINVAL;
> > +			is_masked = 1;
> > +		} else if (*(mask + j) == UINT8_MAX) {
> > +			if (j == 2)
> > +				return -EINVAL;
> > +		} else if (*(mask + j) == 0xF0) {
> > +			if (j != 2)
> > +				return -EINVAL;
> > +			is_masked = 0;
> > +		} else
> > +			return -EINVAL;
> > +	}
> Do you want to check if the mask is {00, 00, 00} or {FF, FF, F0}?
> Why not just compare the mask with two constant array?
> This function is difficult to understand.
Yes, make sense, and actually we only care about {0xFF, 0xFF, 0xF0}. I will remove the function and judge it in parse function.

> > +	return is_masked;
> > +}
> > +
> > +/* 1. Last in item should be NULL as range is not supported.
> > + * 2. Supported filter types: MPLS label.
> > + * 3. Mask of fields which need to be matched should be
> > + *    filled with 1.
> > + * 4. Mask of fields which needn't to be matched should be
> > + *    filled with 0.
> > + */
> > +static int
> > +i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
> > +			     const struct rte_flow_item *pattern,
> > +			     struct rte_flow_error *error,
> > +			     struct i40e_tunnel_filter_conf *filter) {
> > +	const struct rte_flow_item *item = pattern;
> > +	const struct rte_flow_item_mpls *mpls_spec;
> > +	const struct rte_flow_item_mpls *mpls_mask;
> > +	enum rte_flow_item_type item_type;
> > +	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
> > +	int is_label_masked = 0;
> > +	uint32_t label_be = 0;
> > +
> > +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> > +		if (item->last) {
> > +			rte_flow_error_set(error, EINVAL,
> > +					   RTE_FLOW_ERROR_TYPE_ITEM,
> > +					   item,
> > +					   "Not support range");
> > +			return -rte_errno;
> > +		}
> > +		item_type = item->type;
> > +		switch (item_type) {
> > +		case RTE_FLOW_ITEM_TYPE_ETH:
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid ETH item");
> > +				return -rte_errno;
> > +			}
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV4:
> > +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
> > +			/* IPv4 is used to describe protocol,
> > +			 * spec amd mask should be NULL.
> Typo: amd->and
> > +			 */
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid IPv4 item");
> > +				return -rte_errno;
> > +			}
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV6:
> > +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
> > +			/* IPv6 is used to describe protocol,
> > +			 * spec amd mask should be NULL.
> > +			 */
> Typo: amd->and
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid IPv6 item");
> > +				return -rte_errno;
> > +			}
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_UDP:
> > +			/* UDP is used to describe protocol,
> > +			 * spec amd mask should be NULL.
> > +			 */
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid UDP item");
> > +				return -rte_errno;
> > +			}
> > +			is_mplsoudp = 1;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_GRE:
> > +			/* GRE is used to describe protocol,
> > +			 * spec amd mask should be NULL.
> > +			 */
> Typo: amd->and
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid GRE item");
> > +				return -rte_errno;
> > +			}
> > +			break;
> 
> You are checking (item->spec || item->mask) in all above cases.
> Can we merge them to:
> case RTE_FLOW_ITEM_TYPE_ETH:
> case RTE_FLOW_ITEM_TYPE_IPV4:
> case RTE_FLOW_ITEM_TYPE_IPV6:
> case RTE_FLOW_ITEM_TYPE_UDP:
> case RTE_FLOW_ITEM_TYPE_GRE:

The error info returned to user is different, and different flag need to be set.

> 	if (item->spec || item->mask) {
> 		......
> 	}
> 	break;
> > +		case RTE_FLOW_ITEM_TYPE_MPLS:
> > +			mpls_spec =
> > +				(const struct rte_flow_item_mpls *)item-
> >spec;
> > +			mpls_mask =
> > +				(const struct rte_flow_item_mpls *)item-
> > >mask;
> > +
> > +			if (!mpls_spec || !mpls_mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid MPLS item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			is_label_masked =
> > +				i40e_check_label_mask(mpls_mask-
> > >label_tc_s);
> > +
> > +			if (is_label_masked != 0) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid MPLS label mask");
> > +				return -rte_errno;
> > +			}
> > +			rte_memcpy(((uint8_t *)&label_be + 1),
> > +				   mpls_spec->label_tc_s, 3);
> > +			filter->tenant_id = rte_be_to_cpu_32(label_be) >> 4;
> > +			break;
> > +		default:
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (is_mplsoudp)
> > +		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
> > +	else
> > +		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
> > +			    const struct rte_flow_attr *attr,
> > +			    const struct rte_flow_item pattern[],
> > +			    const struct rte_flow_action actions[],
> > +			    struct rte_flow_error *error,
> > +			    union i40e_filter_t *filter)
> > +{
> > +	struct i40e_tunnel_filter_conf *tunnel_filter =
> > +		&filter->consistent_tunnel_filter;
> > +	int ret;
> > +
> > +	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
> > +					   error, tunnel_filter);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = i40e_flow_parse_tunnel_action(dev, actions, error,
> tunnel_filter);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = i40e_flow_parse_attr(attr, error);
> > +	if (ret)
> > +		return ret;
> > +
> > +	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> >  i40e_flow_validate(struct rte_eth_dev *dev,
> >  		   const struct rte_flow_attr *attr,
> >  		   const struct rte_flow_item pattern[], @@ -1750,7 +1982,7
> @@
> > i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
> >  	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
> >  					   &cld_filter.element, 1);
> >  	if (ret < 0)
> > -		return ret;
> > +		return -ENOTSUP;
> >
> >  	node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
> >  	if (!node)
> > --
> > 2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 0/4] add support for MPLS tunnel filter
  2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
                         ` (3 preceding siblings ...)
  2017-03-30  4:07       ` [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
@ 2017-03-30  6:56       ` Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 1/4] ethdev: add MPLS and GRE items Beilei Xing
                           ` (3 more replies)
  4 siblings, 4 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  6:56 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patchset adds support for MPLSoGRE and MPLSoUDP
tunnel filters.
I40e NICs can't recongnize MPLS tunnel packets by
default, so need to load a profile to FW first, then
MPLS tunnel packets can be recongnized with packet
type 61 and 63.
It depends on pipeline personalization profile support
and changes of tunnel filter function.

v5 changes:
 Rework MPLS parse function.
 Add replace filter flag for MPLS.

v4 changes:
 Move replace functions to i40e_ethdev.c.

v3 changes:
 Add big_buffer condition to this patchset.
 Change some descriptions for new MPLS and GRE items.
 Fix default mask error for MPLS label.

Beilei Xing (4):
  ethdev: add MPLS and GRE items
  app/testpmd: add MPLS and GRE fields to flow command
  net/i40e: add MPLS parsing function
  net/i40e: enable tunnel filter for MPLS

 app/test-pmd/cmdline_flow.c                 |  47 ++++++
 app/test-pmd/config.c                       |   2 +
 doc/guides/prog_guide/rte_flow.rst          |  21 ++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c              | 190 ++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h              |  11 ++
 drivers/net/i40e/i40e_flow.c                | 221 +++++++++++++++++++++++++++-
 lib/librte_ether/rte_flow.h                 |  51 +++++++
 8 files changed, 537 insertions(+), 14 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 1/4] ethdev: add MPLS and GRE items
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
@ 2017-03-30  6:56         ` Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  6:56 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch adds MPLS and GRE items to generic rte flow.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 doc/guides/prog_guide/rte_flow.rst | 21 ++++++++++++++--
 lib/librte_ether/rte_flow.h        | 51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3bf8871..5ee045e 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -187,8 +187,8 @@ Pattern item
 Pattern items fall in two categories:
 
 - Matching protocol headers and packet data (ANY, RAW, ETH, VLAN, IPV4,
-  IPV6, ICMP, UDP, TCP, SCTP, VXLAN and so on), usually associated with a
-  specification structure.
+  IPV6, ICMP, UDP, TCP, SCTP, VXLAN, MPLS, GRE and so on), usually
+  associated with a specification structure.
 
 - Matching meta-data or affecting pattern processing (END, VOID, INVERT, PF,
   VF, PORT and so on), often without a specification structure.
@@ -863,6 +863,23 @@ Matches a VXLAN header (RFC 7348).
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``MPLS``
+^^^^^^^^^^^^^^
+
+Matches a MPLS header.
+
+- ``label_tc_s_ttl``: label, TC, Bottom of Stack and TTL.
+- Default ``mask`` matches label only.
+
+Item: ``GRE``
+^^^^^^^^^^^^^^
+
+Matches a GRE header.
+
+- ``c_rsvd0_ver``: checksum, reserved 0 and version.
+- ``protocol``: protocol type.
+- Default ``mask`` matches protocol only.
+
 Actions
 ~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 171a569..8013eca 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -282,6 +282,20 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_nvgre.
 	 */
 	RTE_FLOW_ITEM_TYPE_NVGRE,
+
+	/**
+	 * Matches a MPLS header.
+	 *
+	 * See struct rte_flow_item_mpls.
+	 */
+	RTE_FLOW_ITEM_TYPE_MPLS,
+
+	/**
+	 * Matches a GRE header.
+	 *
+	 * See struct rte_flow_item_gre.
+	 */
+	RTE_FLOW_ITEM_TYPE_GRE,
 };
 
 /**
@@ -599,6 +613,43 @@ struct rte_flow_item_nvgre {
 };
 
 /**
+ * RTE_FLOW_ITEM_TYPE_MPLS.
+ *
+ * Matches a MPLS header.
+ */
+struct rte_flow_item_mpls {
+	/**
+	 * Label (20b), TC (3b), Bottom of Stack (1b).
+	 */
+	uint8_t label_tc_s[3];
+	uint8_t ttl; /** Time-to-Live. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_MPLS. */
+static const struct rte_flow_item_mpls rte_flow_item_mpls_mask = {
+	.label_tc_s = "\xff\xff\xf0",
+};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_GRE.
+ *
+ * Matches a GRE header.
+ */
+struct rte_flow_item_gre {
+	/**
+	 * Checksum (1b), reserved 0 (12b), version (3b).
+	 * Refer to RFC 2784.
+	 */
+	uint16_t c_rsvd0_ver;
+	uint16_t protocol; /**< Protocol type. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_GRE. */
+static const struct rte_flow_item_gre rte_flow_item_gre_mask = {
+	.protocol = 0xffff,
+};
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v5 2/4] app/testpmd: add MPLS and GRE fields to flow command
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 1/4] ethdev: add MPLS and GRE items Beilei Xing
@ 2017-03-30  6:56         ` Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 3/4] net/i40e: add MPLS parsing function Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
  3 siblings, 0 replies; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  6:56 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch exposes the following item fields through the flow command:

 - MPLS label
 - GRE protocol

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 app/test-pmd/cmdline_flow.c                 | 47 +++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  2 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++++
 3 files changed, 57 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index ff98690..2149df4 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -159,6 +159,10 @@ enum index {
 	ITEM_SCTP_CKSUM,
 	ITEM_VXLAN,
 	ITEM_VXLAN_VNI,
+	ITEM_MPLS,
+	ITEM_MPLS_LABEL,
+	ITEM_GRE,
+	ITEM_GRE_PROTO,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -432,6 +436,8 @@ static const enum index next_item[] = {
 	ITEM_TCP,
 	ITEM_SCTP,
 	ITEM_VXLAN,
+	ITEM_MPLS,
+	ITEM_GRE,
 	ZERO,
 };
 
@@ -538,6 +544,18 @@ static const enum index item_vxlan[] = {
 	ZERO,
 };
 
+static const enum index item_mpls[] = {
+	ITEM_MPLS_LABEL,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_gre[] = {
+	ITEM_GRE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1279,6 +1297,35 @@ static const struct token token_list[] = {
 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
 	},
+	[ITEM_MPLS] = {
+		.name = "mpls",
+		.help = "match MPLS header",
+		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+		.next = NEXT(item_mpls),
+		.call = parse_vc,
+	},
+	[ITEM_MPLS_LABEL] = {
+		.name = "label",
+		.help = "MPLS label",
+		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+						  label_tc_s,
+						  "\xff\xff\xf0")),
+	},
+	[ITEM_GRE] = {
+		.name = "gre",
+		.help = "match GRE header",
+		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+		.next = NEXT(item_gre),
+		.call = parse_vc,
+	},
+	[ITEM_GRE_PROTO] = {
+		.name = "protocol",
+		.help = "GRE protocol type",
+		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+					     protocol)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 9865bf1..780ce6b 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -963,6 +963,8 @@ static const struct {
 	MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
 	MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
 	MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+	MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+	MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f08a795..62478d6 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -2481,6 +2481,14 @@ This section lists supported pattern items and their attributes, if any.
 
   - ``vni {unsigned}``: VXLAN identifier.
 
+- ``mpls``: match MPLS header.
+
+  - ``label {unsigned}``: MPLS label.
+
+- ``gre``: match GRE header.
+
+  - ``protocol {unsigned}``: protocol type.
+
 Actions list
 ^^^^^^^^^^^^
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v5 3/4] net/i40e: add MPLS parsing function
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 1/4] ethdev: add MPLS and GRE items Beilei Xing
  2017-03-30  6:56         ` [PATCH v5 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
@ 2017-03-30  6:56         ` Beilei Xing
  2017-03-30  8:22           ` Wu, Jingjing
  2017-03-30  6:56         ` [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
  3 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  6:56 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

This patch add MPLS parsing function to support
MPLS filtering.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |   2 +
 drivers/net/i40e/i40e_flow.c   | 205 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 206 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 9aacff7..dec1bd6 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -543,6 +543,8 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_MPLSoUDP,
+	I40E_TUNNEL_TYPE_MPLSoGRE,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 148e519..d5c705e 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -114,6 +114,12 @@ static int i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 					const struct rte_flow_action actions[],
 					struct rte_flow_error *error,
 					union i40e_filter_t *filter);
+static int i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+				       const struct rte_flow_attr *attr,
+				       const struct rte_flow_item pattern[],
+				       const struct rte_flow_action actions[],
+				       struct rte_flow_error *error,
+				       union i40e_filter_t *filter);
 static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
 				      struct i40e_ethertype_filter *filter);
 static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
@@ -278,6 +284,39 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched MPLS */
+static enum rte_flow_item_type pattern_mpls_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_2[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_mpls_4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_GRE,
+	RTE_FLOW_ITEM_TYPE_MPLS,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +342,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_vxlan_2, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_3, i40e_flow_parse_vxlan_filter },
 	{ pattern_vxlan_4, i40e_flow_parse_vxlan_filter },
+	/* MPLSoUDP & MPLSoGRE */
+	{ pattern_mpls_1, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
+	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1515,6 +1559,165 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 	return ret;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: MPLS label.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_mpls_pattern(__rte_unused struct rte_eth_dev *dev,
+			     const struct rte_flow_item *pattern,
+			     struct rte_flow_error *error,
+			     struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item *item = pattern;
+	const struct rte_flow_item_mpls *mpls_spec;
+	const struct rte_flow_item_mpls *mpls_mask;
+	enum rte_flow_item_type item_type;
+	bool is_mplsoudp = 0; /* 1 - MPLSoUDP, 0 - MPLSoGRE */
+	const uint8_t label_mask[3] = {0xFF, 0xFF, 0xF0};
+	uint32_t label_be = 0;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			/* UDP is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid UDP item");
+				return -rte_errno;
+			}
+			is_mplsoudp = 1;
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			/* GRE is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid GRE item");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			mpls_spec =
+				(const struct rte_flow_item_mpls *)item->spec;
+			mpls_mask =
+				(const struct rte_flow_item_mpls *)item->mask;
+
+			if (!mpls_spec || !mpls_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS item");
+				return -rte_errno;
+			}
+
+			if (memcmp(mpls_mask->label_tc_s, label_mask, 3)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid MPLS label mask");
+				return -rte_errno;
+			}
+			rte_memcpy(((uint8_t *)&label_be + 1),
+				   mpls_spec->label_tc_s, 3);
+			filter->tenant_id = rte_be_to_cpu_32(label_be) >> 4;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (is_mplsoudp)
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoUDP;
+	else
+		filter->tunnel_type = I40E_TUNNEL_TYPE_MPLSoGRE;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error,
+			    union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_mpls_pattern(dev, pattern,
+					   error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static int
 i40e_flow_validate(struct rte_eth_dev *dev,
 		   const struct rte_flow_attr *attr,
@@ -1750,7 +1953,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 					   &cld_filter.element, 1);
 	if (ret < 0)
-		return ret;
+		return -ENOTSUP;
 
 	node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
 	if (!node)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
                           ` (2 preceding siblings ...)
  2017-03-30  6:56         ` [PATCH v5 3/4] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-30  6:56         ` Beilei Xing
  2017-03-30  8:22           ` Wu, Jingjing
  3 siblings, 1 reply; 43+ messages in thread
From: Beilei Xing @ 2017-03-30  6:56 UTC (permalink / raw)
  To: jingjing.wu; +Cc: helin.zhang, bernard.iremonger, dev

MPLSoUDP & MPLSoGRE is not supported by tunnel
filter due to limited resource of HW, this patch
enables MPLS tunnel filter by replacing inner_mac
filter.
This configuration will be set when adding MPLSoUDP
and MPLSoGRE filter rules, and it will be invalid
only by NIC core reset.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 190 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |   9 ++
 drivers/net/i40e/i40e_flow.c   |  15 +++-
 3 files changed, 203 insertions(+), 11 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 60926f0..312bb45 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6935,6 +6935,115 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 	return ret;
 }
 
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0 0x48
+#define I40E_TR_VXLAN_GRE_KEY_MASK		0x4
+#define I40E_TR_GENEVE_KEY_MASK			0x8
+#define I40E_TR_GENERIC_UDP_TUNNEL_MASK		0x40
+#define I40E_TR_GRE_KEY_MASK			0x400
+#define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
+#define I40E_TR_GRE_NO_KEY_MASK			0x8000
+
+static enum
+i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	filter_replace.old_filter_type =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC;
+	filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace.tr_bit = 0xFF;
+
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0xFF;
+	filter_replace_buf.data[3] = 0xFF;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[7] = 0xF0;
+	filter_replace_buf.data[8]
+		= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_TR_WORD0;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[10] = I40E_TR_VXLAN_GRE_KEY_MASK |
+		I40E_TR_GENEVE_KEY_MASK |
+		I40E_TR_GENERIC_UDP_TUNNEL_MASK;
+	filter_replace_buf.data[11] = (I40E_TR_GRE_KEY_MASK |
+		I40E_TR_GRE_KEY_WITH_XSUM_MASK |
+		I40E_TR_GRE_NO_KEY_MASK) >> 8;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
+static enum
+i40e_status_code i40e_replace_mpls_cloud_filter(struct i40e_pf *pf)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	enum i40e_status_code status = I40E_SUCCESS;
+
+	/* For MPLSoUDP */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (status < 0)
+		return status;
+
+	/* For MPLSoGRE */
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER |
+		I40E_AQC_MIRROR_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+	filter_replace.new_filter_type =
+		I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] = I40E_AQC_ADD_L1_FILTER_TEID_MPLS;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -6954,6 +7063,8 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *tunnel, *node;
 	struct i40e_tunnel_filter check_filter; /* Check if filter exists */
+	uint32_t teid_le;
+	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
 			 sizeof(struct i40e_aqc_add_rm_cloud_filt_elem_ext),
@@ -7001,6 +7112,38 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	case I40E_TUNNEL_TYPE_IP_IN_GRE:
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_IP;
 		break;
+	case I40E_TUNNEL_TYPE_MPLSoUDP:
+		if (!pf->mpls_replace_flag) {
+			i40e_replace_mpls_l1_filter(pf);
+			i40e_replace_mpls_cloud_filter(pf);
+			pf->mpls_replace_flag = 1;
+		}
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x40;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP;
+		break;
+	case I40E_TUNNEL_TYPE_MPLSoGRE:
+		if (!pf->mpls_replace_flag) {
+			i40e_replace_mpls_l1_filter(pf);
+			i40e_replace_mpls_cloud_filter(pf);
+			pf->mpls_replace_flag = 1;
+		}
+		teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+			teid_le >> 4;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+			(teid_le & 0xF) << 12;
+		pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+			0x0;
+		big_buffer = 1;
+		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7008,11 +7151,19 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		return -EINVAL;
 	}
 
-	val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
-				       &pfilter->element.flags);
-	if (val < 0) {
-		rte_free(cld_filter);
-		return -EINVAL;
+	if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoUDP)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
+		pfilter->element.flags =
+			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else {
+		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
+						&pfilter->element.flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
 	}
 
 	pfilter->element.flags |= rte_cpu_to_le_16(
@@ -7048,7 +7199,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	}
 
 	if (add) {
-		ret = i40e_aq_add_cloud_filters(hw,
+		if (big_buffer)
+			ret = i40e_aq_add_cloud_filters_big_buffer(hw,
+						   vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_add_cloud_filters(hw,
 					vsi->seid, &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
@@ -7058,7 +7213,11 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
 		ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
 	} else {
-		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+		if (big_buffer)
+			ret = i40e_aq_remove_cloud_filters_big_buffer(
+				hw, vsi->seid, cld_filter, 1);
+		else
+			ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
 						   &cld_filter->element, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
@@ -10444,6 +10603,7 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		*tunnel_list = &pf->tunnel.tunnel_list;
 	struct i40e_tunnel_filter *f;
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
+	bool big_buffer = 0;
 
 	TAILQ_FOREACH(f, tunnel_list, rules) {
 		memset(&cld_filter, 0, sizeof(cld_filter));
@@ -10459,8 +10619,20 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 			   f->input.general_fields,
 			   sizeof(f->input.general_fields));
 
-		i40e_aq_add_cloud_filters(hw, vsi->seid,
-					  &cld_filter.element, 1);
+		if (((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+			big_buffer = 1;
+
+		if (big_buffer)
+			i40e_aq_add_cloud_filters_big_buffer(hw,
+					     vsi->seid, &cld_filter, 1);
+		else
+			i40e_aq_add_cloud_filters(hw, vsi->seid,
+						  &cld_filter.element, 1);
 	}
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index dec1bd6..a8ecea4 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -501,6 +501,14 @@ struct i40e_ethertype_rule {
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoUDP 8
+#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE 9
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP 0x11
+#define I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE 0x12
+#define I40E_AQC_ADD_L1_FILTER_TEID_MPLS 0x11
+
 enum i40e_tunnel_iptype {
 	I40E_TUNNEL_IPTYPE_IPV4,
 	I40E_TUNNEL_IPTYPE_IPV6,
@@ -665,6 +673,7 @@ struct i40e_pf {
 	/* The floating enable flag for the specific VF */
 	bool floating_veb_list[I40E_MAX_VF];
 	struct i40e_flow_list flow_list;
+	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 };
 
 enum pending_msg {
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index f5da126..3c89072 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1936,6 +1936,7 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	struct i40e_aqc_add_rm_cloud_filt_elem_ext cld_filter;
 	struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
 	struct i40e_tunnel_filter *node;
+	bool big_buffer = 0;
 	int ret = 0;
 
 	memset(&cld_filter, 0, sizeof(cld_filter));
@@ -1951,8 +1952,18 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
-	ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
-					   &cld_filter.element, 1);
+	if (((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
+	     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		big_buffer = 1;
+
+	if (big_buffer)
+		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
+							      &cld_filter, 1);
+	else
+		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+						   &cld_filter.element, 1);
 	if (ret < 0)
 		return -ENOTSUP;
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 3/4] net/i40e: add MPLS parsing function
  2017-03-30  6:56         ` [PATCH v5 3/4] net/i40e: add MPLS parsing function Beilei Xing
@ 2017-03-30  8:22           ` Wu, Jingjing
  0 siblings, 0 replies; 43+ messages in thread
From: Wu, Jingjing @ 2017-03-30  8:22 UTC (permalink / raw)
  To: Xing, Beilei; +Cc: Zhang, Helin, Iremonger, Bernard, dev



> -----Original Message-----
> From: Xing, Beilei
> Sent: Thursday, March 30, 2017 2:57 PM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: [PATCH v5 3/4] net/i40e: add MPLS parsing function
> 
> This patch add MPLS parsing function to support MPLS filtering.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>

Acked-by Jingjing Wu <jingjing.wu@intel.com>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS
  2017-03-30  6:56         ` [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
@ 2017-03-30  8:22           ` Wu, Jingjing
  0 siblings, 0 replies; 43+ messages in thread
From: Wu, Jingjing @ 2017-03-30  8:22 UTC (permalink / raw)
  To: Xing, Beilei; +Cc: Zhang, Helin, Iremonger, Bernard, dev



> -----Original Message-----
> From: Xing, Beilei
> Sent: Thursday, March 30, 2017 2:57 PM
> To: Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS
> 
> MPLSoUDP & MPLSoGRE is not supported by tunnel filter due to limited
> resource of HW, this patch enables MPLS tunnel filter by replacing inner_mac
> filter.
> This configuration will be set when adding MPLSoUDP and MPLSoGRE filter
> rules, and it will be invalid only by NIC core reset.
> 
> Signed-off-by: Beilei Xing <beilei.xing@intel.com>

Acked-by Jingjing Wu <jingjing.wu@intel.com>

^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2017-03-30  8:23 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03  9:43 [PATCH 0/3] enable MPLS cloud filter Beilei Xing
2017-03-03  9:43 ` [PATCH 1/3] app/testpmd: support MPLS for generic filter Beilei Xing
2017-03-03 11:09   ` Adrien Mazarguil
2017-03-06  2:39     ` Xing, Beilei
2017-03-03  9:43 ` [PATCH 2/3] net/i40e: add MPLS parsing function Beilei Xing
2017-03-03  9:43 ` [PATCH 3/3] net/i40e: enable cloud filter for MPLS Beilei Xing
2017-03-08 16:05   ` Ferruh Yigit
2017-03-09  3:57     ` Xing, Beilei
2017-03-09 11:13   ` Iremonger, Bernard
2017-03-09 11:39     ` Xing, Beilei
2017-03-09 11:53       ` Iremonger, Bernard
2017-03-09 12:06         ` Xing, Beilei
2017-03-09 13:48           ` Iremonger, Bernard
2017-03-23 10:57 ` [PATCH v2 0/3] add support for MPLS tunnel filter Beilei Xing
2017-03-23 10:57   ` [PATCH v2 1/3] app/testpmd: add support for MPLS and GRE items Beilei Xing
2017-03-23 19:39     ` Adrien Mazarguil
2017-03-24  2:17       ` Xing, Beilei
2017-03-24 10:00         ` Adrien Mazarguil
2017-03-23 10:57   ` [PATCH v2 2/3] net/i40e: add MPLS parsing function Beilei Xing
2017-03-23 10:57   ` [PATCH v2 3/3] net/i40e: enable tunnel filter for MPLS Beilei Xing
2017-03-28  6:40   ` [PATCH v3 0/4] add support for MPLS tunnel filter Beilei Xing
2017-03-28  6:40     ` [PATCH v3 1/4] ethdev: add MPLS and GRE items Beilei Xing
2017-03-28 12:28       ` Adrien Mazarguil
2017-03-28  6:40     ` [PATCH v3 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
2017-03-28 12:29       ` Adrien Mazarguil
2017-03-28  6:40     ` [PATCH v3 3/4] net/i40e: add MPLS parsing function Beilei Xing
2017-03-28  6:40     ` [PATCH v3 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
2017-03-30  4:07     ` [PATCH v4 0/4] add support for MPLS tunnel filter Beilei Xing
2017-03-30  4:07       ` [PATCH v4 1/4] ethdev: add MPLS and GRE items Beilei Xing
2017-03-30  4:07       ` [PATCH v4 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
2017-03-30  4:07       ` [PATCH v4 3/4] net/i40e: add MPLS parsing function Beilei Xing
2017-03-30  6:04         ` Wu, Jingjing
2017-03-30  6:35           ` Xing, Beilei
2017-03-30  4:07       ` [PATCH v4 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
2017-03-30  6:16         ` Wu, Jingjing
2017-03-30  6:20           ` Xing, Beilei
2017-03-30  6:56       ` [PATCH v5 0/4] add support for MPLS tunnel filter Beilei Xing
2017-03-30  6:56         ` [PATCH v5 1/4] ethdev: add MPLS and GRE items Beilei Xing
2017-03-30  6:56         ` [PATCH v5 2/4] app/testpmd: add MPLS and GRE fields to flow command Beilei Xing
2017-03-30  6:56         ` [PATCH v5 3/4] net/i40e: add MPLS parsing function Beilei Xing
2017-03-30  8:22           ` Wu, Jingjing
2017-03-30  6:56         ` [PATCH v5 4/4] net/i40e: enable tunnel filter for MPLS Beilei Xing
2017-03-30  8:22           ` Wu, Jingjing

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.