All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/4]  net/i40e: QinQ filter
@ 2017-03-03 14:48 Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 1/4] net/i40e: update destroy tunnel filter function Bernard Iremonger
                   ` (7 more replies)
  0 siblings, 8 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-03 14:48 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

This patchset depends on the following patchset
[PATCH 1/4] net/i40e: support replace filter type

It adds support for QinQ filters.
It uses the replace filter AQ command.

Bernard Iremonger (4):
  net/i40e: update destroy tunnel filter function
  net/i40e: add QinQ wrapper function
  net/i40e: changes to consistent filter set
  net/i40e: parse QinQ pattern

 drivers/net/i40e/i40e_ethdev.c | 136 +++++++++++++++++++++++++---
 drivers/net/i40e/i40e_ethdev.h |  25 ++++++
 drivers/net/i40e/i40e_flow.c   | 198 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 344 insertions(+), 15 deletions(-)

-- 
2.10.1

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

* [PATCH v1 1/4] net/i40e: update destroy tunnel filter function
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
@ 2017-03-03 14:48 ` Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 2/4] net/i40e: add QinQ wrapper function Bernard Iremonger
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-03 14:48 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

set big_buffer to 1 for QinQ filter in the
i40e_flow_destroy_tunnel_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 3e8c63a..49f5d41 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1748,6 +1748,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 		   filter->input.general_fields,
 		   sizeof(cld_filter.general_fields));
 
+	if (filter->input.flags == 0x10)   /* QinQ filter */
+		big_buffer = 1;
+
 	if (big_buffer)
 		ret = i40e_aq_remove_cloud_filters_big_buffer(hw, vsi->seid,
 							      &cld_filter, 1);
-- 
2.10.1

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

* [PATCH v1 2/4] net/i40e: add QinQ wrapper function
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 1/4] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-03 14:48 ` Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 3/4] net/i40e: changes to consistent filter set Bernard Iremonger
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-03 14:48 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 8432 bytes --]

add i40e_dev_cloud_filter_qinq function.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 116 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  25 +++++++++
 2 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 91bfd73..744b4ac 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -243,6 +243,8 @@
 /* Bit mask of Extended Tag enable/disable */
 #define PCI_DEV_CTRL_EXT_TAG_MASK  (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT)
 
+#define I40E_CLOUD_FILTER_CUSTOM_QINQ 0x10
+
 static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev);
 static int i40e_dev_configure(struct rte_eth_dev *dev);
@@ -414,6 +416,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_dev_cloud_filter_qinq(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -6672,16 +6675,19 @@ static int
 i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
 {
 	switch (filter_type) {
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_TENID:
+	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
+		*flag = I40E_CLOUD_FILTER_CUSTOM_QINQ;
+		break;
+	case I40E_TUNNEL_FILTER_IMAC_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_OMAC_TENID_IMAC:
+	case I40E_TUNNEL_FILTER_OMAC_TENID_IMAC:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC;
 		break;
 	case ETH_TUNNEL_FILTER_IMAC:
@@ -6989,6 +6995,24 @@ 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_QINQ:
+		if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) {
+			PMD_DRV_LOG(INFO, "Replace a tunnel filter.");
+			ret = i40e_dev_cloud_filter_qinq(pf);
+			if (ret < 0) {
+				PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter.");
+				return ret;
+			}
+			/*	Add in the General fields the values of
+			 *	the Outer and Inner VLAN
+			 *	Big Buffer should be set, see changes in
+			 *	i40e_aq_add_cloud_filters
+			 */
+			pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+			pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+			big_buffer = 1;
+		}
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -11383,3 +11407,87 @@ rte_pmd_i40e_reset_vf_stats(uint8_t port,
 
 	return 0;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ * In step 1 we define which fields can be used for filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 ( instead of stag-inner vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0= 8 (outer vlan FV index). Byte1=0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0= 37 (inner vlan FV index). Byte1=0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 3 ( instead of inner-mac,inner vlan)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0= 0x80 | 7 (valid | Stag). Byte1-3=0 (rsv)
+ *		ii.	Byte8= 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11=0 (rsv)
+ */
+static int
+i40e_dev_cloud_filter_qinq(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0xff;  /* tr_bit is not used */
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
+	filter_replace.new_filter_type = I40E_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 3e9b129..54fbc4c 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -541,10 +541,35 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_NVGRE,
 	I40E_TUNNEL_TYPE_IP_IN_GRE,
 	I40E_L2_TUNNEL_TYPE_E_TAG,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
 /**
+ * filter type of tunneling packet
+ */
+#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC addr */
+#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
+#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
+#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr */
+#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */
+#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
+#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
+
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN)
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_TENID | \
+					ETH_TUNNEL_FILTER_IMAC)
+#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN)
+
+/**
  * Tunneling Packet filter configuration.
  */
 struct i40e_tunnel_filter_conf {
-- 
2.10.1

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

* [PATCH v1 3/4] net/i40e: changes to consistent filter set
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 1/4] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 2/4] net/i40e: add QinQ wrapper function Bernard Iremonger
@ 2017-03-03 14:48 ` Bernard Iremonger
  2017-03-03 14:48 ` [PATCH v1 4/4] net/i40e: parse QinQ pattern Bernard Iremonger
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-03 14:48 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

Set filter.element.flags for QINQ filter.
Minor formatting changes.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 744b4ac..2b0d08a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6950,10 +6950,10 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	bool big_buffer = 0;
 
 	cld_filter = rte_zmalloc("tunnel_filter",
-	sizeof(struct i40e_aqc_add_remove_cloud_filters_element_big_data),
-	0);
+		sizeof(struct i40e_aqc_add_remove_cloud_filters_element_big_data),
+		0);
 
-	if (cld_filter == NULL) {
+	if (NULL == cld_filter) {
 		PMD_DRV_LOG(ERR, "Failed to alloc memory.");
 		return -EINVAL;
 	}
@@ -7020,11 +7020,15 @@ 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_QINQ)
+		pfilter->element.flags = 0x10;
+	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(
-- 
2.10.1

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

* [PATCH v1 4/4] net/i40e: parse QinQ pattern
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
                   ` (2 preceding siblings ...)
  2017-03-03 14:48 ` [PATCH v1 3/4] net/i40e: changes to consistent filter set Bernard Iremonger
@ 2017-03-03 14:48 ` Bernard Iremonger
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-03 14:48 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 195 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 192 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 49f5d41..a53848f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -121,6 +121,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -278,6 +290,13 @@ static enum rte_flow_item_type pattern_vxlan_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -303,6 +322,7 @@ 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 },
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1126,8 +1146,8 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
- * Tunnel action only supports PF, VF and QUEUE.
+/* Parse to get the action info of a tunnel filter
+ * Tunnel action only supports QUEUE and VF.
  */
 static int
 i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
@@ -1486,6 +1506,144 @@ i40e_flow_parse_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_eth *i_eth_spec = NULL;
+	const struct rte_flow_item_eth *i_eth_mask = NULL;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if ((!eth_spec && eth_mask) ||
+			    (eth_spec && !eth_mask)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+
+			if (eth_spec && eth_mask) {
+				/* DST address of inner MAC shouldn't be masked.
+				 * SRC address of Inner MAC should be masked.
+				 */
+				if (!is_broadcast_ether_addr(&eth_mask->dst) ||
+				    !is_zero_ether_addr(&eth_mask->src) ||
+				    eth_mask->type) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+					return -rte_errno;
+				}
+
+				rte_memcpy(&filter->outer_mac,
+						   &eth_spec->dst,
+						   ETHER_ADDR_LEN);
+			}
+
+			i_eth_spec = eth_spec;
+			i_eth_mask = eth_mask;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Check specification and mask to get the filter type */
+	if (vlan_spec && vlan_mask &&
+	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+		/* If there's inner vlan */
+		if (vlan_flag)
+			filter->inner_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+				& I40E_TCI_MASK;
+		else {
+			/* There is an inner and outer vlan */
+			filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+				& I40E_TCI_MASK;
+			filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+				& I40E_TCI_MASK;
+		}
+
+		if (i_eth_spec && i_eth_mask)
+			filter->filter_type =
+				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else if ((!vlan_spec && !vlan_mask) ||
+		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
+		if (i_eth_spec && i_eth_mask) {
+			filter->filter_type = I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		} else {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Not supported by tunnel filter.");
+		return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+
+	return 0;
+}
+
+static int
 i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 			     const struct rte_flow_attr *attr,
 			     const struct rte_flow_item pattern[],
@@ -1499,6 +1657,37 @@ i40e_flow_parse_vxlan_filter(struct rte_eth_dev *dev,
 
 	ret = i40e_flow_parse_vxlan_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_parse_qinq_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_qinq_pattern(dev, pattern,
+					     error, tunnel_filter);
 	if (ret)
 		return ret;
 
-- 
2.10.1

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

* [PATCH v2 0/3] net/i40e: QinQ filter
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
                   ` (3 preceding siblings ...)
  2017-03-03 14:48 ` [PATCH v1 4/4] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-23 16:38 ` Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
                     ` (5 more replies)
  2017-03-23 16:38 ` [PATCH v2 1/3] net/i40e: add QinQ wrapper function Bernard Iremonger
                   ` (2 subsequent siblings)
  7 siblings, 6 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-23 16:38 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

This patchset depends on the following patch sets:
[dpdk-dev,v3,1/5] net/i40e: add pipeline personalization profile processing
[dpdk-dev,v2,1/4] net/i40e: rework tunnel filter functions
[dpdk-dev,v2,1/3] app/testpmd: add support for MPLS and GRE items

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (3):
  net/i40e: add QinQ wrapper function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function

 drivers/net/i40e/i40e_ethdev.c | 121 ++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |  26 ++++++
 drivers/net/i40e/i40e_flow.c   | 198 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 338 insertions(+), 7 deletions(-)

-- 
2.10.1

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

* [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
                   ` (4 preceding siblings ...)
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
@ 2017-03-23 16:38 ` Bernard Iremonger
  2017-03-28  8:11   ` Lu, Wenzhuo
  2017-03-23 16:38 ` [PATCH v2 2/3] net/i40e: parse QinQ pattern Bernard Iremonger
  2017-03-23 16:38 ` [PATCH v2 3/3] net/i40e: update destroy tunnel filter function Bernard Iremonger
  7 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-23 16:38 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 9103 bytes --]

Add i40e_dev_cloud_filter_qinq function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace filter 0x1 with QinQ filter.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 121 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  26 +++++++++
 2 files changed, 143 insertions(+), 4 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 1eb1625..e5ddad4 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -414,6 +414,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_dev_cloud_filter_qinq(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -6686,16 +6687,19 @@ static int
 i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
 {
 	switch (filter_type) {
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_TENID:
+	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+		break;
+	case I40E_TUNNEL_FILTER_IMAC_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_OMAC_TENID_IMAC:
+	case I40E_TUNNEL_FILTER_OMAC_TENID_IMAC:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC;
 		break;
 	case ETH_TUNNEL_FILTER_IMAC:
@@ -7029,6 +7033,25 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) {
+			PMD_DRV_LOG(INFO, "Replace a tunnel filter.");
+			ret = i40e_dev_cloud_filter_qinq(pf);
+			if (ret < 0) {
+				PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter.");
+				return ret;
+			}
+			/*	Add in the General fields the values of
+			 *	the Outer and Inner VLAN
+			 *	Big Buffer should be set, see changes in
+			 *	i40e_aq_add_cloud_filters
+			 */
+			pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+			pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+			big_buffer = 1;
+		}
+		break;
+
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7042,6 +7065,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -11702,3 +11728,90 @@ rte_pmd_i40e_get_ppp_list(uint8_t port, uint8_t *buff, uint32_t size)
 
 	return status;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
+ *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv)
+ */
+static int
+i40e_dev_cloud_filter_qinq(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0xff;  /* tr_bit is not used */
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 934c679..020c5a2 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -504,6 +504,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -552,10 +553,35 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
 /**
+ * filter type of tunneling packet
+ */
+#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC addr */
+#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
+#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
+#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr */
+#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */
+#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
+#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
+
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN)
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_TENID | \
+					ETH_TUNNEL_FILTER_IMAC)
+#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN)
+
+/**
  * Tunneling Packet filter configuration.
  */
 struct i40e_tunnel_filter_conf {
-- 
2.10.1

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

* [PATCH v2 2/3] net/i40e: parse QinQ pattern
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
                   ` (5 preceding siblings ...)
  2017-03-23 16:38 ` [PATCH v2 1/3] net/i40e: add QinQ wrapper function Bernard Iremonger
@ 2017-03-23 16:38 ` Bernard Iremonger
  2017-03-28  8:45   ` Lu, Wenzhuo
  2017-03-23 16:38 ` [PATCH v2 3/3] net/i40e: update destroy tunnel filter function Bernard Iremonger
  7 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-23 16:38 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 194 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 192 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8d7765a..e53ab22 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -348,6 +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1721,6 +1743,174 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_eth *i_eth_spec = NULL;
+	const struct rte_flow_item_eth *i_eth_mask = NULL;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if ((!eth_spec && eth_mask) ||
+			    (eth_spec && !eth_mask)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+
+			if (eth_spec && eth_mask) {
+				/* DST address of inner MAC shouldn't be masked.
+				 * SRC address of Inner MAC should be masked.
+				 */
+				if (!is_broadcast_ether_addr(&eth_mask->dst) ||
+				    !is_zero_ether_addr(&eth_mask->src) ||
+				    eth_mask->type) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+					return -rte_errno;
+				}
+
+				rte_memcpy(&filter->outer_mac,
+						   &eth_spec->dst,
+						   ETHER_ADDR_LEN);
+			}
+
+			i_eth_spec = eth_spec;
+			i_eth_mask = eth_mask;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Check specification and mask to get the filter type */
+	if (vlan_spec && vlan_mask &&
+	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+		/* If there's inner vlan */
+		if (vlan_flag)
+			filter->inner_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+				& I40E_TCI_MASK;
+		else {
+			/* There is an inner and outer vlan */
+			filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+				& I40E_TCI_MASK;
+			filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+				& I40E_TCI_MASK;
+		}
+
+		if (i_eth_spec && i_eth_mask)
+			filter->filter_type =
+				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else if ((!vlan_spec && !vlan_mask) ||
+		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
+		if (i_eth_spec && i_eth_mask) {
+			filter->filter_type = I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		} else {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Not supported by tunnel filter.");
+		return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.10.1

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

* [PATCH v2 3/3] net/i40e: update destroy tunnel filter function
  2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
                   ` (6 preceding siblings ...)
  2017-03-23 16:38 ` [PATCH v2 2/3] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-23 16:38 ` Bernard Iremonger
  2017-03-28  8:54   ` Lu, Wenzhuo
  7 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-23 16:38 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, Bernard Iremonger

set big_buffer to 1 for QinQ filter in
i40e_flow_destroy_tunnel_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index e53ab22..b2f997a 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2146,7 +2146,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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)
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE ||
+	    (filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ)
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.10.1

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

* Re: [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-23 16:38 ` [PATCH v2 1/3] net/i40e: add QinQ wrapper function Bernard Iremonger
@ 2017-03-28  8:11   ` Lu, Wenzhuo
  2017-03-28 11:09     ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-28  8:11 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Iremonger, Bernard, Stroe, Laura

Hi Bernard,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
> Sent: Friday, March 24, 2017 12:39 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Iremonger, Bernard; Stroe, Laura
> Subject: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper function
> 
> Add i40e_dev_cloud_filter_qinq function, and call it from
> i40e_dev_consistent_tunnel_filter_set function.
> Replace filter 0x1 with QinQ filter.
Better not use 0x1 here. Maybe it should be change to outer IP filter?
And seems better to add more explanation about what's QinQ filter here.

> +
> +/* Create a QinQ cloud filter
> + *
> + * The Fortville NIC has limited resources for tunnel filters,
> + * so we can only reuse existing filters.
> + *
> + * In step 1 we define which Field Vector fields can be used for
> + * filter types.
> + * As we do not have the inner tag defined as a field,
> + * we have to define it first, by reusing one of L1 entries.
> + *
> + * In step 2 we are replacing one of existing filter types with
> + * a new one for QinQ.
> + * As we reusing L1 and replacing L2, some of the default filter
> + * types will disappear,which depends on L1 and L2 entries we reuse.
> + *
> + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
> + *
> + * 1.	Create L1 filter of outer vlan (12b) which will be in use
> + *		later when we define the cloud filter.
> + *	a.	Valid_flags.replace_cloud = 0
> + *	b.	Old_filter = 10 (Stag_Inner_Vlan)
> + *	c.	New_filter = 0x10
> + *	d.	TR bit = 0xff (optional, not used here)
> + *	e.	Buffer – 2 entries:
> + *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-
> 3 = 0x0fff
> + *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte
> 2-3 = 0x0fff
> + *
> + * Step 2:
> + * 2.	Create cloud filter using two L1 filters entries: stag and
> + *		new filter(outer vlan+ inner vlan)
> + *	a.	Valid_flags.replace_cloud = 1
> + *	b.	Old_filter = 1 (instead of outer IP)
> + *	c.	New_filter = 0x10
> + *	d.	Buffer – 2 entries:
> + *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
> + *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1).
> Byte9-11 = 0 (rsv)
> + */
> +static int
> +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) {
Is it better to change the function name to i40e_dev_create_cloud_filter_qinq?

> diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> index 934c679..020c5a2 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> 
>  /**
> + * filter type of tunneling packet
> + */
> +#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC addr */
> +#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
> +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
> +#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr */
> +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */
> +#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
Seems not necessary to redefine these macros.

> +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
> +
> +#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \
> +					ETH_TUNNEL_FILTER_IVLAN)
> +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID
> (ETH_TUNNEL_FILTER_IMAC | \
> +					ETH_TUNNEL_FILTER_IVLAN | \
> +					ETH_TUNNEL_FILTER_TENID)
> +#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \
> +					ETH_TUNNEL_FILTER_TENID)
> +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC
> (ETH_TUNNEL_FILTER_OMAC | \
> +					ETH_TUNNEL_FILTER_TENID | \
> +					ETH_TUNNEL_FILTER_IMAC)
I don't think it's necessary the redefine these macros either. Maybe we only need to add I40E_TUNNEL_FILTER_CUSTOM_QINQ.

> +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC
> | \
> +					ETH_TUNNEL_FILTER_OVLAN |
> ETH_TUNNEL_FILTER_IVLAN)
> +
> +/**
>   * Tunneling Packet filter configuration.
>   */
>  struct i40e_tunnel_filter_conf {
> --
> 2.10.1


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

* Re: [PATCH v2 2/3] net/i40e: parse QinQ pattern
  2017-03-23 16:38 ` [PATCH v2 2/3] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-28  8:45   ` Lu, Wenzhuo
  2017-03-28 11:12     ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-28  8:45 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Iremonger, Bernard

Hi Bernard,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
> Sent: Friday, March 24, 2017 12:39 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Iremonger, Bernard
> Subject: [dpdk-dev] [PATCH v2 2/3] net/i40e: parse QinQ pattern
> 
> add QinQ pattern.
> add i40e_flow_parse_qinq_pattern function.
> add i40e_flow_parse_qinq_filter function.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_flow.c | 194
> ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 192 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index
> 8d7765a..e53ab22 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c

> +/* Pattern matched QINQ */
> +static enum rte_flow_item_type pattern_qinq_1[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};

> +
> +	/* Check specification and mask to get the filter type */
> +	if (vlan_spec && vlan_mask &&
> +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
> +		/* If there's inner vlan */
> +		if (vlan_flag)
I think vlan_flag here is always 0, according to defined 'pattern_qinq_1'. Single vlan is not supported.

> +			filter->inner_vlan = rte_be_to_cpu_16(o_vlan_spec-
> >tci)
> +				& I40E_TCI_MASK;
> +		else {
> +			/* There is an inner and outer vlan */
> +			filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec-
> >tci)
> +				& I40E_TCI_MASK;
> +			filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec-
> >tci)
> +				& I40E_TCI_MASK;
> +		}

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

* Re: [PATCH v2 3/3] net/i40e: update destroy tunnel filter function
  2017-03-23 16:38 ` [PATCH v2 3/3] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-28  8:54   ` Lu, Wenzhuo
  2017-03-28 11:13     ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-28  8:54 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Iremonger, Bernard

Hi Bernard,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard Iremonger
> Sent: Friday, March 24, 2017 12:39 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Iremonger, Bernard
> Subject: [dpdk-dev] [PATCH v2 3/3] net/i40e: update destroy tunnel filter
> function
> 
> set big_buffer to 1 for QinQ filter in
> i40e_flow_destroy_tunnel_filter function.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Besides the commit log it too detail to repeat the code.

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

* Re: [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-28  8:11   ` Lu, Wenzhuo
@ 2017-03-28 11:09     ` Iremonger, Bernard
  2017-03-28 13:23       ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-28 11:09 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, Stroe, Laura

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Tuesday, March 28, 2017 9:11 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; Stroe, Laura <laura.stroe@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper function
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> Iremonger
> > Sent: Friday, March 24, 2017 12:39 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Iremonger, Bernard; Stroe, Laura
> > Subject: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper function
> >
> > Add i40e_dev_cloud_filter_qinq function, and call it from
> > i40e_dev_consistent_tunnel_filter_set function.
> > Replace filter 0x1 with QinQ filter.
> Better not use 0x1 here. Maybe it should be change to outer IP filter?
Ok, I will change to out IP filter.
> And seems better to add more explanation about what's QinQ filter here.
Ok, I will add some information.
> 
> > +
> > +/* Create a QinQ cloud filter
> > + *
> > + * The Fortville NIC has limited resources for tunnel filters,
> > + * so we can only reuse existing filters.
> > + *
> > + * In step 1 we define which Field Vector fields can be used for
> > + * filter types.
> > + * As we do not have the inner tag defined as a field,
> > + * we have to define it first, by reusing one of L1 entries.
> > + *
> > + * In step 2 we are replacing one of existing filter types with
> > + * a new one for QinQ.
> > + * As we reusing L1 and replacing L2, some of the default filter
> > + * types will disappear,which depends on L1 and L2 entries we reuse.
> > + *
> > + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
> > + *
> > + * 1.	Create L1 filter of outer vlan (12b) which will be in use
> > + *		later when we define the cloud filter.
> > + *	a.	Valid_flags.replace_cloud = 0
> > + *	b.	Old_filter = 10 (Stag_Inner_Vlan)
> > + *	c.	New_filter = 0x10
> > + *	d.	TR bit = 0xff (optional, not used here)
> > + *	e.	Buffer – 2 entries:
> > + *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-
> > 3 = 0x0fff
> > + *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte
> > 2-3 = 0x0fff
> > + *
> > + * Step 2:
> > + * 2.	Create cloud filter using two L1 filters entries: stag and
> > + *		new filter(outer vlan+ inner vlan)
> > + *	a.	Valid_flags.replace_cloud = 1
> > + *	b.	Old_filter = 1 (instead of outer IP)
> > + *	c.	New_filter = 0x10
> > + *	d.	Buffer – 2 entries:
> > + *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
> > + *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1).
> > Byte9-11 = 0 (rsv)
> > + */
> > +static int
> > +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) {
> Is it better to change the function name to
> i40e_dev_create_cloud_filter_qinq?
> 
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index 934c679..020c5a2 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> >
> >  /**
> > + * filter type of tunneling packet
> > + */
> > +#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC addr
> */
> > +#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
> > +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
> > +#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr
> */
> > +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */
> > +#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
> Seems not necessary to redefine these macros.
> 
> > +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID
> */
> > +
> > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC
> | \
> > +					ETH_TUNNEL_FILTER_IVLAN)
> > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID
> > (ETH_TUNNEL_FILTER_IMAC | \
> > +					ETH_TUNNEL_FILTER_IVLAN | \
> > +					ETH_TUNNEL_FILTER_TENID)
> > +#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC
> | \
> > +					ETH_TUNNEL_FILTER_TENID)
> > +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC
> > (ETH_TUNNEL_FILTER_OMAC | \
> > +					ETH_TUNNEL_FILTER_TENID | \
> > +					ETH_TUNNEL_FILTER_IMAC)
> I don't think it's necessary the redefine these macros either. Maybe we only
> need to add I40E_TUNNEL_FILTER_CUSTOM_QINQ.

I will check this.

> 
> > +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ
> (ETH_TUNNEL_FILTER_OMAC
> > | \
> > +					ETH_TUNNEL_FILTER_OVLAN |
> > ETH_TUNNEL_FILTER_IVLAN)
> > +
> > +/**
> >   * Tunneling Packet filter configuration.
> >   */
> >  struct i40e_tunnel_filter_conf {
> > --
> > 2.10.1

Thanks for the review.

Regards,

Bernard.


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

* Re: [PATCH v2 2/3] net/i40e: parse QinQ pattern
  2017-03-28  8:45   ` Lu, Wenzhuo
@ 2017-03-28 11:12     ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-28 11:12 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Tuesday, March 28, 2017 9:46 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 2/3] net/i40e: parse QinQ pattern
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> Iremonger
> > Sent: Friday, March 24, 2017 12:39 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Iremonger, Bernard
> > Subject: [dpdk-dev] [PATCH v2 2/3] net/i40e: parse QinQ pattern
> >
> > add QinQ pattern.
> > add i40e_flow_parse_qinq_pattern function.
> > add i40e_flow_parse_qinq_filter function.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_flow.c | 194
> > ++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 192 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index
> > 8d7765a..e53ab22 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> 
> > +/* Pattern matched QINQ */
> > +static enum rte_flow_item_type pattern_qinq_1[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> 
> > +
> > +	/* Check specification and mask to get the filter type */
> > +	if (vlan_spec && vlan_mask &&
> > +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
> > +		/* If there's inner vlan */
> > +		if (vlan_flag)
> I think vlan_flag here is always 0, according to defined 'pattern_qinq_1'.
> Single vlan is not supported.

I will check.
> 
> > +			filter->inner_vlan = rte_be_to_cpu_16(o_vlan_spec-
> > >tci)
> > +				& I40E_TCI_MASK;
> > +		else {
> > +			/* There is an inner and outer vlan */
> > +			filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec-
> > >tci)
> > +				& I40E_TCI_MASK;
> > +			filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec-
> > >tci)
> > +				& I40E_TCI_MASK;
> > +		}

Regards,

Bernard.

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

* Re: [PATCH v2 3/3] net/i40e: update destroy tunnel filter function
  2017-03-28  8:54   ` Lu, Wenzhuo
@ 2017-03-28 11:13     ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-28 11:13 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Tuesday, March 28, 2017 9:55 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 3/3] net/i40e: update destroy tunnel filter
> function
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> Iremonger
> > Sent: Friday, March 24, 2017 12:39 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Iremonger, Bernard
> > Subject: [dpdk-dev] [PATCH v2 3/3] net/i40e: update destroy tunnel
> > filter function
> >
> > set big_buffer to 1 for QinQ filter in i40e_flow_destroy_tunnel_filter
> > function.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com> Besides the commit log it
> too detail to repeat the code.

I will revise the commit log.

Regards,

Bernard.

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

* Re: [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-28 11:09     ` Iremonger, Bernard
@ 2017-03-28 13:23       ` Iremonger, Bernard
  2017-03-29  0:52         ` Lu, Wenzhuo
  0 siblings, 1 reply; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-28 13:23 UTC (permalink / raw)
  To: Iremonger, Bernard, Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Stroe, Laura

Hi Wenzhuo,

<snip>

-----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> > Iremonger
> > > Sent: Friday, March 24, 2017 12:39 AM
> > > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > > Cc: Zhang, Helin; Iremonger, Bernard; Stroe, Laura
> > > Subject: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper
> > > function
> > >
> > > Add i40e_dev_cloud_filter_qinq function, and call it from
> > > i40e_dev_consistent_tunnel_filter_set function.
> > > Replace filter 0x1 with QinQ filter.
> > Better not use 0x1 here. Maybe it should be change to outer IP filter?
> Ok, I will change to out IP filter.
> > And seems better to add more explanation about what's QinQ filter here.
> Ok, I will add some information.
> >
> > > +
> > > +/* Create a QinQ cloud filter
> > > + *
> > > + * The Fortville NIC has limited resources for tunnel filters,
> > > + * so we can only reuse existing filters.
> > > + *
> > > + * In step 1 we define which Field Vector fields can be used for
> > > + * filter types.
> > > + * As we do not have the inner tag defined as a field,
> > > + * we have to define it first, by reusing one of L1 entries.
> > > + *
> > > + * In step 2 we are replacing one of existing filter types with
> > > + * a new one for QinQ.
> > > + * As we reusing L1 and replacing L2, some of the default filter
> > > + * types will disappear,which depends on L1 and L2 entries we reuse.
> > > + *
> > > + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
> > > + *
> > > + * 1.	Create L1 filter of outer vlan (12b) which will be in use
> > > + *		later when we define the cloud filter.
> > > + *	a.	Valid_flags.replace_cloud = 0
> > > + *	b.	Old_filter = 10 (Stag_Inner_Vlan)
> > > + *	c.	New_filter = 0x10
> > > + *	d.	TR bit = 0xff (optional, not used here)
> > > + *	e.	Buffer – 2 entries:
> > > + *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-
> > > 3 = 0x0fff
> > > + *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte
> > > 2-3 = 0x0fff
> > > + *
> > > + * Step 2:
> > > + * 2.	Create cloud filter using two L1 filters entries: stag and
> > > + *		new filter(outer vlan+ inner vlan)
> > > + *	a.	Valid_flags.replace_cloud = 1
> > > + *	b.	Old_filter = 1 (instead of outer IP)
> > > + *	c.	New_filter = 0x10
> > > + *	d.	Buffer – 2 entries:
> > > + *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
> > > + *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1).
> > > Byte9-11 = 0 (rsv)
> > > + */
> > > +static int
> > > +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) {
> > Is it better to change the function name to
> > i40e_dev_create_cloud_filter_qinq?

Ok, how about i40e_cloud_filter_qinq_create()?
It is more in line with the existing code.

> >
> > > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > > b/drivers/net/i40e/i40e_ethdev.h index 934c679..020c5a2 100644
> > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > >
> > >  /**
> > > + * filter type of tunneling packet
> > > + */
> > > +#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC
> addr
> > */
> > > +#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
> > > +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
> > > +#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr
> > */
> > > +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID
> */
> > > +#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
> > Seems not necessary to redefine these macros.
> >
> > > +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID
> > */
> > > +
> > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN
> (ETH_TUNNEL_FILTER_IMAC
> > | \
> > > +					ETH_TUNNEL_FILTER_IVLAN)
> > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID
> > > (ETH_TUNNEL_FILTER_IMAC | \
> > > +					ETH_TUNNEL_FILTER_IVLAN | \
> > > +					ETH_TUNNEL_FILTER_TENID)
> > > +#define I40E_TUNNEL_FILTER_IMAC_TENID
> (ETH_TUNNEL_FILTER_IMAC
> > | \
> > > +					ETH_TUNNEL_FILTER_TENID)
> > > +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC
> > > (ETH_TUNNEL_FILTER_OMAC | \
> > > +					ETH_TUNNEL_FILTER_TENID | \
> > > +					ETH_TUNNEL_FILTER_IMAC)
> > I don't think it's necessary the redefine these macros either. Maybe
> > we only need to add I40E_TUNNEL_FILTER_CUSTOM_QINQ.
> 
> I will check this.

These are now used in the i40e_ethdev code replacing RTE_* macros.
 
> >
> > > +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ
> > (ETH_TUNNEL_FILTER_OMAC
> > > | \
> > > +					ETH_TUNNEL_FILTER_OVLAN |
> > > ETH_TUNNEL_FILTER_IVLAN)
> > > +
> > > +/**
> > >   * Tunneling Packet filter configuration.
> > >   */
> > >  struct i40e_tunnel_filter_conf {
> > > --
> > > 2.10.1
> 
> Thanks for the review.
> 
> Regards,
> 
> Bernard.


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

* [PATCH v3 0/5] net/i40e: QinQ filter
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
                       ` (5 more replies)
  2017-03-28 16:20   ` [PATCH v3 1/5] net/i40e: add QinQ filter create function Bernard Iremonger
                     ` (4 subsequent siblings)
  5 siblings, 6 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

This patchset depends on the following patch sets:
[dpdk-dev,v5,1/5] net/i40e: add pipeline personalization profile processing
[dpdk-dev,v4,1/4] net/i40e: rework tunnel filter functions
[dpdk-dev,v3,1/3] app/testpmd: add support for MPLS and GRE items

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.


Bernard Iremonger (5):
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: initialise L3 MAP register
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 134 +++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  28 +++++-
 drivers/net/i40e/i40e_flow.c   | 191 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 344 insertions(+), 9 deletions(-)

-- 
2.11.0

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

* [PATCH v3 1/5] net/i40e: add QinQ filter create function
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 2/5] net/i40e: parse QinQ pattern Bernard Iremonger
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 9656 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 121 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h |  28 +++++++++-
 2 files changed, 144 insertions(+), 5 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e9f22e781..5a03c7a95 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -6695,16 +6696,19 @@ static int
 i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
 {
 	switch (filter_type) {
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID:
+	case I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_IMAC_TENID:
+	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+		break;
+	case I40E_TUNNEL_FILTER_IMAC_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
 		break;
-	case RTE_TUNNEL_FILTER_OMAC_TENID_IMAC:
+	case I40E_TUNNEL_FILTER_OMAC_TENID_IMAC:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC;
 		break;
 	case ETH_TUNNEL_FILTER_IMAC:
@@ -7029,6 +7033,25 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) {
+			PMD_DRV_LOG(INFO, "Replace a tunnel filter.");
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0) {
+				PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter.");
+				return ret;
+			}
+			/*	Add in the General fields the values of
+			 *	the Outer and Inner VLAN
+			 *	Big Buffer should be set, see changes in
+			 *	i40e_aq_add_cloud_filters
+			 */
+			pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+			pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+			big_buffer = 1;
+		}
+		break;
+
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7042,6 +7065,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -11921,3 +11947,90 @@ rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
 
 	return ret;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
+ *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0xff;  /* tr_bit is not used */
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index fd1fcd4a9..575e3f0ce 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,10 +554,35 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
 /**
+ * filter type of tunneling packet
+ */
+#define ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC addr */
+#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
+#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
+#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC addr */
+#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */
+#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
+#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
+
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN)
+#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_IVLAN | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \
+					ETH_TUNNEL_FILTER_TENID)
+#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_TENID | \
+					ETH_TUNNEL_FILTER_IMAC)
+#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN)
+
+/**
  * Tunneling Packet filter configuration.
  */
 struct i40e_tunnel_filter_conf {
-- 
2.11.0

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

* [PATCH v3 2/5] net/i40e: parse QinQ pattern
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 1/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-29  1:25     ` Lu, Wenzhuo
  2017-03-29  2:46     ` Xing, Beilei
  2017-03-28 16:20   ` [PATCH v3 3/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
                     ` (2 subsequent siblings)
  5 siblings, 2 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 187 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 185 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index be243e172..39b09ead5 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -348,6 +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1748,6 +1770,167 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_eth *i_eth_spec = NULL;
+	const struct rte_flow_item_eth *i_eth_mask = NULL;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if ((!eth_spec && eth_mask) ||
+			    (eth_spec && !eth_mask)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+
+			if (eth_spec && eth_mask) {
+				/* DST address of inner MAC shouldn't be masked.
+				 * SRC address of Inner MAC should be masked.
+				 */
+				if (!is_broadcast_ether_addr(&eth_mask->dst) ||
+				    !is_zero_ether_addr(&eth_mask->src) ||
+				    eth_mask->type) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+					return -rte_errno;
+				}
+
+				rte_memcpy(&filter->outer_mac,
+						   &eth_spec->dst,
+						   ETHER_ADDR_LEN);
+			}
+
+			i_eth_spec = eth_spec;
+			i_eth_mask = eth_mask;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Check specification and mask to get the filter type */
+	if (vlan_spec && vlan_mask &&
+	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+			/* There is an inner and outer vlan */
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		if (i_eth_spec && i_eth_mask)
+			filter->filter_type =
+				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else if ((!vlan_spec && !vlan_mask) ||
+		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
+		if (i_eth_spec && i_eth_mask) {
+			filter->filter_type = I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		} else {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Not supported by tunnel filter.");
+		return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v3 3/5] net/i40e: update destroy tunnel filter function
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
                     ` (2 preceding siblings ...)
  2017-03-28 16:20   ` [PATCH v3 2/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 4/5] net/i40e: initialise L3 MAP register Bernard Iremonger
  2017-03-28 16:20   ` [PATCH v3 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 39b09ead5..fba9ab718 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2166,7 +2166,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v3 4/5] net/i40e: initialise L3 MAP register
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
                     ` (3 preceding siblings ...)
  2017-03-28 16:20   ` [PATCH v3 3/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-29  1:24     ` Xing, Beilei
  2017-03-29  1:53     ` Lu, Wenzhuo
  2017-03-28 16:20   ` [PATCH v3 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 2 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 5a03c7a95..a57b0416d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -687,6 +687,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1128,6 +1131,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40), 0x00000028, NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v3 5/5] net/i40e: update tunnel filter restore function
  2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
                     ` (4 preceding siblings ...)
  2017-03-28 16:20   ` [PATCH v3 4/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-28 16:20   ` Bernard Iremonger
  2017-03-29  1:54     ` Lu, Wenzhuo
  5 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-28 16:20 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index a57b0416d..33bf3b0ac 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10543,7 +10543,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* Re: [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-28 13:23       ` Iremonger, Bernard
@ 2017-03-29  0:52         ` Lu, Wenzhuo
  2017-03-29  9:11           ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-29  0:52 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Stroe, Laura

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Tuesday, March 28, 2017 9:23 PM
> To: Iremonger, Bernard; Lu, Wenzhuo; dev@dpdk.org; Xing, Beilei; Wu,
> Jingjing
> Cc: Zhang, Helin; Stroe, Laura
> Subject: RE: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper function
> 
> Hi Wenzhuo,
> 
> <snip>
> 
> -----Original Message-----
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> > > Iremonger
> > > > Sent: Friday, March 24, 2017 12:39 AM
> > > > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > > > Cc: Zhang, Helin; Iremonger, Bernard; Stroe, Laura
> > > > Subject: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper
> > > > function
> > > >
> > > > Add i40e_dev_cloud_filter_qinq function, and call it from
> > > > i40e_dev_consistent_tunnel_filter_set function.
> > > > Replace filter 0x1 with QinQ filter.
> > > Better not use 0x1 here. Maybe it should be change to outer IP filter?
> > Ok, I will change to out IP filter.
> > > And seems better to add more explanation about what's QinQ filter here.
> > Ok, I will add some information.
> > >
> > > > +
> > > > +/* Create a QinQ cloud filter
> > > > + *
> > > > + * The Fortville NIC has limited resources for tunnel filters,
> > > > + * so we can only reuse existing filters.
> > > > + *
> > > > + * In step 1 we define which Field Vector fields can be used for
> > > > + * filter types.
> > > > + * As we do not have the inner tag defined as a field,
> > > > + * we have to define it first, by reusing one of L1 entries.
> > > > + *
> > > > + * In step 2 we are replacing one of existing filter types with
> > > > + * a new one for QinQ.
> > > > + * As we reusing L1 and replacing L2, some of the default filter
> > > > + * types will disappear,which depends on L1 and L2 entries we reuse.
> > > > + *
> > > > + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan
> > > > +(12b)
> > > > + *
> > > > + * 1.	Create L1 filter of outer vlan (12b) which will be in use
> > > > + *		later when we define the cloud filter.
> > > > + *	a.	Valid_flags.replace_cloud = 0
> > > > + *	b.	Old_filter = 10 (Stag_Inner_Vlan)
> > > > + *	c.	New_filter = 0x10
> > > > + *	d.	TR bit = 0xff (optional, not used here)
> > > > + *	e.	Buffer – 2 entries:
> > > > + *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv)
> Byte 2-
> > > > 3 = 0x0fff
> > > > + *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv)
> Byte
> > > > 2-3 = 0x0fff
> > > > + *
> > > > + * Step 2:
> > > > + * 2.	Create cloud filter using two L1 filters entries: stag and
> > > > + *		new filter(outer vlan+ inner vlan)
> > > > + *	a.	Valid_flags.replace_cloud = 1
> > > > + *	b.	Old_filter = 1 (instead of outer IP)
> > > > + *	c.	New_filter = 0x10
> > > > + *	d.	Buffer – 2 entries:
> > > > + *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
> > > > + *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter
> step1).
> > > > Byte9-11 = 0 (rsv)
> > > > + */
> > > > +static int
> > > > +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) {
> > > Is it better to change the function name to
> > > i40e_dev_create_cloud_filter_qinq?
> 
> Ok, how about i40e_cloud_filter_qinq_create()?
> It is more in line with the existing code.
It's fine to me:)

> 
> > >
> > > > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > > > b/drivers/net/i40e/i40e_ethdev.h index 934c679..020c5a2 100644
> > > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > >
> > > >  /**
> > > > + * filter type of tunneling packet  */ #define
> > > > +ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC
> > addr
> > > */
> > > > +#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr */
> > > > +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */
> > > > +#define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner MAC
> > > > +addr
> > > */
> > > > +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID
> > */
> > > > +#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr */
> > > Seems not necessary to redefine these macros.
> > >
> > > > +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID
> > > */
> > > > +
> > > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN
> > (ETH_TUNNEL_FILTER_IMAC
> > > | \
> > > > +					ETH_TUNNEL_FILTER_IVLAN)
> > > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID
> > > > (ETH_TUNNEL_FILTER_IMAC | \
> > > > +					ETH_TUNNEL_FILTER_IVLAN | \
> > > > +					ETH_TUNNEL_FILTER_TENID)
> > > > +#define I40E_TUNNEL_FILTER_IMAC_TENID
> > (ETH_TUNNEL_FILTER_IMAC
> > > | \
> > > > +					ETH_TUNNEL_FILTER_TENID)
> > > > +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC
> > > > (ETH_TUNNEL_FILTER_OMAC | \
> > > > +					ETH_TUNNEL_FILTER_TENID | \
> > > > +					ETH_TUNNEL_FILTER_IMAC)
> > > I don't think it's necessary the redefine these macros either. Maybe
> > > we only need to add I40E_TUNNEL_FILTER_CUSTOM_QINQ.
> >
> > I will check this.
> 
> These are now used in the i40e_ethdev code replacing RTE_* macros.
I think these macros are not NIC specific. Better define them in RTE. But if it's not the good time to add them to RTE, maybe the concern of ABI change. We need only define ETH_TUNNEL_FILTER_OVLAN and I40E_TUNNEL_FILTER_OMAC_TENID_IMAC here.

> 
> > >
> > > > +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ
> > > (ETH_TUNNEL_FILTER_OMAC
> > > > | \
> > > > +					ETH_TUNNEL_FILTER_OVLAN |
> > > > ETH_TUNNEL_FILTER_IVLAN)
> > > > +
> > > > +/**
> > > >   * Tunneling Packet filter configuration.
> > > >   */
> > > >  struct i40e_tunnel_filter_conf {
> > > > --
> > > > 2.10.1
> >
> > Thanks for the review.
> >
> > Regards,
> >
> > Bernard.


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

* Re: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
  2017-03-28 16:20   ` [PATCH v3 4/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-29  1:24     ` Xing, Beilei
  2017-03-29  8:27       ` Iremonger, Bernard
  2017-03-29  1:53     ` Lu, Wenzhuo
  1 sibling, 1 reply; 74+ messages in thread
From: Xing, Beilei @ 2017-03-29  1:24 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Wu, Jingjing; +Cc: Zhang, Helin, Lu, Wenzhuo



> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, March 29, 2017 12:21 AM
> To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> 
> The L3 MAP register is initialised to support QinQ cloud filters.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 5a03c7a95..a57b0416d 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -687,6 +687,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "*
> igb_uio | uio_pci_generic | vfio");  #ifndef I40E_GLQF_PIT
>  #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
>  #endif
> +#ifndef I40E_GLQF_L3_MAP
> +#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4)) #endif
> 
>  static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)  { @@ -1128,6
> +1131,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
>  		     ((hw->nvm.version >> 4) & 0xff),
>  		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
> 
> +	/* initialise the L3_MAP register */
> +	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
> 0x00000028, NULL);
> +	if (ret)
> +		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d",
> ret);
> +

Hi Bernard,

It's better to put it in i40e_GLQF_reg_init function.

Best Regards
Beilei

>  	/* Need the special FW version to support floating VEB */
>  	config_floating_veb(dev);
>  	/* Clear PXE mode */
> --
> 2.11.0

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

* Re: [PATCH v3 2/5] net/i40e: parse QinQ pattern
  2017-03-28 16:20   ` [PATCH v3 2/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-29  1:25     ` Lu, Wenzhuo
  2017-03-29 15:10       ` Iremonger, Bernard
  2017-03-29  2:46     ` Xing, Beilei
  1 sibling, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-29  1:25 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, March 29, 2017 12:21 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> Subject: [PATCH v3 2/5] net/i40e: parse QinQ pattern
> 
> add QinQ pattern.
> add i40e_flow_parse_qinq_pattern function.
> add i40e_flow_parse_qinq_filter function.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_flow.c | 187
> ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 185 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index
> be243e172..39b09ead5 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c

> +	/* Check specification and mask to get the filter type */
> +	if (vlan_spec && vlan_mask &&
The previous code already checked the vlan_spec and vlan_mask should not be NULL. Seems not necessary to check it again.

> +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
The vlan_mask here should be inner vlan mask.  The outer vlan mask is lost. Should we store the outer vlan mask and check it?

> +			/* There is an inner and outer vlan */
> +		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
> +			& I40E_TCI_MASK;
> +		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
> +			& I40E_TCI_MASK;
> +		if (i_eth_spec && i_eth_mask)
> +			filter->filter_type =
> +				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> +		else {
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   NULL,
> +					   "Invalid filter type");
> +			return -rte_errno;
> +		}
> +	} else if ((!vlan_spec && !vlan_mask) ||
> +		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
> +		if (i_eth_spec && i_eth_mask) {
The similar concern as above.

> +			filter->filter_type =
> I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> +		} else {
> +			rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> +				   "Invalid filter type");
> +			return -rte_errno;
> +		}
> +	} else {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> +				   "Not supported by tunnel filter.");
> +		return -rte_errno;
> +	}
> +
> +	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
> +
> +	return 0;
> +}

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

* Re: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
  2017-03-28 16:20   ` [PATCH v3 4/5] net/i40e: initialise L3 MAP register Bernard Iremonger
  2017-03-29  1:24     ` Xing, Beilei
@ 2017-03-29  1:53     ` Lu, Wenzhuo
  2017-03-29  8:56       ` Iremonger, Bernard
  1 sibling, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-29  1:53 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, March 29, 2017 12:21 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> Subject: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> 
> The L3 MAP register is initialised to support QinQ cloud filters.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
>  1 file changed, 8 insertions(+)

Is it better to adjust the sequence? Put it before the patch 1 or even merge it into patch 1?

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

* Re: [PATCH v3 5/5] net/i40e: update tunnel filter restore function
  2017-03-28 16:20   ` [PATCH v3 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
@ 2017-03-29  1:54     ` Lu, Wenzhuo
  0 siblings, 0 replies; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-29  1:54 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, March 29, 2017 12:21 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> Subject: [PATCH v3 5/5] net/i40e: update tunnel filter restore function
> 
> The QinQ filter uses big buffers, set the big_buffer flag when restoring a QinQ
> filter.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com> 
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

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

* Re: [PATCH v3 2/5] net/i40e: parse QinQ pattern
  2017-03-28 16:20   ` [PATCH v3 2/5] net/i40e: parse QinQ pattern Bernard Iremonger
  2017-03-29  1:25     ` Lu, Wenzhuo
@ 2017-03-29  2:46     ` Xing, Beilei
  2017-03-29  6:16       ` Xing, Beilei
  1 sibling, 1 reply; 74+ messages in thread
From: Xing, Beilei @ 2017-03-29  2:46 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Wu, Jingjing; +Cc: Zhang, Helin, Lu, Wenzhuo

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, March 29, 2017 12:21 AM
> To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>
> Subject: [PATCH v3 2/5] net/i40e: parse QinQ pattern
> 
> add QinQ pattern.
> add i40e_flow_parse_qinq_pattern function.
> add i40e_flow_parse_qinq_filter function.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_flow.c | 187
> ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 185 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index be243e172..39b09ead5 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -1,7 +1,7 @@
>  /*-
>   *   BSD LICENSE
>   *
> - *   Copyright (c) 2016 Intel Corporation. All rights reserved.
> + *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
>   *
>   *   Redistribution and use in source and binary forms, with or without
>   *   modification, are permitted provided that the following conditions
> @@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct
> i40e_pf *pf,  static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);  static
> int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);  static int
> i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
> +static int
> +i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
>  	.validate = i40e_flow_validate,
> @@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[] =
> {
>  	RTE_FLOW_ITEM_TYPE_END,
>  };
> 
> +/* Pattern matched QINQ */
> +static enum rte_flow_item_type pattern_qinq_1[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
>  static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	/* Ethertype */
>  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -348,6
> +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
>  	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
>  	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
> +	/* QINQ */
> +	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
>  };
> 
>  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> @@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev
> *dev,
>  	return 0;
>  }
> 
> -/* Parse to get the action info of a tunnle filter
> +/* Parse to get the action info of a tunnel filter
>   * Tunnel action only supports PF, VF and QUEUE.
>   */
>  static int
> @@ -1748,6 +1770,167 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev
> *dev,  }
> 
>  static int
> +i40e_flow_parse_qinq_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_eth *eth_spec;
> +	const struct rte_flow_item_eth *eth_mask;
> +	const struct rte_flow_item_eth *i_eth_spec = NULL;
> +	const struct rte_flow_item_eth *i_eth_mask = NULL;
> +	const struct rte_flow_item_vlan *vlan_spec = NULL;
> +	const struct rte_flow_item_vlan *vlan_mask = NULL;
> +	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
> +	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
> +
> +	enum rte_flow_item_type item_type;
> +	bool vlan_flag = 0;

Seems vlan_flag is not used at last.

> +
> +	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:
> +			eth_spec = (const struct rte_flow_item_eth *)item-
> >spec;
> +			eth_mask = (const struct rte_flow_item_eth *)item-
> >mask;
> +			if ((!eth_spec && eth_mask) ||
> +			    (eth_spec && !eth_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ether spec/mask");
> +				return -rte_errno;
> +			}
> +
> +			if (eth_spec && eth_mask) {
> +				/* DST address of inner MAC shouldn't be
> masked.
> +				 * SRC address of Inner MAC should be
> masked.
> +				 */
> +				if (!is_broadcast_ether_addr(&eth_mask-
> >dst) ||
> +				    !is_zero_ether_addr(&eth_mask->src) ||
> +				    eth_mask->type) {
> +					rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ether spec/mask");
> +					return -rte_errno;
> +				}
> +
> +				rte_memcpy(&filter->outer_mac,
> +						   &eth_spec->dst,
> +						   ETHER_ADDR_LEN);
> +			}
> +
> +			i_eth_spec = eth_spec;
> +			i_eth_mask = eth_mask;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VLAN:
> +			vlan_spec =
> +				(const struct rte_flow_item_vlan *)item-
> >spec;
> +			vlan_mask =
> +				(const struct rte_flow_item_vlan *)item-
> >mask;
> +
> +			if (!(vlan_spec && vlan_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid vlan item");
> +				return -rte_errno;
> +			}
> +
> +			if (!vlan_flag) {
> +				o_vlan_spec = vlan_spec;
> +				vlan_flag = 1;
> +			} else {
> +				i_vlan_spec = vlan_spec;
> +				vlan_flag = 0;
> +			}
> +			break;
> +
> +		default:
> +			break;
> +		}
> +	}
> +
> +	/* Check specification and mask to get the filter type */
> +	if (vlan_spec && vlan_mask &&
> +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
> +			/* There is an inner and outer vlan */
> +		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
> +			& I40E_TCI_MASK;
> +		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
> +			& I40E_TCI_MASK;
> +		if (i_eth_spec && i_eth_mask)
> +			filter->filter_type =
> +				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> +		else {
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   NULL,
> +					   "Invalid filter type");
> +			return -rte_errno;
> +		}
> +	} else if ((!vlan_spec && !vlan_mask) ||
> +		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
> +		if (i_eth_spec && i_eth_mask) {
> +			filter->filter_type =
> I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> +		} else {
> +			rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> +				   "Invalid filter type");
> +			return -rte_errno;
> +		}
> +	} else {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> +				   "Not supported by tunnel filter.");
> +		return -rte_errno;
> +	}
> +
> +	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_flow_parse_qinq_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_qinq_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[],
> --
> 2.11.0

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

* Re: [PATCH v3 2/5] net/i40e: parse QinQ pattern
  2017-03-29  2:46     ` Xing, Beilei
@ 2017-03-29  6:16       ` Xing, Beilei
  0 siblings, 0 replies; 74+ messages in thread
From: Xing, Beilei @ 2017-03-29  6:16 UTC (permalink / raw)
  To: Xing, Beilei, Iremonger, Bernard, dev, Wu, Jingjing
  Cc: Zhang, Helin, Lu, Wenzhuo



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Xing, Beilei
> Sent: Wednesday, March 29, 2017 10:46 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 2/5] net/i40e: parse QinQ pattern
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Wednesday, March 29, 2017 12:21 AM
> > To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>
> > Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> > <wenzhuo.lu@intel.com>; Iremonger, Bernard
> > <bernard.iremonger@intel.com>
> > Subject: [PATCH v3 2/5] net/i40e: parse QinQ pattern
> >
> > add QinQ pattern.
> > add i40e_flow_parse_qinq_pattern function.
> > add i40e_flow_parse_qinq_filter function.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_flow.c | 187
> > ++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 185 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c
> > b/drivers/net/i40e/i40e_flow.c index be243e172..39b09ead5 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> > @@ -1,7 +1,7 @@
> >  /*-
> >   *   BSD LICENSE
> >   *
> > - *   Copyright (c) 2016 Intel Corporation. All rights reserved.
> > + *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
> >   *
> >   *   Redistribution and use in source and binary forms, with or without
> >   *   modification, are permitted provided that the following conditions
> > @@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct
> > i40e_pf *pf,  static int i40e_flow_flush_fdir_filter(struct i40e_pf
> > *pf);  static int i40e_flow_flush_ethertype_filter(struct i40e_pf
> > *pf);  static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
> > +static int
> > +i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
> >  	.validate = i40e_flow_validate,
> > @@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[]
> =
> > {
> >  	RTE_FLOW_ITEM_TYPE_END,
> >  };
> >
> > +/* Pattern matched QINQ */
> > +static enum rte_flow_item_type pattern_qinq_1[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> >  static struct i40e_valid_pattern i40e_supported_patterns[] = {
> >  	/* Ethertype */
> >  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -348,6
> > +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] =
> > +{
> >  	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
> >  	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
> >  	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
> > +	/* QINQ */
> > +	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
> >  };
> >
> >  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> > @@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev
> > *dev,
> >  	return 0;
> >  }
> >
> > -/* Parse to get the action info of a tunnle filter
> > +/* Parse to get the action info of a tunnel filter
> >   * Tunnel action only supports PF, VF and QUEUE.
> >   */
> >  static int
> > @@ -1748,6 +1770,167 @@ i40e_flow_parse_mpls_filter(struct
> rte_eth_dev
> > *dev,  }
> >
> >  static int
> > +i40e_flow_parse_qinq_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_eth *eth_spec;
> > +	const struct rte_flow_item_eth *eth_mask;
> > +	const struct rte_flow_item_eth *i_eth_spec = NULL;
> > +	const struct rte_flow_item_eth *i_eth_mask = NULL;
> > +	const struct rte_flow_item_vlan *vlan_spec = NULL;
> > +	const struct rte_flow_item_vlan *vlan_mask = NULL;
> > +	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
> > +	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
> > +
> > +	enum rte_flow_item_type item_type;
> > +	bool vlan_flag = 0;
> 
> Seems vlan_flag is not used at last.

Ignore it, sorry for missing the info of distinguishing outer vlan and inner vlan.

> 
> > +
> > +	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:
> > +			eth_spec = (const struct rte_flow_item_eth *)item-
> > >spec;
> > +			eth_mask = (const struct rte_flow_item_eth *)item-
> > >mask;
> > +			if ((!eth_spec && eth_mask) ||
> > +			    (eth_spec && !eth_mask)) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid ether spec/mask");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (eth_spec && eth_mask) {
> > +				/* DST address of inner MAC shouldn't be
> > masked.
> > +				 * SRC address of Inner MAC should be
> > masked.
> > +				 */
> > +				if (!is_broadcast_ether_addr(&eth_mask-
> > >dst) ||
> > +				    !is_zero_ether_addr(&eth_mask->src) ||
> > +				    eth_mask->type) {
> > +					rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid ether spec/mask");
> > +					return -rte_errno;
> > +				}
> > +
> > +				rte_memcpy(&filter->outer_mac,
> > +						   &eth_spec->dst,
> > +						   ETHER_ADDR_LEN);
> > +			}
> > +
> > +			i_eth_spec = eth_spec;
> > +			i_eth_mask = eth_mask;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VLAN:
> > +			vlan_spec =
> > +				(const struct rte_flow_item_vlan *)item-
> > >spec;
> > +			vlan_mask =
> > +				(const struct rte_flow_item_vlan *)item-
> > >mask;
> > +
> > +			if (!(vlan_spec && vlan_mask)) {
> > +				rte_flow_error_set(error, EINVAL,
> > +					   RTE_FLOW_ERROR_TYPE_ITEM,
> > +					   item,
> > +					   "Invalid vlan item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (!vlan_flag) {
> > +				o_vlan_spec = vlan_spec;
> > +				vlan_flag = 1;
> > +			} else {
> > +				i_vlan_spec = vlan_spec;
> > +				vlan_flag = 0;
> > +			}
> > +			break;
> > +
> > +		default:
> > +			break;
> > +		}
> > +	}
> > +
> > +	/* Check specification and mask to get the filter type */
> > +	if (vlan_spec && vlan_mask &&
> > +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
> > +			/* There is an inner and outer vlan */
> > +		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
> > +			& I40E_TCI_MASK;
> > +		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
> > +			& I40E_TCI_MASK;
> > +		if (i_eth_spec && i_eth_mask)
> > +			filter->filter_type =
> > +				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> > +		else {
> > +			rte_flow_error_set(error, EINVAL,
> > +					   RTE_FLOW_ERROR_TYPE_ITEM,
> > +					   NULL,
> > +					   "Invalid filter type");
> > +			return -rte_errno;
> > +		}
> > +	} else if ((!vlan_spec && !vlan_mask) ||
> > +		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
> > +		if (i_eth_spec && i_eth_mask) {
> > +			filter->filter_type =
> > I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> > +		} else {
> > +			rte_flow_error_set(error, EINVAL,
> > +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> > +				   "Invalid filter type");
> > +			return -rte_errno;
> > +		}
> > +	} else {
> > +		rte_flow_error_set(error, EINVAL,
> > +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> > +				   "Not supported by tunnel filter.");
> > +		return -rte_errno;
> > +	}
> > +
> > +	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_flow_parse_qinq_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_qinq_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[],
> > --
> > 2.11.0

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

* Re: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
  2017-03-29  1:24     ` Xing, Beilei
@ 2017-03-29  8:27       ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-29  8:27 UTC (permalink / raw)
  To: Xing, Beilei, dev, Wu, Jingjing; +Cc: Zhang, Helin, Lu, Wenzhuo

Hi Beilei,


> -----Original Message-----
> From: Xing, Beilei
> Sent: Wednesday, March 29, 2017 2:25 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>
> Subject: RE: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> 
> 
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Wednesday, March 29, 2017 12:21 AM
> > To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>
> > Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> > <wenzhuo.lu@intel.com>; Iremonger, Bernard
> > <bernard.iremonger@intel.com>
> > Subject: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> >
> > The L3 MAP register is initialised to support QinQ cloud filters.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 5a03c7a95..a57b0416d 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -687,6 +687,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "*
> igb_uio |
> > uio_pci_generic | vfio");  #ifndef I40E_GLQF_PIT
> >  #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
> >  #endif
> > +#ifndef I40E_GLQF_L3_MAP
> > +#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4)) #endif
> >
> >  static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)  { @@
> > -1128,6
> > +1131,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  		     ((hw->nvm.version >> 4) & 0xff),
> >  		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
> >
> > +	/* initialise the L3_MAP register */
> > +	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
> > 0x00000028, NULL);
> > +	if (ret)
> > +		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d",
> > ret);
> > +
> 
> Hi Bernard,
> 
> It's better to put it in i40e_GLQF_reg_init function.

I tried this but it could not be written directly.
It has to be written using the admin queue. The admin queue has not been initialized when the i40e_GLQF_reg_init() function is called.

Regards,

Bernard.

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

* Re: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
  2017-03-29  1:53     ` Lu, Wenzhuo
@ 2017-03-29  8:56       ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-29  8:56 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Wednesday, March 29, 2017 2:53 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>
> Subject: RE: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Wednesday, March 29, 2017 12:21 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> > Subject: [PATCH v3 4/5] net/i40e: initialise L3 MAP register
> >
> > The L3 MAP register is initialised to support QinQ cloud filters.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> 
> Is it better to adjust the sequence? Put it before the patch 1 or even merge it
> into patch 1?

I think it should be a separate patch. 
It was added later that is why it is the fourth patch, the first three patches compile independently.
I can put it as the first patch if you like, however the sequence is ok as it is.

Regards,

Bernard.
 

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

* Re: [PATCH v2 1/3] net/i40e: add QinQ wrapper function
  2017-03-29  0:52         ` Lu, Wenzhuo
@ 2017-03-29  9:11           ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-29  9:11 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, Stroe, Laura

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Wednesday, March 29, 2017 1:53 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Stroe, Laura
> <laura.stroe@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper function
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Tuesday, March 28, 2017 9:23 PM
> > To: Iremonger, Bernard; Lu, Wenzhuo; dev@dpdk.org; Xing, Beilei; Wu,
> > Jingjing
> > Cc: Zhang, Helin; Stroe, Laura
> > Subject: RE: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper
> > function
> >
> > Hi Wenzhuo,
> >
> > <snip>
> >
> > -----Original Message-----
> > > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Bernard
> > > > Iremonger
> > > > > Sent: Friday, March 24, 2017 12:39 AM
> > > > > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > > > > Cc: Zhang, Helin; Iremonger, Bernard; Stroe, Laura
> > > > > Subject: [dpdk-dev] [PATCH v2 1/3] net/i40e: add QinQ wrapper
> > > > > function
> > > > >
> > > > > Add i40e_dev_cloud_filter_qinq function, and call it from
> > > > > i40e_dev_consistent_tunnel_filter_set function.
> > > > > Replace filter 0x1 with QinQ filter.
> > > > Better not use 0x1 here. Maybe it should be change to outer IP filter?
> > > Ok, I will change to out IP filter.
> > > > And seems better to add more explanation about what's QinQ filter
> here.
> > > Ok, I will add some information.
> > > >
> > > > > +
> > > > > +/* Create a QinQ cloud filter
> > > > > + *
> > > > > + * The Fortville NIC has limited resources for tunnel filters,
> > > > > + * so we can only reuse existing filters.
> > > > > + *
> > > > > + * In step 1 we define which Field Vector fields can be used
> > > > > +for
> > > > > + * filter types.
> > > > > + * As we do not have the inner tag defined as a field,
> > > > > + * we have to define it first, by reusing one of L1 entries.
> > > > > + *
> > > > > + * In step 2 we are replacing one of existing filter types with
> > > > > + * a new one for QinQ.
> > > > > + * As we reusing L1 and replacing L2, some of the default
> > > > > +filter
> > > > > + * types will disappear,which depends on L1 and L2 entries we reuse.
> > > > > + *
> > > > > + * Step 1: Create L1 filter of outer vlan (12b) + inner vlan
> > > > > +(12b)
> > > > > + *
> > > > > + * 1.	Create L1 filter of outer vlan (12b) which will be in use
> > > > > + *		later when we define the cloud filter.
> > > > > + *	a.	Valid_flags.replace_cloud = 0
> > > > > + *	b.	Old_filter = 10 (Stag_Inner_Vlan)
> > > > > + *	c.	New_filter = 0x10
> > > > > + *	d.	TR bit = 0xff (optional, not used here)
> > > > > + *	e.	Buffer – 2 entries:
> > > > > + *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv)
> > Byte 2-
> > > > > 3 = 0x0fff
> > > > > + *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0
> (rsv)
> > Byte
> > > > > 2-3 = 0x0fff
> > > > > + *
> > > > > + * Step 2:
> > > > > + * 2.	Create cloud filter using two L1 filters entries: stag and
> > > > > + *		new filter(outer vlan+ inner vlan)
> > > > > + *	a.	Valid_flags.replace_cloud = 1
> > > > > + *	b.	Old_filter = 1 (instead of outer IP)
> > > > > + *	c.	New_filter = 0x10
> > > > > + *	d.	Buffer – 2 entries:
> > > > > + *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
> > > > > + *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter
> > step1).
> > > > > Byte9-11 = 0 (rsv)
> > > > > + */
> > > > > +static int
> > > > > +i40e_dev_cloud_filter_qinq(struct i40e_pf *pf) {
> > > > Is it better to change the function name to
> > > > i40e_dev_create_cloud_filter_qinq?
> >
> > Ok, how about i40e_cloud_filter_qinq_create()?
> > It is more in line with the existing code.
> It's fine to me:)
> 
> >
> > > >
> > > > > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > > > > b/drivers/net/i40e/i40e_ethdev.h index 934c679..020c5a2 100644
> > > > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > > >
> > > > >  /**
> > > > > + * filter type of tunneling packet  */ #define
> > > > > +ETH_TUNNEL_FILTER_OMAC  0x01 /**< filter by outer MAC
> > > addr
> > > > */
> > > > > +#define ETH_TUNNEL_FILTER_OIP   0x02 /**< filter by outer IP Addr
> */
> > > > > +#define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID
> > > > > +*/ #define ETH_TUNNEL_FILTER_IMAC  0x08 /**< filter by inner
> > > > > +MAC addr
> > > > */
> > > > > +#define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN
> > > > > +ID
> > > */
> > > > > +#define ETH_TUNNEL_FILTER_IIP   0x20 /**< filter by inner IP addr
> */
> > > > Seems not necessary to redefine these macros.
> > > >
> > > > > +#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer
> VLAN
> > > > > +ID
> > > > */
> > > > > +
> > > > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN
> > > (ETH_TUNNEL_FILTER_IMAC
> > > > | \
> > > > > +					ETH_TUNNEL_FILTER_IVLAN)
> > > > > +#define I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID
> > > > > (ETH_TUNNEL_FILTER_IMAC | \
> > > > > +					ETH_TUNNEL_FILTER_IVLAN
> | \
> > > > > +					ETH_TUNNEL_FILTER_TENID)
> > > > > +#define I40E_TUNNEL_FILTER_IMAC_TENID
> > > (ETH_TUNNEL_FILTER_IMAC
> > > > | \
> > > > > +					ETH_TUNNEL_FILTER_TENID)
> > > > > +#define I40E_TUNNEL_FILTER_OMAC_TENID_IMAC
> > > > > (ETH_TUNNEL_FILTER_OMAC | \
> > > > > +					ETH_TUNNEL_FILTER_TENID
> | \
> > > > > +					ETH_TUNNEL_FILTER_IMAC)
> > > > I don't think it's necessary the redefine these macros either.
> > > > Maybe we only need to add I40E_TUNNEL_FILTER_CUSTOM_QINQ.
> > >
> > > I will check this.
> >
> > These are now used in the i40e_ethdev code replacing RTE_* macros.
> I think these macros are not NIC specific. Better define them in RTE. But if it's
> not the good time to add them to RTE, maybe the concern of ABI change. We
> need only define ETH_TUNNEL_FILTER_OVLAN and
> I40E_TUNNEL_FILTER_OMAC_TENID_IMAC here.

If I just define the above filters, then the following switch statement has mixed RTE and I40E macros, it seems cleaner to me to use all  I40E macros. I can change back to mixed macros if you think it is better.

static int
i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
{
	switch (filter_type) {
	case I40E_TUNNEL_FILTER_IMAC_IVLAN:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
		break;
	case I40E_TUNNEL_FILTER_IMAC_IVLAN_TENID:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
		break;
	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
		break;
	case I40E_TUNNEL_FILTER_IMAC_TENID:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
		break;
	case I40E_TUNNEL_FILTER_OMAC_TENID_IMAC:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC;
		break;
	case ETH_TUNNEL_FILTER_IMAC:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
		break;
	case ETH_TUNNEL_FILTER_OIP:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_OIP;
		break;
	case ETH_TUNNEL_FILTER_IIP:
		*flag = I40E_AQC_ADD_CLOUD_FILTER_IIP;
		break;
	default:
		PMD_DRV_LOG(ERR, "invalid tunnel filter type");
		return -EINVAL;
	}

	return 0;
> 
> >
> > > >
> > > > > +#define I40E_TUNNEL_FILTER_CUSTOM_QINQ
> > > > (ETH_TUNNEL_FILTER_OMAC
> > > > > | \
> > > > > +					ETH_TUNNEL_FILTER_OVLAN
> |
> > > > > ETH_TUNNEL_FILTER_IVLAN)
> > > > > +
> > > > > +/**
> > > > >   * Tunneling Packet filter configuration.
> > > > >   */
> > > > >  struct i40e_tunnel_filter_conf {
> > > > > --
> > > > > 2.10.1
> > >
> > > Thanks for the review.
> > >
> > > Regards,
> > >
> > > Bernard.

Regards,

Bernard.


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

* Re: [PATCH v3 2/5] net/i40e: parse QinQ pattern
  2017-03-29  1:25     ` Lu, Wenzhuo
@ 2017-03-29 15:10       ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-29 15:10 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Wednesday, March 29, 2017 2:25 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>
> Subject: RE: [PATCH v3 2/5] net/i40e: parse QinQ pattern
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Wednesday, March 29, 2017 12:21 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> > Subject: [PATCH v3 2/5] net/i40e: parse QinQ pattern
> >
> > add QinQ pattern.
> > add i40e_flow_parse_qinq_pattern function.
> > add i40e_flow_parse_qinq_filter function.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_flow.c | 187
> > ++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 185 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index
> > be243e172..39b09ead5 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> 
> > +	/* Check specification and mask to get the filter type */
> > +	if (vlan_spec && vlan_mask &&
> The previous code already checked the vlan_spec and vlan_mask should not
> be NULL. Seems not necessary to check it again.

I will remove this check.

> > +	    (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
> The vlan_mask here should be inner vlan mask.  The outer vlan mask is lost.
> Should we store the outer vlan mask and check it?

Yes, I will store and check both inner and outer vlan masks.
 
> > +			/* There is an inner and outer vlan */
> > +		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
> > +			& I40E_TCI_MASK;
> > +		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
> > +			& I40E_TCI_MASK;
> > +		if (i_eth_spec && i_eth_mask)
> > +			filter->filter_type =
> > +				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> > +		else {
> > +			rte_flow_error_set(error, EINVAL,
> > +					   RTE_FLOW_ERROR_TYPE_ITEM,
> > +					   NULL,
> > +					   "Invalid filter type");
> > +			return -rte_errno;
> > +		}
> > +	} else if ((!vlan_spec && !vlan_mask) ||
> > +		   (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
> > +		if (i_eth_spec && i_eth_mask) {
> The similar concern as above.

I will  change as above.
  

> 
> > +			filter->filter_type =
> > I40E_TUNNEL_FILTER_CUSTOM_QINQ;
> > +		} else {
> > +			rte_flow_error_set(error, EINVAL,
> > +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> > +				   "Invalid filter type");
> > +			return -rte_errno;
> > +		}
> > +	} else {
> > +		rte_flow_error_set(error, EINVAL,
> > +				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> > +				   "Not supported by tunnel filter.");
> > +		return -rte_errno;
> > +	}
> > +
> > +	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
> > +
> > +	return 0;
> > +}

Regards,

Bernard.

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

* [PATCH v4 0/5] net/i40e: QinQ filter
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  2017-03-30 16:01       ` Bernard Iremonger
                         ` (5 more replies)
  2017-03-29 16:41     ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
                       ` (4 subsequent siblings)
  5 siblings, 6 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

This patchset depends on the following patch sets:
[dpdk-dev,v4,1/4] net/i40e: rework tunnel filter functions
[dpdk-dev,v3,1/3] app/testpmd: add support for MPLS and GRE items

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v4:
Reordered patches following comments.
Revises patches 2 and 3 following comments.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (5):
  net/i40e: initialise L3 MAP register
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 126 +++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |   8 +-
 drivers/net/i40e/i40e_flow.c   | 195 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 324 insertions(+), 5 deletions(-)

-- 
2.11.0

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

* [PATCH v4 1/5] net/i40e: initialise L3 MAP register
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  2017-03-30  0:54       ` Lu, Wenzhuo
  2017-03-29 16:41     ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
                       ` (3 subsequent siblings)
  5 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e9f22e781..dafc995a1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -686,6 +686,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1127,6 +1130,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40), 0x00000028, NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v4 2/5] net/i40e: add QinQ filter create function
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  2017-03-30  0:57       ` Lu, Wenzhuo
  2017-03-29 16:41     ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
                       ` (2 subsequent siblings)
  5 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 8238 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 113 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |   8 ++-
 2 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index dafc995a1..41e0fe5f7 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -6709,6 +6710,9 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
 	case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
 		break;
+	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+		break;
 	case RTE_TUNNEL_FILTER_IMAC_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
 		break;
@@ -7037,6 +7041,25 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) {
+			PMD_DRV_LOG(INFO, "Replace a tunnel filter.");
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0) {
+				PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter.");
+				return ret;
+			}
+			/*	Add in the General fields the values of
+			 *	the Outer and Inner VLAN
+			 *	Big Buffer should be set, see changes in
+			 *	i40e_aq_add_cloud_filters
+			 */
+			pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+			pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+			big_buffer = 1;
+		}
+		break;
+
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7050,6 +7073,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -11929,3 +11955,90 @@ rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
 
 	return ret;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
+ *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0xff;  /* tr_bit is not used */
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index fd1fcd4a9..03e89b5e4 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,9 +554,14 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
+#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN)
+
 /**
  * Tunneling Packet filter configuration.
  */
-- 
2.11.0

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

* [PATCH v4 3/5] net/i40e: parse QinQ pattern
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
                       ` (2 preceding siblings ...)
  2017-03-29 16:41     ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 191 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 189 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index be243e172..5d4847442 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -348,6 +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1748,6 +1770,171 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_eth *i_eth_spec = NULL;
+	const struct rte_flow_item_eth *i_eth_mask = NULL;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if ((!eth_spec && eth_mask) ||
+			    (eth_spec && !eth_mask)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+
+			if (eth_spec && eth_mask) {
+				/* DST address of inner MAC shouldn't be masked.
+				 * SRC address of Inner MAC should be masked.
+				 */
+				if (!is_broadcast_ether_addr(&eth_mask->dst) ||
+				    !is_zero_ether_addr(&eth_mask->src) ||
+				    eth_mask->type) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+					return -rte_errno;
+				}
+
+				rte_memcpy(&filter->outer_mac,
+						   &eth_spec->dst,
+						   ETHER_ADDR_LEN);
+			}
+
+			i_eth_spec = eth_spec;
+			i_eth_mask = eth_mask;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				o_vlan_mask = vlan_mask;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				i_vlan_mask = vlan_mask;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Check specification and mask to get the filter type */
+	if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) &&
+	    (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+			/* There is an inner and outer vlan */
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		if (i_eth_spec && i_eth_mask)
+			filter->filter_type =
+				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else if (((!o_vlan_spec && !o_vlan_mask) || (o_vlan_mask->tci == 0x0)) &&
+	    ((!i_vlan_spec && !i_vlan_mask) || (i_vlan_mask->tci == 0x0))) {
+		if (i_eth_spec && i_eth_mask) {
+			filter->filter_type = I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		} else {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Not supported by tunnel filter.");
+		return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v4 4/5] net/i40e: update destroy tunnel filter function
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
                       ` (3 preceding siblings ...)
  2017-03-29 16:41     ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  2017-03-29 16:41     ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 5d4847442..516103e64 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2170,7 +2170,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v4 5/5] net/i40e: update tunnel filter restore function
  2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
                       ` (4 preceding siblings ...)
  2017-03-29 16:41     ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-29 16:41     ` Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-29 16:41 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 41e0fe5f7..0c3619233 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10543,7 +10543,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* Re: [PATCH v4 1/5] net/i40e: initialise L3 MAP register
  2017-03-29 16:41     ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-30  0:54       ` Lu, Wenzhuo
  0 siblings, 0 replies; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-30  0:54 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, March 30, 2017 12:42 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> Subject: [PATCH v4 1/5] net/i40e: initialise L3 MAP register
> 
> The L3 MAP register is initialised to support QinQ cloud filters.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

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

* Re: [PATCH v4 2/5] net/i40e: add QinQ filter create function
  2017-03-29 16:41     ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-30  0:57       ` Lu, Wenzhuo
  0 siblings, 0 replies; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-30  0:57 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Stroe, Laura

Hi,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, March 30, 2017 12:42 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard; Stroe, Laura
> Subject: [PATCH v4 2/5] net/i40e: add QinQ filter create function
> 
> Add i40e_cloud_filter_qinq_create function, and call it from
> i40e_dev_consistent_tunnel_filter_set function.
> Replace the Outer IP filter with the QinQ filter.
> 
> QinQ allows multiple VLAN tags to be inserted into a single Ethernet frame.
> A QinQ frame is a frame that has two VLAN 802.1Q headers.
> 802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
> providers as a layer 2 VPN for customers.
> 
> Signed-off-by: Laura Stroe <laura.stroe@intel.com>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

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

* [PATCH v4 0/5] net/i40e: QinQ filter
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
                           ` (5 more replies)
  2017-03-30 16:01       ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
                         ` (4 subsequent siblings)
  5 siblings, 6 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

This patchset depends on the following patch sets:
[dpdk-dev,v4,1/4] net/i40e: rework tunnel filter functions
[dpdk-dev,v3,1/3] app/testpmd: add support for MPLS and GRE items

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v4:
Reordered patches following comments.
Revises patches 2 and 3 following comments.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (5):
  net/i40e: initialise L3 MAP register
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 126 +++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |   8 +-
 drivers/net/i40e/i40e_flow.c   | 195 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 324 insertions(+), 5 deletions(-)

-- 
2.11.0

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

* [PATCH v4 1/5] net/i40e: initialise L3 MAP register
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
  2017-03-30 16:01       ` Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e9f22e781..dafc995a1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -686,6 +686,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1127,6 +1130,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40), 0x00000028, NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v4 2/5] net/i40e: add QinQ filter create function
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
  2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 8238 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 113 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |   8 ++-
 2 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index dafc995a1..41e0fe5f7 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -6709,6 +6710,9 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
 	case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
 		break;
+	case I40E_TUNNEL_FILTER_CUSTOM_QINQ:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+		break;
 	case RTE_TUNNEL_FILTER_IMAC_TENID:
 		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
 		break;
@@ -7037,6 +7041,25 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (tunnel_filter->filter_type == I40E_TUNNEL_FILTER_CUSTOM_QINQ) {
+			PMD_DRV_LOG(INFO, "Replace a tunnel filter.");
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0) {
+				PMD_DRV_LOG(ERR, "Failed to replace a tunnel filter.");
+				return ret;
+			}
+			/*	Add in the General fields the values of
+			 *	the Outer and Inner VLAN
+			 *	Big Buffer should be set, see changes in
+			 *	i40e_aq_add_cloud_filters
+			 */
+			pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+			pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+			big_buffer = 1;
+		}
+		break;
+
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7050,6 +7073,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -11929,3 +11955,90 @@ rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
 
 	return ret;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
+ *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0xff;  /* tr_bit is not used */
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index fd1fcd4a9..03e89b5e4 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,9 +554,14 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+#define ETH_TUNNEL_FILTER_OVLAN 0x40 /**< filter by outer VLAN ID */
+#define I40E_TUNNEL_FILTER_CUSTOM_QINQ (ETH_TUNNEL_FILTER_OMAC | \
+					ETH_TUNNEL_FILTER_OVLAN | ETH_TUNNEL_FILTER_IVLAN)
+
 /**
  * Tunneling Packet filter configuration.
  */
-- 
2.11.0

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

* [PATCH v4 3/5] net/i40e: parse QinQ pattern
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
                         ` (2 preceding siblings ...)
  2017-03-30 16:01       ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 191 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 189 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index be243e172..5d4847442 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -128,6 +128,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -318,6 +330,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -348,6 +368,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1171,7 +1193,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1748,6 +1770,171 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_eth *i_eth_spec = NULL;
+	const struct rte_flow_item_eth *i_eth_mask = NULL;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if ((!eth_spec && eth_mask) ||
+			    (eth_spec && !eth_mask)) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+
+			if (eth_spec && eth_mask) {
+				/* DST address of inner MAC shouldn't be masked.
+				 * SRC address of Inner MAC should be masked.
+				 */
+				if (!is_broadcast_ether_addr(&eth_mask->dst) ||
+				    !is_zero_ether_addr(&eth_mask->src) ||
+				    eth_mask->type) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+					return -rte_errno;
+				}
+
+				rte_memcpy(&filter->outer_mac,
+						   &eth_spec->dst,
+						   ETHER_ADDR_LEN);
+			}
+
+			i_eth_spec = eth_spec;
+			i_eth_mask = eth_mask;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				o_vlan_mask = vlan_mask;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				i_vlan_mask = vlan_mask;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Check specification and mask to get the filter type */
+	if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) &&
+	    (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+			/* There is an inner and outer vlan */
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		if (i_eth_spec && i_eth_mask)
+			filter->filter_type =
+				I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else if (((!o_vlan_spec && !o_vlan_mask) || (o_vlan_mask->tci == 0x0)) &&
+	    ((!i_vlan_spec && !i_vlan_mask) || (i_vlan_mask->tci == 0x0))) {
+		if (i_eth_spec && i_eth_mask) {
+			filter->filter_type = I40E_TUNNEL_FILTER_CUSTOM_QINQ;
+		} else {
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Invalid filter type");
+			return -rte_errno;
+		}
+	} else {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				   "Not supported by tunnel filter.");
+		return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v4 4/5] net/i40e: update destroy tunnel filter function
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
                         ` (3 preceding siblings ...)
  2017-03-30 16:01       ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:01       ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 5d4847442..516103e64 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2170,7 +2170,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v4 5/5] net/i40e: update tunnel filter restore function
  2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
                         ` (4 preceding siblings ...)
  2017-03-30 16:01       ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-30 16:01       ` Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:01 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 41e0fe5f7..0c3619233 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10543,7 +10543,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* [PATCH v5 0/5] net/i40e: QinQ filter
  2017-03-30 16:01       ` Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  2017-03-31 13:33           ` Ferruh Yigit
                             ` (6 more replies)
  2017-03-30 16:09         ` [PATCH v5 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
                           ` (4 subsequent siblings)
  5 siblings, 7 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

This patchset depends on the following patch set:
[dpdk-dev,v6,1/4] ethdev: add MPLS and GRE items

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v5:
Rebase to latest dpdk-next-net.
Rebase patches 2 and 3 following comments.
Uses  map_5.88_ATT firmware.

Changes in v4:
Reordered patches following comments.
Revises patches 2 and 3 following comments.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (5):
  net/i40e: initialise L3 MAP register
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 120 ++++++++++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 drivers/net/i40e/i40e_flow.c   | 149 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 269 insertions(+), 5 deletions(-)

-- 
2.11.0

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

* [PATCH v5 1/5] net/i40e: initialise L3 MAP register
  2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
                           ` (3 subsequent siblings)
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3c784b50b..8f0dc546b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -686,6 +686,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1127,6 +1130,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40), 0x00000028, NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v5 2/5] net/i40e: add QinQ filter create function
  2017-03-30 16:01       ` Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  2017-03-31  9:43           ` Xing, Beilei
  2017-03-30 16:09         ` [PATCH v5 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
                           ` (2 subsequent siblings)
  5 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 7741 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 107 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8f0dc546b..bc07e628c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -7152,6 +7153,22 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (!pf->qinq_replace_flag) {
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0)
+				PMD_DRV_LOG(ERR, "Failed to create a qinq tunnel filter.");
+			pf->qinq_replace_flag = 1;
+		}
+		/*	Add in the General fields the values of
+		 *	the Outer and Inner VLAN
+		 *	Big Buffer should be set, see changes in
+		 *	i40e_aq_add_cloud_filters
+		 */
+		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+		big_buffer = 1;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7165,6 +7182,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -12044,3 +12064,90 @@ rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
 
 	return ret;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte0 = 8 (outer vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *		ii.	Byte0 = 37 (inner vlan FV index). Byte1 =0 (rsv) Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte0 = 0x80 | 7 (valid | Stag). Byte13 = 0 (rsv)
+ *		ii.	Byte8 = 0x80 | 0x10 (valid | new l1 filter step1). Byte9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0;
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index a8ecea4f0..f537a3a90 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,6 +554,7 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
@@ -674,6 +676,7 @@ struct i40e_pf {
 	bool floating_veb_list[I40E_MAX_VF];
 	struct i40e_flow_list flow_list;
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
+	bool qinq_replace_flag;  /* QINQ filter replace is done */
 };
 
 enum pending_msg {
-- 
2.11.0

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

* [PATCH v5 3/5] net/i40e: parse QinQ pattern
  2017-03-30 16:01       ` Bernard Iremonger
                           ` (2 preceding siblings ...)
  2017-03-30 16:09         ` [PATCH v5 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  2017-03-31  0:58           ` Lu, Wenzhuo
  2017-03-30 16:09         ` [PATCH v5 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 145 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index dc456c338..bbec7dc1c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -127,6 +127,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -317,6 +329,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -347,6 +367,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1170,7 +1192,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1719,6 +1741,125 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if (eth_spec && eth_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				o_vlan_mask = vlan_mask;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				i_vlan_mask = vlan_mask;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Get filter specification */
+	if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) &&
+	    (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+	} else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v5 4/5] net/i40e: update destroy tunnel filter function
  2017-03-30 16:01       ` Bernard Iremonger
                           ` (3 preceding siblings ...)
  2017-03-30 16:09         ` [PATCH v5 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  2017-03-30 16:09         ` [PATCH v5 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index bbec7dc1c..9f541eaff 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2095,7 +2095,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v5 5/5] net/i40e: update tunnel filter restore function
  2017-03-30 16:01       ` Bernard Iremonger
                           ` (4 preceding siblings ...)
  2017-03-30 16:09         ` [PATCH v5 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-30 16:09         ` Bernard Iremonger
  5 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-30 16:09 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index bc07e628c..e3313b622 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10652,7 +10652,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* Re: [PATCH v5 3/5] net/i40e: parse QinQ pattern
  2017-03-30 16:09         ` [PATCH v5 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-31  0:58           ` Lu, Wenzhuo
  2017-03-31  8:01             ` Iremonger, Bernard
  0 siblings, 1 reply; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-31  0:58 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Bernard,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Friday, March 31, 2017 12:10 AM
> To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> Subject: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> 
> add QinQ pattern.
> add i40e_flow_parse_qinq_pattern function.
> add i40e_flow_parse_qinq_filter function.
> 
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
>  drivers/net/i40e/i40e_flow.c | 145
> ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 143 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index
> dc456c338..bbec7dc1c 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -1,7 +1,7 @@
>  /*-
>   *   BSD LICENSE
>   *
> - *   Copyright (c) 2016 Intel Corporation. All rights reserved.
> + *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
>   *
>   *   Redistribution and use in source and binary forms, with or without
>   *   modification, are permitted provided that the following conditions
> @@ -127,6 +127,18 @@ static int i40e_flow_destroy_tunnel_filter(struct
> i40e_pf *pf,  static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);  static
> int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);  static int
> i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
> +static int
> +i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
>  	.validate = i40e_flow_validate,
> @@ -317,6 +329,14 @@ static enum rte_flow_item_type pattern_mpls_4[] =
> {
>  	RTE_FLOW_ITEM_TYPE_END,
>  };
> 
> +/* Pattern matched QINQ */
> +static enum rte_flow_item_type pattern_qinq_1[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_VLAN,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
>  static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	/* Ethertype */
>  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -347,6
> +367,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
>  	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
>  	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
>  	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
> +	/* QINQ */
> +	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
>  };
> 
>  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> @@ -1170,7 +1192,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev
> *dev,
>  	return 0;
>  }
> 
> -/* Parse to get the action info of a tunnle filter
> +/* Parse to get the action info of a tunnel filter
>   * Tunnel action only supports PF, VF and QUEUE.
>   */
>  static int
> @@ -1719,6 +1741,125 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev
> *dev,  }
> 
>  static int
> +i40e_flow_parse_qinq_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_eth *eth_spec;
> +	const struct rte_flow_item_eth *eth_mask;
> +	const struct rte_flow_item_vlan *vlan_spec = NULL;
> +	const struct rte_flow_item_vlan *vlan_mask = NULL;
> +	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
> +	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
> +	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
> +	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
> +
> +	enum rte_flow_item_type item_type;
> +	bool vlan_flag = 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:
> +			eth_spec = (const struct rte_flow_item_eth *)item-
> >spec;
> +			eth_mask = (const struct rte_flow_item_eth *)item-
> >mask;
> +			if (eth_spec && eth_mask) {
Should it be (eth_spec || eth_mask)?
All  the other is good to me.

> +				rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ether spec/mask");
> +				return -rte_errno;
> +			}
> +			break;

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

* Re: [PATCH v5 3/5] net/i40e: parse QinQ pattern
  2017-03-31  0:58           ` Lu, Wenzhuo
@ 2017-03-31  8:01             ` Iremonger, Bernard
  2017-03-31  8:27               ` Lu, Wenzhuo
  0 siblings, 1 reply; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-31  8:01 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Friday, March 31, 2017 1:59 AM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>
> Subject: RE: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> 
> Hi Bernard,
> 
> > -----Original Message-----
> > From: Iremonger, Bernard
> > Sent: Friday, March 31, 2017 12:10 AM
> > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> > Subject: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> >
> > add QinQ pattern.
> > add i40e_flow_parse_qinq_pattern function.
> > add i40e_flow_parse_qinq_filter function.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> >  drivers/net/i40e/i40e_flow.c | 145
> > ++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 143 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c
> > b/drivers/net/i40e/i40e_flow.c index dc456c338..bbec7dc1c 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> > @@ -1,7 +1,7 @@
> >  /*-
> >   *   BSD LICENSE
> >   *
> > - *   Copyright (c) 2016 Intel Corporation. All rights reserved.
> > + *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
> >   *
> >   *   Redistribution and use in source and binary forms, with or without
> >   *   modification, are permitted provided that the following conditions
> > @@ -127,6 +127,18 @@ static int i40e_flow_destroy_tunnel_filter(struct
> > i40e_pf *pf,  static int i40e_flow_flush_fdir_filter(struct i40e_pf
> > *pf);  static int i40e_flow_flush_ethertype_filter(struct i40e_pf
> > *pf);  static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
> > +static int
> > +i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
> >  	.validate = i40e_flow_validate,
> > @@ -317,6 +329,14 @@ static enum rte_flow_item_type pattern_mpls_4[]
> =
> > {
> >  	RTE_FLOW_ITEM_TYPE_END,
> >  };
> >
> > +/* Pattern matched QINQ */
> > +static enum rte_flow_item_type pattern_qinq_1[] = {
> > +	RTE_FLOW_ITEM_TYPE_ETH,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_VLAN,
> > +	RTE_FLOW_ITEM_TYPE_END,
> > +};
> > +
> >  static struct i40e_valid_pattern i40e_supported_patterns[] = {
> >  	/* Ethertype */
> >  	{ pattern_ethertype, i40e_flow_parse_ethertype_filter }, @@ -347,6
> > +367,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] =
> > +{
> >  	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
> >  	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
> >  	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
> > +	/* QINQ */
> > +	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
> >  };
> >
> >  #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> > @@ -1170,7 +1192,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev
> > *dev,
> >  	return 0;
> >  }
> >
> > -/* Parse to get the action info of a tunnle filter
> > +/* Parse to get the action info of a tunnel filter
> >   * Tunnel action only supports PF, VF and QUEUE.
> >   */
> >  static int
> > @@ -1719,6 +1741,125 @@ i40e_flow_parse_mpls_filter(struct
> rte_eth_dev
> > *dev,  }
> >
> >  static int
> > +i40e_flow_parse_qinq_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_eth *eth_spec;
> > +	const struct rte_flow_item_eth *eth_mask;
> > +	const struct rte_flow_item_vlan *vlan_spec = NULL;
> > +	const struct rte_flow_item_vlan *vlan_mask = NULL;
> > +	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
> > +	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
> > +	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
> > +	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
> > +
> > +	enum rte_flow_item_type item_type;
> > +	bool vlan_flag = 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:
> > +			eth_spec = (const struct rte_flow_item_eth *)item-
> > >spec;
> > +			eth_mask = (const struct rte_flow_item_eth *)item-
> > >mask;
> > +			if (eth_spec && eth_mask) {
> Should it be (eth_spec || eth_mask)?
> All  the other is good to me.

No, I believe this is correct ( I tested it and it worked correctly).


> 
> > +				rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid ether spec/mask");
> > +				return -rte_errno;
> > +			}
> > +			break;

Regards,

Bernard.

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

* Re: [PATCH v5 3/5] net/i40e: parse QinQ pattern
  2017-03-31  8:01             ` Iremonger, Bernard
@ 2017-03-31  8:27               ` Lu, Wenzhuo
  0 siblings, 0 replies; 74+ messages in thread
From: Lu, Wenzhuo @ 2017-03-31  8:27 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin

Hi,

> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Friday, March 31, 2017 4:02 PM
> To: Lu, Wenzhuo; dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> Cc: Zhang, Helin
> Subject: RE: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: Lu, Wenzhuo
> > Sent: Friday, March 31, 2017 1:59 AM
> > To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> > Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>
> > Cc: Zhang, Helin <helin.zhang@intel.com>
> > Subject: RE: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> >
> > Hi Bernard,
> >
> > > -----Original Message-----
> > > From: Iremonger, Bernard
> > > Sent: Friday, March 31, 2017 12:10 AM
> > > To: dev@dpdk.org; Xing, Beilei; Wu, Jingjing
> > > Cc: Zhang, Helin; Lu, Wenzhuo; Iremonger, Bernard
> > > Subject: [PATCH v5 3/5] net/i40e: parse QinQ pattern
> > >
> > > add QinQ pattern.
> > > add i40e_flow_parse_qinq_pattern function.
> > > add i40e_flow_parse_qinq_filter function.
> > >
> > > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

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

* Re: [PATCH v5 2/5] net/i40e: add QinQ filter create function
  2017-03-30 16:09         ` [PATCH v5 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-31  9:43           ` Xing, Beilei
  0 siblings, 0 replies; 74+ messages in thread
From: Xing, Beilei @ 2017-03-31  9:43 UTC (permalink / raw)
  To: Iremonger, Bernard, dev, Wu, Jingjing
  Cc: Zhang, Helin, Lu, Wenzhuo, Stroe, Laura



> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Friday, March 31, 2017 12:10 AM
> To: dev@dpdk.org; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; Stroe, Laura <laura.stroe@intel.com>
> Subject: [PATCH v5 2/5] net/i40e: add QinQ filter create function
> 
> Add i40e_cloud_filter_qinq_create function, and call it from
> i40e_dev_consistent_tunnel_filter_set function.
> Replace the Outer IP filter with the QinQ filter.
> 
> QinQ allows multiple VLAN tags to be inserted into a single Ethernet frame. A
> QinQ frame is a frame that has two VLAN 802.1Q headers.
> 802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
> providers as a layer 2 VPN for customers.
> 
> Signed-off-by: Laura Stroe <laura.stroe@intel.com>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>

Acked-by: Beilei Xing <beilei.xing@intel.com>

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

* Re: [PATCH v5 0/5] net/i40e: QinQ filter
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
@ 2017-03-31 13:33           ` Ferruh Yigit
  2017-03-31 13:37             ` Iremonger, Bernard
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
                             ` (5 subsequent siblings)
  6 siblings, 1 reply; 74+ messages in thread
From: Ferruh Yigit @ 2017-03-31 13:33 UTC (permalink / raw)
  To: Bernard Iremonger, dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu

On 3/30/2017 5:09 PM, Bernard Iremonger wrote:
> This patchset depends on the following patch set:
> [dpdk-dev,v6,1/4] ethdev: add MPLS and GRE items
> 
> It adds support for QinQ filters.
> It uses the replace filter Admin Queue command.
> 
> Changes in v5:
> Rebase to latest dpdk-next-net.
> Rebase patches 2 and 3 following comments.
> Uses  map_5.88_ATT firmware.
> 
> Changes in v4:
> Reordered patches following comments.
> Revises patches 2 and 3 following comments.
> 
> Changes in v3:
> Rebase to latest dpdk-next-net.
> Revised patches 1-3  following comments.
> Added patches 4 and 5.
> 
> Changes in v2:
> Rebase to latest dpdk-next-net.
> Reordered patches, and reduced from 4 to 3 patches.
> 
> Bernard Iremonger (5):
>   net/i40e: initialise L3 MAP register
>   net/i40e: add QinQ filter create function
>   net/i40e: parse QinQ pattern
>   net/i40e: update destroy tunnel filter function
>   net/i40e: update tunnel filter restore function

Hi Bernard,

Patch doesn't merged cleanly, can you please rebase it on top of latest
next-net?

Meanwhile, there are some long-line checkpatch warnings, can you please
address them in next release?

Please feel free to carry acks.

Thanks,
ferruh

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

* Re: [PATCH v5 0/5] net/i40e: QinQ filter
  2017-03-31 13:33           ` Ferruh Yigit
@ 2017-03-31 13:37             ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-31 13:37 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Xing, Beilei, Wu, Jingjing
  Cc: Zhang, Helin, Lu, Wenzhuo, Iremonger, Bernard

Hi Ferruh,



> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Friday, March 31, 2017 2:33 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v5 0/5] net/i40e: QinQ filter
> 
> On 3/30/2017 5:09 PM, Bernard Iremonger wrote:
> > This patchset depends on the following patch set:
> > [dpdk-dev,v6,1/4] ethdev: add MPLS and GRE items
> >
> > It adds support for QinQ filters.
> > It uses the replace filter Admin Queue command.
> >
> > Changes in v5:
> > Rebase to latest dpdk-next-net.
> > Rebase patches 2 and 3 following comments.
> > Uses  map_5.88_ATT firmware.
> >
> > Changes in v4:
> > Reordered patches following comments.
> > Revises patches 2 and 3 following comments.
> >
> > Changes in v3:
> > Rebase to latest dpdk-next-net.
> > Revised patches 1-3  following comments.
> > Added patches 4 and 5.
> >
> > Changes in v2:
> > Rebase to latest dpdk-next-net.
> > Reordered patches, and reduced from 4 to 3 patches.
> >
> > Bernard Iremonger (5):
> >   net/i40e: initialise L3 MAP register
> >   net/i40e: add QinQ filter create function
> >   net/i40e: parse QinQ pattern
> >   net/i40e: update destroy tunnel filter function
> >   net/i40e: update tunnel filter restore function
> 
> Hi Bernard,
> 
> Patch doesn't merged cleanly, can you please rebase it on top of latest next-
> net?
> 
> Meanwhile, there are some long-line checkpatch warnings, can you please
> address them in next release?
> 
> Please feel free to carry acks.
> 
> Thanks,
> Ferruh

I will rebase on top of latest next-net release and fix checkpatch long-line warnings.

Regards,

Bernard.

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

* [PATCH v6 0/5] net/i40e: QinQ filter
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
  2017-03-31 13:33           ` Ferruh Yigit
@ 2017-03-31 15:18           ` Bernard Iremonger
  2017-03-31 16:53             ` Ferruh Yigit
                               ` (6 more replies)
  2017-03-31 15:18           ` [PATCH v6 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
                             ` (4 subsequent siblings)
  6 siblings, 7 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

It adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v6:
Rebase to latest dpdk-next-net.
Fix checkpatch warnings.

Changes in v5:
Rebase to latest dpdk-next-net.
Rebase patches 2 and 3 following comments.
Uses  map_5.88 firmware.

Changes in v4:
Reordered patches following comments.
Revises patches 2 and 3 following comments.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2: 
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (5):
  net/i40e: initialise L3 MAP register
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 130 ++++++++++++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 drivers/net/i40e/i40e_flow.c   | 149 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 279 insertions(+), 5 deletions(-)

-- 
2.11.0

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

* [PATCH v6 1/5] net/i40e: initialise L3 MAP register
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
  2017-03-31 13:33           ` Ferruh Yigit
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
@ 2017-03-31 15:18           ` Bernard Iremonger
  2017-03-31 15:18           ` [PATCH v6 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
                             ` (3 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00079bb9c..2a3957d4a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -688,6 +688,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1129,6 +1132,11 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40), 0x00000028, NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v6 2/5] net/i40e: add QinQ filter create function
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
                             ` (2 preceding siblings ...)
  2017-03-31 15:18           ` [PATCH v6 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-31 15:18           ` Bernard Iremonger
  2017-03-31 15:18           ` [PATCH v6 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
                             ` (2 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 7880 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 117 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 2 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2a3957d4a..e49f8dc5b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -7154,6 +7155,22 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (!pf->qinq_replace_flag) {
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0)
+				PMD_DRV_LOG(ERR, "Failed to create a qinq tunnel filter.");
+			pf->qinq_replace_flag = 1;
+		}
+		/*	Add in the General fields the values of
+		 *	the Outer and Inner VLAN
+		 *	Big Buffer should be set, see changes in
+		 *	i40e_aq_add_cloud_filters
+		 */
+		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+		big_buffer = 1;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7167,6 +7184,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -12281,3 +12301,100 @@ rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
 
 	return status;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte 0 = 8 (outer vlan FV index).
+ *			Byte 1 = 0 (rsv)
+ *			Byte 2-3 = 0x0fff
+ *		ii.	Byte 0 = 37 (inner vlan FV index).
+ *			Byte 1 =0 (rsv)
+ *			Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte 0 = 0x80 | 7 (valid | Stag).
+ *			Byte 1-3 = 0 (rsv)
+ *		ii.	Byte 8 = 0x80 | 0x10 (valid | new l1 filter step1)
+ *			Byte 9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0;
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |= I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace, &filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index a8ecea4f0..f537a3a90 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,6 +554,7 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
@@ -674,6 +676,7 @@ struct i40e_pf {
 	bool floating_veb_list[I40E_MAX_VF];
 	struct i40e_flow_list flow_list;
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
+	bool qinq_replace_flag;  /* QINQ filter replace is done */
 };
 
 enum pending_msg {
-- 
2.11.0

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

* [PATCH v6 3/5] net/i40e: parse QinQ pattern
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
                             ` (3 preceding siblings ...)
  2017-03-31 15:18           ` [PATCH v6 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-31 15:18           ` Bernard Iremonger
  2017-03-31 15:18           ` [PATCH v6 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-31 15:18           ` [PATCH v6 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 145 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index dc456c338..bbec7dc1c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -127,6 +127,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -317,6 +329,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -347,6 +367,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1170,7 +1192,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1719,6 +1741,125 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if (eth_spec && eth_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				o_vlan_mask = vlan_mask;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				i_vlan_mask = vlan_mask;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Get filter specification */
+	if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) &&
+	    (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+	} else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v6 4/5] net/i40e: update destroy tunnel filter function
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
                             ` (4 preceding siblings ...)
  2017-03-31 15:18           ` [PATCH v6 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-31 15:18           ` Bernard Iremonger
  2017-03-31 15:18           ` [PATCH v6 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index bbec7dc1c..9f541eaff 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2095,7 +2095,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v6 5/5] net/i40e: update tunnel filter restore function
  2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
                             ` (5 preceding siblings ...)
  2017-03-31 15:18           ` [PATCH v6 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-31 15:18           ` Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 15:18 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e49f8dc5b..ca769361e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10654,7 +10654,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* Re: [PATCH v6 0/5] net/i40e: QinQ filter
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
@ 2017-03-31 16:53             ` Ferruh Yigit
  2017-03-31 17:05               ` Iremonger, Bernard
  2017-03-31 17:58             ` [PATCH v7 " Bernard Iremonger
                               ` (5 subsequent siblings)
  6 siblings, 1 reply; 74+ messages in thread
From: Ferruh Yigit @ 2017-03-31 16:53 UTC (permalink / raw)
  To: Bernard Iremonger, dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu

On 3/31/2017 4:18 PM, Bernard Iremonger wrote:
> It adds support for QinQ filters.
> It uses the replace filter Admin Queue command.
> 
> Changes in v6:
> Rebase to latest dpdk-next-net.
> Fix checkpatch warnings.
> 
> Changes in v5:
> Rebase to latest dpdk-next-net.
> Rebase patches 2 and 3 following comments.
> Uses  map_5.88 firmware.
> 
> Changes in v4:
> Reordered patches following comments.
> Revises patches 2 and 3 following comments.
> 
> Changes in v3:
> Rebase to latest dpdk-next-net.
> Revised patches 1-3  following comments.
> Added patches 4 and 5.
> 
> Changes in v2: 
> Rebase to latest dpdk-next-net.
> Reordered patches, and reduced from 4 to 3 patches.
> 
> Bernard Iremonger (5):
>   net/i40e: initialise L3 MAP register
>   net/i40e: add QinQ filter create function
>   net/i40e: parse QinQ pattern
>   net/i40e: update destroy tunnel filter function
>   net/i40e: update tunnel filter restore function

Still getting some long-line checkpatch warnings [1], can you please
check them?

Thanks,
ferruh

[1]
WARNING:LONG_LINE: line over 80 characters
#46: FILE: drivers/net/i40e/i40e_ethdev.c:1136:
+       ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
0x00000028, NULL);

WARNING:LONG_LINE: line over 80 characters
#144: FILE: drivers/net/i40e/i40e_ethdev.c:12363:
+       filter_replace.old_filter_type =
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;

WARNING:LONG_LINE: line over 80 characters
#150: FILE: drivers/net/i40e/i40e_ethdev.c:12369:
+       filter_replace_buf.data[0] |=
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;

WARNING:LONG_LINE: line over 80 characters
#154: FILE: drivers/net/i40e/i40e_ethdev.c:12373:
+       filter_replace_buf.data[4] =
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;

WARNING:LONG_LINE: line over 80 characters
#155: FILE: drivers/net/i40e/i40e_ethdev.c:12374:
+       filter_replace_buf.data[4] |=
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;

WARNING:LONG_LINE: line over 80 characters
#159: FILE: drivers/net/i40e/i40e_ethdev.c:12378:
+       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
&filter_replace_buf);

WARNING:LONG_LINE: line over 80 characters
#176: FILE: drivers/net/i40e/i40e_ethdev.c:12395:
+       filter_replace_buf.data[0] |=
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;

WARNING:LONG_LINE: line over 80 characters
#178: FILE: drivers/net/i40e/i40e_ethdev.c:12397:
+       filter_replace_buf.data[4] |=
I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;

WARNING:LONG_LINE: line over 80 characters
#179: FILE: drivers/net/i40e/i40e_ethdev.c:12398:
+       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
&filter_replace_buf);

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

* Re: [PATCH v6 0/5] net/i40e: QinQ filter
  2017-03-31 16:53             ` Ferruh Yigit
@ 2017-03-31 17:05               ` Iremonger, Bernard
  0 siblings, 0 replies; 74+ messages in thread
From: Iremonger, Bernard @ 2017-03-31 17:05 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Xing, Beilei, Wu, Jingjing; +Cc: Zhang, Helin, Lu, Wenzhuo

Hi Ferruh,


> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Friday, March 31, 2017 5:53 PM
> To: Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org;
> Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Cc: Zhang, Helin <helin.zhang@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v6 0/5] net/i40e: QinQ filter
> 
> On 3/31/2017 4:18 PM, Bernard Iremonger wrote:
> > It adds support for QinQ filters.
> > It uses the replace filter Admin Queue command.
> >
> > Changes in v6:
> > Rebase to latest dpdk-next-net.
> > Fix checkpatch warnings.
> >
> > Changes in v5:
> > Rebase to latest dpdk-next-net.
> > Rebase patches 2 and 3 following comments.
> > Uses  map_5.88 firmware.
> >
> > Changes in v4:
> > Reordered patches following comments.
> > Revises patches 2 and 3 following comments.
> >
> > Changes in v3:
> > Rebase to latest dpdk-next-net.
> > Revised patches 1-3  following comments.
> > Added patches 4 and 5.
> >
> > Changes in v2:
> > Rebase to latest dpdk-next-net.
> > Reordered patches, and reduced from 4 to 3 patches.
> >
> > Bernard Iremonger (5):
> >   net/i40e: initialise L3 MAP register
> >   net/i40e: add QinQ filter create function
> >   net/i40e: parse QinQ pattern
> >   net/i40e: update destroy tunnel filter function
> >   net/i40e: update tunnel filter restore function
> 
> Still getting some long-line checkpatch warnings [1], can you please check
> them?
> 
> Thanks,
> ferruh
> 
> [1]
> WARNING:LONG_LINE: line over 80 characters
> #46: FILE: drivers/net/i40e/i40e_ethdev.c:1136:
> +       ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
> 0x00000028, NULL);
> 
> WARNING:LONG_LINE: line over 80 characters
> #144: FILE: drivers/net/i40e/i40e_ethdev.c:12363:
> +       filter_replace.old_filter_type =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> 
> WARNING:LONG_LINE: line over 80 characters
> #150: FILE: drivers/net/i40e/i40e_ethdev.c:12369:
> +       filter_replace_buf.data[0] |=
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> 
> WARNING:LONG_LINE: line over 80 characters
> #154: FILE: drivers/net/i40e/i40e_ethdev.c:12373:
> +       filter_replace_buf.data[4] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
> 
> WARNING:LONG_LINE: line over 80 characters
> #155: FILE: drivers/net/i40e/i40e_ethdev.c:12374:
> +       filter_replace_buf.data[4] |=
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> 
> WARNING:LONG_LINE: line over 80 characters
> #159: FILE: drivers/net/i40e/i40e_ethdev.c:12378:
> +       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> &filter_replace_buf);
> 
> WARNING:LONG_LINE: line over 80 characters
> #176: FILE: drivers/net/i40e/i40e_ethdev.c:12395:
> +       filter_replace_buf.data[0] |=
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> 
> WARNING:LONG_LINE: line over 80 characters
> #178: FILE: drivers/net/i40e/i40e_ethdev.c:12397:
> +       filter_replace_buf.data[4] |=
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> 
> WARNING:LONG_LINE: line over 80 characters
> #179: FILE: drivers/net/i40e/i40e_ethdev.c:12398:
> +       ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> &filter_replace_buf);

The checkpatch script is allowing lines up to 90 characters now.

Previously long lines were acceptable .

Regards,

Bernard.

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

* [PATCH v7 0/5] net/i40e: QinQ filter
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
  2017-03-31 16:53             ` Ferruh Yigit
@ 2017-03-31 17:58             ` Bernard Iremonger
  2017-04-03  9:24               ` Ferruh Yigit
  2017-03-31 17:58             ` [PATCH v7 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
                               ` (4 subsequent siblings)
  6 siblings, 1 reply; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

it adds support for QinQ filters.
It uses the replace filter Admin Queue command.

Changes in v7:
Rebase to latest dpdk-next-net.
Fix checkpatch warnings.

Changes in v6:
Rebase to latest dpdk-next-net.
Fix checkpatch warnings.

Changes in v5:
Rebase to latest dpdk-next-net.
Rebase patches 2 and 3 following comments.
Uses  map_5.88 firmware.

Changes in v4:
Reordered patches following comments.
Revises patches 2 and 3 following comments.

Changes in v3:
Rebase to latest dpdk-next-net.
Revised patches 1-3  following comments.
Added patches 4 and 5.

Changes in v2:
Rebase to latest dpdk-next-net.
Reordered patches, and reduced from 4 to 3 patches.

Bernard Iremonger (5):
  net/i40e: initialise L3 MAP register
  net/i40e: add QinQ filter create function
  net/i40e: parse QinQ pattern
  net/i40e: update destroy tunnel filter function
  net/i40e: update tunnel filter restore function

 drivers/net/i40e/i40e_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 drivers/net/i40e/i40e_flow.c   | 149 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 289 insertions(+), 5 deletions(-)

-- 
2.11.0

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

* [PATCH v7 1/5] net/i40e: initialise L3 MAP register
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
  2017-03-31 16:53             ` Ferruh Yigit
  2017-03-31 17:58             ` [PATCH v7 " Bernard Iremonger
@ 2017-03-31 17:58             ` Bernard Iremonger
  2017-03-31 17:58             ` [PATCH v7 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
                               ` (3 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The L3 MAP register is initialised to support QinQ
cloud filters.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 00079bb9c..3a06f0c78 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -688,6 +688,9 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio");
 #ifndef I40E_GLQF_PIT
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
+#ifndef I40E_GLQF_L3_MAP
+#define I40E_GLQF_L3_MAP(_i) (0x0026C700 + ((_i) * 4))
+#endif
 
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
@@ -1129,6 +1132,12 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 		     ((hw->nvm.version >> 4) & 0xff),
 		     (hw->nvm.version & 0xf), hw->nvm.eetrack);
 
+	/* initialise the L3_MAP register */
+	ret = i40e_aq_debug_write_register(hw, I40E_GLQF_L3_MAP(40),
+				   0x00000028,	NULL);
+	if (ret)
+		PMD_INIT_LOG(ERR, "Failed to write L3 MAP register %d", ret);
+
 	/* Need the special FW version to support floating VEB */
 	config_floating_veb(dev);
 	/* Clear PXE mode */
-- 
2.11.0

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

* [PATCH v7 2/5] net/i40e: add QinQ filter create function
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
                               ` (2 preceding siblings ...)
  2017-03-31 17:58             ` [PATCH v7 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
@ 2017-03-31 17:58             ` Bernard Iremonger
  2017-03-31 17:58             ` [PATCH v7 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
                               ` (2 subsequent siblings)
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu
  Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger, Laura Stroe

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 7912 bytes --]

Add i40e_cloud_filter_qinq_create function, and call it
from i40e_dev_consistent_tunnel_filter_set function.
Replace the Outer IP filter with the QinQ filter.

QinQ allows multiple VLAN tags to be inserted into a single Ethernet
frame. A QinQ frame is a frame that has two VLAN 802.1Q headers.
802.1Q tunneling (QinQ) is a technique often used by Metro Ethernet
providers as a layer 2 VPN for customers.

Signed-off-by: Laura Stroe <laura.stroe@intel.com>
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 126 +++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |   5 +-
 2 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3a06f0c78..09c485e8a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -423,6 +423,7 @@ static int i40e_tunnel_filter_convert(
 	struct i40e_tunnel_filter *tunnel_filter);
 static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 				struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
 
 static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
 static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
@@ -7155,6 +7156,23 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		big_buffer = 1;
 		tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSoGRE;
 		break;
+	case I40E_TUNNEL_TYPE_QINQ:
+		if (!pf->qinq_replace_flag) {
+			ret = i40e_cloud_filter_qinq_create(pf);
+			if (ret < 0)
+				PMD_DRV_LOG(ERR,
+					"Failed to create a qinq tunnel filter.");
+			pf->qinq_replace_flag = 1;
+		}
+		/*	Add in the General fields the values of
+		 *	the Outer and Inner VLAN
+		 *	Big Buffer should be set, see changes in
+		 *	i40e_aq_add_cloud_filters
+		 */
+		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
+		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
+		big_buffer = 1;
+		break;
 	default:
 		/* Other tunnel types is not supported. */
 		PMD_DRV_LOG(ERR, "tunnel type is not supported.");
@@ -7168,6 +7186,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_MPLSoGRE)
 		pfilter->element.flags =
 			I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE;
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
+		pfilter->element.flags |=
+			I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
 	else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
@@ -12282,3 +12303,108 @@ rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
 
 	return status;
 }
+
+/* Create a QinQ cloud filter
+ *
+ * The Fortville NIC has limited resources for tunnel filters,
+ * so we can only reuse existing filters.
+ *
+ * In step 1 we define which Field Vector fields can be used for
+ * filter types.
+ * As we do not have the inner tag defined as a field,
+ * we have to define it first, by reusing one of L1 entries.
+ *
+ * In step 2 we are replacing one of existing filter types with
+ * a new one for QinQ.
+ * As we reusing L1 and replacing L2, some of the default filter
+ * types will disappear,which depends on L1 and L2 entries we reuse.
+ *
+ * Step 1: Create L1 filter of outer vlan (12b) + inner vlan (12b)
+ *
+ * 1.	Create L1 filter of outer vlan (12b) which will be in use
+ *		later when we define the cloud filter.
+ *	a.	Valid_flags.replace_cloud = 0
+ *	b.	Old_filter = 10 (Stag_Inner_Vlan)
+ *	c.	New_filter = 0x10
+ *	d.	TR bit = 0xff (optional, not used here)
+ *	e.	Buffer – 2 entries:
+ *		i.	Byte 0 = 8 (outer vlan FV index).
+ *			Byte 1 = 0 (rsv)
+ *			Byte 2-3 = 0x0fff
+ *		ii.	Byte 0 = 37 (inner vlan FV index).
+ *			Byte 1 =0 (rsv)
+ *			Byte 2-3 = 0x0fff
+ *
+ * Step 2:
+ * 2.	Create cloud filter using two L1 filters entries: stag and
+ *		new filter(outer vlan+ inner vlan)
+ *	a.	Valid_flags.replace_cloud = 1
+ *	b.	Old_filter = 1 (instead of outer IP)
+ *	c.	New_filter = 0x10
+ *	d.	Buffer – 2 entries:
+ *		i.	Byte 0 = 0x80 | 7 (valid | Stag).
+ *			Byte 1-3 = 0 (rsv)
+ *		ii.	Byte 8 = 0x80 | 0x10 (valid | new l1 filter step1)
+ *			Byte 9-11 = 0 (rsv)
+ */
+static int
+i40e_cloud_filter_qinq_create(struct i40e_pf *pf)
+{
+	int ret = -ENOTSUP;
+	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);
+
+	/* Init */
+	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_STAG_IVLAN;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+	filter_replace.tr_bit = 0;
+
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[2] = 0xff;
+	filter_replace_buf.data[3] = 0x0f;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	/* Field Vector 12b mask */
+	filter_replace_buf.data[6] = 0xff;
+	filter_replace_buf.data[7] = 0x0f;
+	ret = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+			&filter_replace_buf);
+	if (ret != I40E_SUCCESS)
+		return ret;
+
+	/* Apply the second L2 cloud filter */
+	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 L2 filter, input for L2 filter will be L1 filter  */
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+	filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ;
+
+	/* 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_CLOUD_FILTER_CUSTOM_QINQ;
+	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;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index a8ecea4f0..f537a3a90 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -505,6 +505,7 @@ struct i40e_ethertype_rule {
 #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_CUSTOM_QINQ 0x10
 #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
@@ -553,6 +554,7 @@ enum i40e_tunnel_type {
 	I40E_L2_TUNNEL_TYPE_E_TAG,
 	I40E_TUNNEL_TYPE_MPLSoUDP,
 	I40E_TUNNEL_TYPE_MPLSoGRE,
+	I40E_TUNNEL_TYPE_QINQ,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
@@ -674,6 +676,7 @@ struct i40e_pf {
 	bool floating_veb_list[I40E_MAX_VF];
 	struct i40e_flow_list flow_list;
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
+	bool qinq_replace_flag;  /* QINQ filter replace is done */
 };
 
 enum pending_msg {
-- 
2.11.0

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

* [PATCH v7 3/5] net/i40e: parse QinQ pattern
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
                               ` (3 preceding siblings ...)
  2017-03-31 17:58             ` [PATCH v7 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
@ 2017-03-31 17:58             ` Bernard Iremonger
  2017-03-31 17:58             ` [PATCH v7 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
  2017-03-31 17:58             ` [PATCH v7 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

add QinQ pattern.
add i40e_flow_parse_qinq_pattern function.
add i40e_flow_parse_qinq_filter function.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 145 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index dc456c338..bbec7dc1c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *   Copyright (c) 2016-2017 Intel Corporation. All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
  *   modification, are permitted provided that the following conditions
@@ -127,6 +127,18 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
+static int
+i40e_flow_parse_qinq_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_parse_qinq_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_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
@@ -317,6 +329,14 @@ static enum rte_flow_item_type pattern_mpls_4[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* Pattern matched QINQ */
+static enum rte_flow_item_type pattern_qinq_1[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* Ethertype */
 	{ pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -347,6 +367,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	{ pattern_mpls_2, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_3, i40e_flow_parse_mpls_filter },
 	{ pattern_mpls_4, i40e_flow_parse_mpls_filter },
+	/* QINQ */
+	{ pattern_qinq_1, i40e_flow_parse_qinq_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -1170,7 +1192,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/* Parse to get the action info of a tunnle filter
+/* Parse to get the action info of a tunnel filter
  * Tunnel action only supports PF, VF and QUEUE.
  */
 static int
@@ -1719,6 +1741,125 @@ i40e_flow_parse_mpls_filter(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_flow_parse_qinq_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_eth *eth_spec;
+	const struct rte_flow_item_eth *eth_mask;
+	const struct rte_flow_item_vlan *vlan_spec = NULL;
+	const struct rte_flow_item_vlan *vlan_mask = NULL;
+	const struct rte_flow_item_vlan *i_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *i_vlan_mask = NULL;
+	const struct rte_flow_item_vlan *o_vlan_spec = NULL;
+	const struct rte_flow_item_vlan *o_vlan_mask = NULL;
+
+	enum rte_flow_item_type item_type;
+	bool vlan_flag = 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:
+			eth_spec = (const struct rte_flow_item_eth *)item->spec;
+			eth_mask = (const struct rte_flow_item_eth *)item->mask;
+			if (eth_spec && eth_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ether spec/mask");
+				return -rte_errno;
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan_spec =
+				(const struct rte_flow_item_vlan *)item->spec;
+			vlan_mask =
+				(const struct rte_flow_item_vlan *)item->mask;
+
+			if (!(vlan_spec && vlan_mask)) {
+				rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Invalid vlan item");
+				return -rte_errno;
+			}
+
+			if (!vlan_flag) {
+				o_vlan_spec = vlan_spec;
+				o_vlan_mask = vlan_mask;
+				vlan_flag = 1;
+			} else {
+				i_vlan_spec = vlan_spec;
+				i_vlan_mask = vlan_mask;
+				vlan_flag = 0;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/* Get filter specification */
+	if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) &&
+	    (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
+			& I40E_TCI_MASK;
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
+			& I40E_TCI_MASK;
+	} else {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   NULL,
+					   "Invalid filter type");
+			return -rte_errno;
+	}
+
+	filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
+	return 0;
+}
+
+static int
+i40e_flow_parse_qinq_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_qinq_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[],
-- 
2.11.0

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

* [PATCH v7 4/5] net/i40e: update destroy tunnel filter function
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
                               ` (4 preceding siblings ...)
  2017-03-31 17:58             ` [PATCH v7 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
@ 2017-03-31 17:58             ` Bernard Iremonger
  2017-03-31 17:58             ` [PATCH v7 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when removing a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_flow.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index bbec7dc1c..9f541eaff 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2095,7 +2095,9 @@ i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 	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))
+	    I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+	    ((filter->input.flags & I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+	    I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 		big_buffer = 1;
 
 	if (big_buffer)
-- 
2.11.0

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

* [PATCH v7 5/5] net/i40e: update tunnel filter restore function
  2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
                               ` (5 preceding siblings ...)
  2017-03-31 17:58             ` [PATCH v7 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
@ 2017-03-31 17:58             ` Bernard Iremonger
  6 siblings, 0 replies; 74+ messages in thread
From: Bernard Iremonger @ 2017-03-31 17:58 UTC (permalink / raw)
  To: dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu, Bernard Iremonger

The QinQ filter uses big buffers, set the big_buffer flag
when restoring a QinQ filter.

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 09c485e8a..4b61d9935 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10656,7 +10656,10 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoUDP) ||
 		    ((f->input.flags &
 		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ==
-		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE))
+		     I40E_AQC_ADD_CLOUD_FILTER_TEID_MPLSoGRE) ||
+		    ((f->input.flags &
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ) ==
+		     I40E_AQC_ADD_CLOUD_FILTER_CUSTOM_QINQ))
 			big_buffer = 1;
 
 		if (big_buffer)
-- 
2.11.0

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

* Re: [PATCH v7 0/5] net/i40e: QinQ filter
  2017-03-31 17:58             ` [PATCH v7 " Bernard Iremonger
@ 2017-04-03  9:24               ` Ferruh Yigit
  0 siblings, 0 replies; 74+ messages in thread
From: Ferruh Yigit @ 2017-04-03  9:24 UTC (permalink / raw)
  To: Bernard Iremonger, dev, beilei.xing, jingjing.wu; +Cc: helin.zhang, wenzhuo.lu

On 3/31/2017 6:58 PM, Bernard Iremonger wrote:
> it adds support for QinQ filters.
> It uses the replace filter Admin Queue command.
> 
<...>
> 
> Bernard Iremonger (5):
>   net/i40e: initialise L3 MAP register
>   net/i40e: add QinQ filter create function
>   net/i40e: parse QinQ pattern
>   net/i40e: update destroy tunnel filter function
>   net/i40e: update tunnel filter restore function

Series applied to dpdk-next-net/master, thanks.

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

end of thread, other threads:[~2017-04-03  9:24 UTC | newest]

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03 14:48 [PATCH v1 0/4] net/i40e: QinQ filter Bernard Iremonger
2017-03-03 14:48 ` [PATCH v1 1/4] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-03 14:48 ` [PATCH v1 2/4] net/i40e: add QinQ wrapper function Bernard Iremonger
2017-03-03 14:48 ` [PATCH v1 3/4] net/i40e: changes to consistent filter set Bernard Iremonger
2017-03-03 14:48 ` [PATCH v1 4/4] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-23 16:38 ` [PATCH v2 0/3] net/i40e: QinQ filter Bernard Iremonger
2017-03-28 16:20   ` [PATCH v3 0/5] " Bernard Iremonger
2017-03-29 16:41     ` [PATCH v4 " Bernard Iremonger
2017-03-30 16:01       ` Bernard Iremonger
2017-03-30 16:09         ` [PATCH v5 " Bernard Iremonger
2017-03-31 13:33           ` Ferruh Yigit
2017-03-31 13:37             ` Iremonger, Bernard
2017-03-31 15:18           ` [PATCH v6 " Bernard Iremonger
2017-03-31 16:53             ` Ferruh Yigit
2017-03-31 17:05               ` Iremonger, Bernard
2017-03-31 17:58             ` [PATCH v7 " Bernard Iremonger
2017-04-03  9:24               ` Ferruh Yigit
2017-03-31 17:58             ` [PATCH v7 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-31 17:58             ` [PATCH v7 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-31 17:58             ` [PATCH v7 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-31 17:58             ` [PATCH v7 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-31 17:58             ` [PATCH v7 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-31 15:18           ` [PATCH v6 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-31 15:18           ` [PATCH v6 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-31 15:18           ` [PATCH v6 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-31 15:18           ` [PATCH v6 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-31 15:18           ` [PATCH v6 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-30 16:09         ` [PATCH v5 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-30 16:09         ` [PATCH v5 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-31  9:43           ` Xing, Beilei
2017-03-30 16:09         ` [PATCH v5 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-31  0:58           ` Lu, Wenzhuo
2017-03-31  8:01             ` Iremonger, Bernard
2017-03-31  8:27               ` Lu, Wenzhuo
2017-03-30 16:09         ` [PATCH v5 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-30 16:09         ` [PATCH v5 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-30 16:01       ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-30 16:01       ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-30 16:01       ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-30 16:01       ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-30 16:01       ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-29 16:41     ` [PATCH v4 1/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-30  0:54       ` Lu, Wenzhuo
2017-03-29 16:41     ` [PATCH v4 2/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-30  0:57       ` Lu, Wenzhuo
2017-03-29 16:41     ` [PATCH v4 3/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-29 16:41     ` [PATCH v4 4/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-29 16:41     ` [PATCH v4 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-28 16:20   ` [PATCH v3 1/5] net/i40e: add QinQ filter create function Bernard Iremonger
2017-03-28 16:20   ` [PATCH v3 2/5] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-29  1:25     ` Lu, Wenzhuo
2017-03-29 15:10       ` Iremonger, Bernard
2017-03-29  2:46     ` Xing, Beilei
2017-03-29  6:16       ` Xing, Beilei
2017-03-28 16:20   ` [PATCH v3 3/5] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-28 16:20   ` [PATCH v3 4/5] net/i40e: initialise L3 MAP register Bernard Iremonger
2017-03-29  1:24     ` Xing, Beilei
2017-03-29  8:27       ` Iremonger, Bernard
2017-03-29  1:53     ` Lu, Wenzhuo
2017-03-29  8:56       ` Iremonger, Bernard
2017-03-28 16:20   ` [PATCH v3 5/5] net/i40e: update tunnel filter restore function Bernard Iremonger
2017-03-29  1:54     ` Lu, Wenzhuo
2017-03-23 16:38 ` [PATCH v2 1/3] net/i40e: add QinQ wrapper function Bernard Iremonger
2017-03-28  8:11   ` Lu, Wenzhuo
2017-03-28 11:09     ` Iremonger, Bernard
2017-03-28 13:23       ` Iremonger, Bernard
2017-03-29  0:52         ` Lu, Wenzhuo
2017-03-29  9:11           ` Iremonger, Bernard
2017-03-23 16:38 ` [PATCH v2 2/3] net/i40e: parse QinQ pattern Bernard Iremonger
2017-03-28  8:45   ` Lu, Wenzhuo
2017-03-28 11:12     ` Iremonger, Bernard
2017-03-23 16:38 ` [PATCH v2 3/3] net/i40e: update destroy tunnel filter function Bernard Iremonger
2017-03-28  8:54   ` Lu, Wenzhuo
2017-03-28 11:13     ` Iremonger, Bernard

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.