All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
@ 2016-01-29  7:03 Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 1/8] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                   ` (15 more replies)
  0 siblings, 16 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

Wenzhuo Lu (8):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel config
  ixgbe: support l2 tunnel config
  app/testpmd: add CLIs for l2 tunnel config
  lib/librte_ether: support new l2 tunnel operation
  ixgbe: support l2 tunnel operation
  app/testpmd: add CLIs for E-tag operation
  doc: add release note for E-tag

 app/test-pmd/cmdline.c               | 599 +++++++++++++++++++++++++++++++++++
 doc/guides/rel_notes/release_2_3.rst |   6 +
 drivers/net/ixgbe/ixgbe_ethdev.c     | 507 +++++++++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h      |   9 +
 lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
 lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
 6 files changed, 1648 insertions(+)

-- 
1.9.3

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

* [PATCH 1/8] ixgbe: select pool by MAC when using double VLAN
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 2/8] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4c4c6df..83df0c0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH 2/8] lib/librte_ether: support l2 tunnel config
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 1/8] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 3/8] ixgbe: " Wenzhuo Lu
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration.
The support includes ether type modification and the tunnel support
enabling/disabling.
Ether type modification means modifying the ether type of a specific
type of tunnel. So the packet with this ether type will be parsed as
this type of tunnel.
Enabling/disabling a tunnel support means enabling/disabling the
ability of parsing the specific type of tunnel. This ability should
be enabled before we enable filtering, forwarding, offloading for
this specific type of tunnel.
Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h |  9 +++++
 lib/librte_ether/rte_ethdev.c   | 61 ++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h   | 84 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index ed971b4..1b90e09 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3239,3 +3239,64 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_enable)(dev, l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index bada8ad..9b594b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,14 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1269,20 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable a type of l2 tunnel */
+
+typedef int (*eth_l2_tunnel_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable a type of l2 tunnel */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1465,12 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable a type of l2 tunnel */
+	eth_l2_tunnel_enable_t l2_tunnel_enable;
+	/** Disable a type of l2 tunnel */
+	eth_l2_tunnel_disable_t l2_tunnel_disable;
 };
 
 /**
@@ -3887,6 +3915,62 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets depend on
+ * this ability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets will not
+ * work either even if they're enabled.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH 3/8] ixgbe: support l2 tunnel config
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 1/8] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 2/8] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 4/8] app/testpmd: add CLIs for " Wenzhuo Lu
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration.
Support modifying ether type of a type of l2 tunnel.
Support enabling and disabling the support of a type of l2 tunnel.
Only E-tag tunnel is supported now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 83df0c0..55ab474 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,10 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
+	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
 };
 
 /*
@@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH 4/8] app/testpmd: add CLIs for l2 tunnel config
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (2 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 3/8] ixgbe: " Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 5/8] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 73298c9..d409934 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -9630,6 +9630,261 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	portid_t pid;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis)) {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_enable(pid, l2_tunnel_type);
+		}
+	} else {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_disable(pid, l2_tunnel_type);
+		}
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_enable(res->id, l2_tunnel_type);
+	else
+		rte_eth_dev_l2_tunnel_disable(res->id, l2_tunnel_type);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9771,6 +10026,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
-- 
1.9.3

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

* [PATCH 5/8] lib/librte_ether: support new l2 tunnel operation
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (3 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 4/8] app/testpmd: add CLIs for " Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 6/8] ixgbe: support " Wenzhuo Lu
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add functions to support the new l2 tunnel operation.
1, Insertion and stripping for l2 tunnel tag.
2, Forwarding the packets to a pool based on l2 tunnel tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 178 ++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 204 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 382 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1b90e09..a5a398c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3300,3 +3300,181 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
 }
+
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
+					enum rte_eth_l2_tunnel_type
+						l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
+				       enum rte_eth_l2_tunnel_type
+					       l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
+							   l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
+							     l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel,
+						     pool);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9b594b8..ffb4993 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 struct rte_eth_l2_tunnel {
 	enum rte_eth_l2_tunnel_type l2_tunnel_type;
 	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
 };
 
 /*
@@ -1283,6 +1284,41 @@ typedef int (*eth_l2_tunnel_disable_t)
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 /**< @internal disable a type of l2 tunnel */
 
+typedef int (*eth_l2_tunnel_insertion_enable_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal enable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_insertion_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_enable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_forwarding_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_forwarding_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel,
+					  uint32_t pool);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1471,6 +1507,22 @@ struct eth_dev_ops {
 	eth_l2_tunnel_enable_t l2_tunnel_enable;
 	/** Disable a type of l2 tunnel */
 	eth_l2_tunnel_disable_t l2_tunnel_disable;
+	/** Enable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
+	/** Disable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
+	/** Enable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
+	/** Disable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
+	/** Enable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
+	/** Disable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3971,6 +4023,158 @@ int
 rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
+ /**
+ * Enable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Disable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param pool
+ *   Destination pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH 6/8] ixgbe: support l2 tunnel operation
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (4 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 5/8] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 7/8] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel operation.
Support enabling/disabling l2 tunnel tag insertion/stripping.
Support enabling/disabling l2 tunnel packets forwarding.
Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 357 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 357 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 55ab474..35e76a2 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,10 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
 #define DEFAULT_ETAG_ETYPE                     0x893f
 #define IXGBE_ETAG_ETYPE                       0x00005084
 #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
 #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -351,6 +358,30 @@ static int ixgbe_dev_l2_tunnel_enable
 static int ixgbe_dev_l2_tunnel_disable
 	(struct rte_eth_dev *dev,
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_insertion_enable
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t pool);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -512,6 +543,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
 	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
 	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
+	.l2_tunnel_insertion_enable   = ixgbe_dev_l2_tunnel_insertion_enable,
+	.l2_tunnel_insertion_disable  = ixgbe_dev_l2_tunnel_insertion_disable,
+	.l2_tunnel_stripping_enable   = ixgbe_dev_l2_tunnel_stripping_enable,
+	.l2_tunnel_stripping_disable  = ixgbe_dev_l2_tunnel_stripping_disable,
+	.l2_tunnel_forwarding_enable  = ixgbe_dev_l2_tunnel_forwarding_enable,
+	.l2_tunnel_forwarding_disable = ixgbe_dev_l2_tunnel_forwarding_disable,
+	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6341,6 +6380,324 @@ ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel,
+		       uint32_t pool)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -1;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel,
+			       uint32_t pool)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "Don't find the matched entry in E-tag forwarding"
+		     " table.");
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	uint16_t vf;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	for (vf = 0; vf < dev->pci_dev->max_vfs; vf++) {
+		IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf), vmtir);
+
+		vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+		vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+		if (en)
+			vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+		IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
+	}
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH 7/8] app/testpmd: add CLIs for E-tag operation
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (5 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 6/8] ixgbe: support " Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-01-29  7:03 ` [PATCH 8/8] doc: add release note for E-tag Wenzhuo Lu
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 340 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d409934..df07e60 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -9885,6 +9885,340 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id, &entry);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
+						RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_stripping_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_stripping_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_forwarding_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_forwarding_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry,
+					 res->dst_pool_val);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10030,6 +10364,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
-- 
1.9.3

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

* [PATCH 8/8] doc: add release note for E-tag
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (6 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 7/8] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-01-29  7:03 ` Wenzhuo Lu
  2016-02-01 16:15   ` Mcnamara, John
  2016-01-29  7:16 ` [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Qiu, Michael
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-01-29  7:03 UTC (permalink / raw)
  To: dev

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_2_3.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst
index 99de186..16bd80b 100644
--- a/doc/guides/rel_notes/release_2_3.rst
+++ b/doc/guides/rel_notes/release_2_3.rst
@@ -4,6 +4,12 @@ DPDK Release 2.3
 New Features
 ------------
 
+* **Added support for E-tag on X550.**
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
+
 
 Resolved Issues
 ---------------
-- 
1.9.3

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (7 preceding siblings ...)
  2016-01-29  7:03 ` [PATCH 8/8] doc: add release note for E-tag Wenzhuo Lu
@ 2016-01-29  7:16 ` Qiu, Michael
  2016-02-01  1:04   ` Lu, Wenzhuo
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 95+ messages in thread
From: Qiu, Michael @ 2016-01-29  7:16 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi, Wenzhuo

Better to explain what E-tag is, so that reviewers could known it.

Thanks,
Michael

On 1/29/2016 3:05 PM, Wenzhuo Lu wrote:
> This patch set adds the support of E-tag offloading and forwarding
> on X550.
> The offloading means E-tag can be inserted and stripped by HW.
> And E-tag packets can be recognized and forwarded to specific pools
> based on GRP and E-CID_base in E-tag.
>
> Wenzhuo Lu (8):
>   ixgbe: select pool by MAC when using double VLAN
>   lib/librte_ether: support l2 tunnel config
>   ixgbe: support l2 tunnel config
>   app/testpmd: add CLIs for l2 tunnel config
>   lib/librte_ether: support new l2 tunnel operation
>   ixgbe: support l2 tunnel operation
>   app/testpmd: add CLIs for E-tag operation
>   doc: add release note for E-tag
>
>  app/test-pmd/cmdline.c               | 599 +++++++++++++++++++++++++++++++++++
>  doc/guides/rel_notes/release_2_3.rst |   6 +
>  drivers/net/ixgbe/ixgbe_ethdev.c     | 507 +++++++++++++++++++++++++++++
>  lib/librte_ether/rte_eth_ctrl.h      |   9 +
>  lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
>  lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
>  6 files changed, 1648 insertions(+)
>


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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-01-29  7:16 ` [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Qiu, Michael
@ 2016-02-01  1:04   ` Lu, Wenzhuo
  2016-02-01  1:39     ` Yuanhan Liu
  0 siblings, 1 reply; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-01  1:04 UTC (permalink / raw)
  To: Qiu, Michael, dev

Hi,

> -----Original Message-----
> From: Qiu, Michael
> Sent: Friday, January 29, 2016 3:16 PM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> Intel X550 NIC
> 
> Hi, Wenzhuo
> 
> Better to explain what E-tag is, so that reviewers could known it.
Yes, it's better. But not sure where should I add this info. In release note or just cover letter? Any suggestion? Thanks.
> 
> Thanks,
> Michael

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  1:04   ` Lu, Wenzhuo
@ 2016-02-01  1:39     ` Yuanhan Liu
  2016-02-01  1:56       ` Lu, Wenzhuo
  2016-02-01  8:31       ` Qiu, Michael
  0 siblings, 2 replies; 95+ messages in thread
From: Yuanhan Liu @ 2016-02-01  1:39 UTC (permalink / raw)
  To: Lu, Wenzhuo; +Cc: dev

On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
> Hi,
> 
> > -----Original Message-----
> > From: Qiu, Michael
> > Sent: Friday, January 29, 2016 3:16 PM
> > To: Lu, Wenzhuo; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> > Intel X550 NIC
> > 
> > Hi, Wenzhuo
> > 
> > Better to explain what E-tag is, so that reviewers could known it.
> Yes, it's better. But not sure where should I add this info. In release note or just cover letter? Any suggestion? Thanks.

It should be done in the first patch introduced E-tag, so that it will
be in the git log history. And of course, it does no harm at all to
mention (briefly) it again in cover letter, so that reviewer/maintainer
has a brief understanding of your whole patchset first.

	--yliu

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  1:39     ` Yuanhan Liu
@ 2016-02-01  1:56       ` Lu, Wenzhuo
  2016-02-01  2:06         ` Yuanhan Liu
  2016-02-01  8:31       ` Qiu, Michael
  1 sibling, 1 reply; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-01  1:56 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev

Hi Yuanhan,

> -----Original Message-----
> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> Sent: Monday, February 1, 2016 9:40 AM
> To: Lu, Wenzhuo
> Cc: Qiu, Michael; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> Intel X550 NIC
> 
> On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
> > Hi,
> >
> > > -----Original Message-----
> > > From: Qiu, Michael
> > > Sent: Friday, January 29, 2016 3:16 PM
> > > To: Lu, Wenzhuo; dev@dpdk.org
> > > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and
> > > forwarding on Intel X550 NIC
> > >
> > > Hi, Wenzhuo
> > >
> > > Better to explain what E-tag is, so that reviewers could known it.
> > Yes, it's better. But not sure where should I add this info. In release note or just
> cover letter? Any suggestion? Thanks.
> 
> It should be done in the first patch introduced E-tag, so that it will be in the git
> log history. And of course, it does no harm at all to mention (briefly) it again in
> cover letter, so that reviewer/maintainer has a brief understanding of your
> whole patchset first.
> 
> 	--yliu
Thanks for the suggestion!

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  1:56       ` Lu, Wenzhuo
@ 2016-02-01  2:06         ` Yuanhan Liu
  2016-02-01  3:00           ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: Yuanhan Liu @ 2016-02-01  2:06 UTC (permalink / raw)
  To: Lu, Wenzhuo; +Cc: dev

On Mon, Feb 01, 2016 at 01:56:32AM +0000, Lu, Wenzhuo wrote:
> Hi Yuanhan,
> 
> > -----Original Message-----
> > From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> > Sent: Monday, February 1, 2016 9:40 AM
> > To: Lu, Wenzhuo
> > Cc: Qiu, Michael; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> > Intel X550 NIC
> > 
> > On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
> > > Hi,
> > >
> > > > -----Original Message-----
> > > > From: Qiu, Michael
> > > > Sent: Friday, January 29, 2016 3:16 PM
> > > > To: Lu, Wenzhuo; dev@dpdk.org
> > > > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and
> > > > forwarding on Intel X550 NIC
> > > >
> > > > Hi, Wenzhuo
> > > >
> > > > Better to explain what E-tag is, so that reviewers could known it.
> > > Yes, it's better. But not sure where should I add this info. In release note or just
> > cover letter? Any suggestion? Thanks.
> > 
> > It should be done in the first patch introduced E-tag, so that it will be in the git
> > log history. And of course, it does no harm at all to mention (briefly) it again in
> > cover letter, so that reviewer/maintainer has a brief understanding of your
> > whole patchset first.
> > 
> > 	--yliu
> Thanks for the suggestion!

Welcome! Another side note is that, as suggested (and asked) by Thomas,
release note should not be done in a standalone patch, but instead, in
the patch that enables it. Which is to say, you should squash patch 8 to
patch 7 here.

	--yliu

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  2:06         ` Yuanhan Liu
@ 2016-02-01  3:00           ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-01  3:00 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev

Hi Yuanhan,

> -----Original Message-----
> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> Sent: Monday, February 1, 2016 10:06 AM
> To: Lu, Wenzhuo
> Cc: Qiu, Michael; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> Intel X550 NIC
> 
> On Mon, Feb 01, 2016 at 01:56:32AM +0000, Lu, Wenzhuo wrote:
> > Hi Yuanhan,
> >
> > > -----Original Message-----
> > > From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> > > Sent: Monday, February 1, 2016 9:40 AM
> > > To: Lu, Wenzhuo
> > > Cc: Qiu, Michael; dev@dpdk.org
> > > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and
> > > forwarding on Intel X550 NIC
> > >
> > > On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
> > > > Hi,
> > > >
> > > > > -----Original Message-----
> > > > > From: Qiu, Michael
> > > > > Sent: Friday, January 29, 2016 3:16 PM
> > > > > To: Lu, Wenzhuo; dev@dpdk.org
> > > > > Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and
> > > > > forwarding on Intel X550 NIC
> > > > >
> > > > > Hi, Wenzhuo
> > > > >
> > > > > Better to explain what E-tag is, so that reviewers could known it.
> > > > Yes, it's better. But not sure where should I add this info. In
> > > > release note or just
> > > cover letter? Any suggestion? Thanks.
> > >
> > > It should be done in the first patch introduced E-tag, so that it
> > > will be in the git log history. And of course, it does no harm at
> > > all to mention (briefly) it again in cover letter, so that
> > > reviewer/maintainer has a brief understanding of your whole patchset first.
> > >
> > > 	--yliu
> > Thanks for the suggestion!
> 
> Welcome! Another side note is that, as suggested (and asked) by Thomas,
> release note should not be done in a standalone patch, but instead, in the patch
> that enables it. Which is to say, you should squash patch 8 to patch 7 here.
> 
> 	--yliu
Thanks for the reminder!

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  1:39     ` Yuanhan Liu
  2016-02-01  1:56       ` Lu, Wenzhuo
@ 2016-02-01  8:31       ` Qiu, Michael
  2016-02-02  1:24         ` Lu, Wenzhuo
  1 sibling, 1 reply; 95+ messages in thread
From: Qiu, Michael @ 2016-02-01  8:31 UTC (permalink / raw)
  To: Yuanhan Liu, Lu, Wenzhuo; +Cc: dev

On 2/1/2016 9:38 AM, Yuanhan Liu wrote:
> On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: Qiu, Michael
>>> Sent: Friday, January 29, 2016 3:16 PM
>>> To: Lu, Wenzhuo; dev@dpdk.org
>>> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
>>> Intel X550 NIC
>>>
>>> Hi, Wenzhuo
>>>
>>> Better to explain what E-tag is, so that reviewers could known it.
>> Yes, it's better. But not sure where should I add this info. In release note or just cover letter? Any suggestion? Thanks.
> It should be done in the first patch introduced E-tag, so that it will
> be in the git log history. And of course, it does no harm at all to
> mention (briefly) it again in cover letter, so that reviewer/maintainer
> has a brief understanding of your whole patchset first.
>
> 	--yliu

Yes, in my view, cover letter is a good place, but as want to be in git
log history, it would be better to include in the right patch of the
feature, because most of time, the first patch is not core related to
new feature, perhaps only some prepare code.

My opinion is to explain it where it first be mentioned in the code.

But again, it OK for Yuanhan's solution, the only thing you want to do
is think you are a reviewer, and want to review you patch, what do you want.

Thanks,
Michael


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

* Re: [PATCH 8/8] doc: add release note for E-tag
  2016-01-29  7:03 ` [PATCH 8/8] doc: add release note for E-tag Wenzhuo Lu
@ 2016-02-01 16:15   ` Mcnamara, John
  0 siblings, 0 replies; 95+ messages in thread
From: Mcnamara, John @ 2016-02-01 16:15 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Friday, January 29, 2016 7:04 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 8/8] doc: add release note for E-tag
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>


Acked-by: John McNamara <john.mcnamara@intel.com>

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

* Re: [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-01  8:31       ` Qiu, Michael
@ 2016-02-02  1:24         ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-02  1:24 UTC (permalink / raw)
  To: Qiu, Michael, Yuanhan Liu; +Cc: dev

Hi Michael,

> -----Original Message-----
> From: Qiu, Michael
> Sent: Monday, February 1, 2016 4:32 PM
> To: Yuanhan Liu; Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and forwarding on
> Intel X550 NIC
> 
> On 2/1/2016 9:38 AM, Yuanhan Liu wrote:
> > On Mon, Feb 01, 2016 at 01:04:52AM +0000, Lu, Wenzhuo wrote:
> >> Hi,
> >>
> >>> -----Original Message-----
> >>> From: Qiu, Michael
> >>> Sent: Friday, January 29, 2016 3:16 PM
> >>> To: Lu, Wenzhuo; dev@dpdk.org
> >>> Subject: Re: [dpdk-dev] [PATCH 0/8] support E-tag offloading and
> >>> forwarding on Intel X550 NIC
> >>>
> >>> Hi, Wenzhuo
> >>>
> >>> Better to explain what E-tag is, so that reviewers could known it.
> >> Yes, it's better. But not sure where should I add this info. In release note or
> just cover letter? Any suggestion? Thanks.
> > It should be done in the first patch introduced E-tag, so that it will
> > be in the git log history. And of course, it does no harm at all to
> > mention (briefly) it again in cover letter, so that
> > reviewer/maintainer has a brief understanding of your whole patchset first.
> >
> > 	--yliu
> 
> Yes, in my view, cover letter is a good place, but as want to be in git log history,
> it would be better to include in the right patch of the feature, because most of
> time, the first patch is not core related to new feature, perhaps only some
> prepare code.
> 
> 
> My opinion is to explain it where it first be mentioned in the code.
I think it's good to explain it when we meet this concept at the first time. I'll do that. Thanks.

> 
> But again, it OK for Yuanhan's solution, the only thing you want to do is think
> you are a reviewer, and want to review you patch, what do you want.
> 
> Thanks,
> Michael

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

* [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (8 preceding siblings ...)
  2016-01-29  7:16 ` [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Qiu, Michael
@ 2016-02-02  6:56 ` Wenzhuo Lu
  2016-02-02  6:56   ` [PATCH v2 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (7 more replies)
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
                   ` (5 subsequent siblings)
  15 siblings, 8 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:56 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

Wenzhuo Lu (7):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel config
  ixgbe: support l2 tunnel config
  app/testpmd: add CLIs for l2 tunnel config
  lib/librte_ether: support new l2 tunnel operation
  ixgbe: support l2 tunnel operation
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c               | 599 +++++++++++++++++++++++++++++++++++
 doc/guides/rel_notes/release_2_3.rst |   6 +
 drivers/net/ixgbe/ixgbe_ethdev.c     | 507 +++++++++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h      |   9 +
 lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
 lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
 6 files changed, 1648 insertions(+)

-- 
1.9.3

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

* [PATCH v2 1/7] ixgbe: select pool by MAC when using double VLAN
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
@ 2016-02-02  6:56   ` Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:56 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4c4c6df..83df0c0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
  2016-02-02  6:56   ` [PATCH v2 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-02 12:03     ` Bruce Richardson
  2016-02-03  3:36     ` Stephen Hemminger
  2016-02-02  6:57   ` [PATCH v2 3/7] ixgbe: " Wenzhuo Lu
                     ` (5 subsequent siblings)
  7 siblings, 2 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration.
The support includes ether type modification and the tunnel support
enabling/disabling.
Ether type modification means modifying the ether type of a specific
type of tunnel. So the packet with this ether type will be parsed as
this type of tunnel.
Enabling/disabling a tunnel support means enabling/disabling the
ability of parsing the specific type of tunnel. This ability should
be enabled before we enable filtering, forwarding, offloading for
this specific type of tunnel.
Only support e-tag tunnel now.

E-tag introduction,
E-tag means external tag which is defined in IEEEE 802.1BR
specification.
E-tag is a kind of l2 tunnel. It means a tag will be inserted in the
l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h |  9 +++++
 lib/librte_ether/rte_ethdev.c   | 61 ++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h   | 84 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index ed971b4..1b90e09 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3239,3 +3239,64 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_enable)(dev, l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index bada8ad..9b594b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,14 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1269,20 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable a type of l2 tunnel */
+
+typedef int (*eth_l2_tunnel_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable a type of l2 tunnel */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1465,12 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable a type of l2 tunnel */
+	eth_l2_tunnel_enable_t l2_tunnel_enable;
+	/** Disable a type of l2 tunnel */
+	eth_l2_tunnel_disable_t l2_tunnel_disable;
 };
 
 /**
@@ -3887,6 +3915,62 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets depend on
+ * this ability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets will not
+ * work either even if they're enabled.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v2 3/7] ixgbe: support l2 tunnel config
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
  2016-02-02  6:56   ` [PATCH v2 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration.
Support modifying ether type of a type of l2 tunnel.
Support enabling and disabling the support of a type of l2 tunnel.
Only E-tag tunnel is supported now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 83df0c0..55ab474 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,10 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
+	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
 };
 
 /*
@@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v2 4/7] app/testpmd: add CLIs for l2 tunnel config
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-02-02  6:57   ` [PATCH v2 3/7] ixgbe: " Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 73298c9..d409934 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -9630,6 +9630,261 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	portid_t pid;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis)) {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_enable(pid, l2_tunnel_type);
+		}
+	} else {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_disable(pid, l2_tunnel_type);
+		}
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_enable(res->id, l2_tunnel_type);
+	else
+		rte_eth_dev_l2_tunnel_disable(res->id, l2_tunnel_type);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9771,6 +10026,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
-- 
1.9.3

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

* [PATCH v2 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-02-02  6:57   ` [PATCH v2 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 6/7] ixgbe: support " Wenzhuo Lu
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add functions to support the new l2 tunnel operation.
1, Insertion and stripping for l2 tunnel tag.
2, Forwarding the packets to a pool based on l2 tunnel tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 178 ++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 204 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 382 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1b90e09..a5a398c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3300,3 +3300,181 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
 }
+
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
+					enum rte_eth_l2_tunnel_type
+						l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
+				       enum rte_eth_l2_tunnel_type
+					       l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
+							   l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
+							     l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel,
+						     pool);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9b594b8..ffb4993 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 struct rte_eth_l2_tunnel {
 	enum rte_eth_l2_tunnel_type l2_tunnel_type;
 	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
 };
 
 /*
@@ -1283,6 +1284,41 @@ typedef int (*eth_l2_tunnel_disable_t)
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 /**< @internal disable a type of l2 tunnel */
 
+typedef int (*eth_l2_tunnel_insertion_enable_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal enable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_insertion_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_enable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_forwarding_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_forwarding_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel,
+					  uint32_t pool);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1471,6 +1507,22 @@ struct eth_dev_ops {
 	eth_l2_tunnel_enable_t l2_tunnel_enable;
 	/** Disable a type of l2 tunnel */
 	eth_l2_tunnel_disable_t l2_tunnel_disable;
+	/** Enable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
+	/** Disable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
+	/** Enable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
+	/** Disable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
+	/** Enable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
+	/** Disable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3971,6 +4023,158 @@ int
 rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
+ /**
+ * Enable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Disable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param pool
+ *   Destination pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v2 6/7] ixgbe: support l2 tunnel operation
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-02-02  6:57   ` [PATCH v2 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-02  6:57   ` [PATCH v2 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  2016-02-12 13:50   ` [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC De Lara Guarch, Pablo
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel operation.
Support enabling/disabling l2 tunnel tag insertion/stripping.
Support enabling/disabling l2 tunnel packets forwarding.
Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_2_3.rst |   6 +
 drivers/net/ixgbe/ixgbe_ethdev.c     | 357 +++++++++++++++++++++++++++++++++++
 2 files changed, 363 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst
index 99de186..16bd80b 100644
--- a/doc/guides/rel_notes/release_2_3.rst
+++ b/doc/guides/rel_notes/release_2_3.rst
@@ -4,6 +4,12 @@ DPDK Release 2.3
 New Features
 ------------
 
+* **Added support for E-tag on X550.**
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
+
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 55ab474..35e76a2 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,10 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
 #define DEFAULT_ETAG_ETYPE                     0x893f
 #define IXGBE_ETAG_ETYPE                       0x00005084
 #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
 #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -351,6 +358,30 @@ static int ixgbe_dev_l2_tunnel_enable
 static int ixgbe_dev_l2_tunnel_disable
 	(struct rte_eth_dev *dev,
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_insertion_enable
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t pool);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -512,6 +543,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
 	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
 	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
+	.l2_tunnel_insertion_enable   = ixgbe_dev_l2_tunnel_insertion_enable,
+	.l2_tunnel_insertion_disable  = ixgbe_dev_l2_tunnel_insertion_disable,
+	.l2_tunnel_stripping_enable   = ixgbe_dev_l2_tunnel_stripping_enable,
+	.l2_tunnel_stripping_disable  = ixgbe_dev_l2_tunnel_stripping_disable,
+	.l2_tunnel_forwarding_enable  = ixgbe_dev_l2_tunnel_forwarding_enable,
+	.l2_tunnel_forwarding_disable = ixgbe_dev_l2_tunnel_forwarding_disable,
+	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6341,6 +6380,324 @@ ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel,
+		       uint32_t pool)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -1;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel,
+			       uint32_t pool)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "Don't find the matched entry in E-tag forwarding"
+		     " table.");
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	uint16_t vf;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	for (vf = 0; vf < dev->pci_dev->max_vfs; vf++) {
+		IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf), vmtir);
+
+		vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
+		vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+		if (en)
+			vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+		IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
+	}
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v2 7/7] app/testpmd: add CLIs for E-tag operation
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                     ` (5 preceding siblings ...)
  2016-02-02  6:57   ` [PATCH v2 6/7] ixgbe: support " Wenzhuo Lu
@ 2016-02-02  6:57   ` Wenzhuo Lu
  2016-02-12 13:50   ` [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC De Lara Guarch, Pablo
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-02  6:57 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 340 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index d409934..df07e60 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -9885,6 +9885,340 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id, &entry);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
+						RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_stripping_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_stripping_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_forwarding_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_forwarding_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry,
+					 res->dst_pool_val);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10030,6 +10364,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
-- 
1.9.3

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

* Re: [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-02  6:57   ` [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-02-02 12:03     ` Bruce Richardson
  2016-02-03  1:05       ` Lu, Wenzhuo
  2016-02-03  3:36     ` Stephen Hemminger
  1 sibling, 1 reply; 95+ messages in thread
From: Bruce Richardson @ 2016-02-02 12:03 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev

On Tue, Feb 02, 2016 at 02:57:00PM +0800, Wenzhuo Lu wrote:
> Add functions to support l2 tunnel configuration.
> The support includes ether type modification and the tunnel support
> enabling/disabling.
> Ether type modification means modifying the ether type of a specific
> type of tunnel. So the packet with this ether type will be parsed as
> this type of tunnel.
> Enabling/disabling a tunnel support means enabling/disabling the
> ability of parsing the specific type of tunnel. This ability should
> be enabled before we enable filtering, forwarding, offloading for
> this specific type of tunnel.
> Only support e-tag tunnel now.
> 
> E-tag introduction,
> E-tag means external tag which is defined in IEEEE 802.1BR
> specification.
> E-tag is a kind of l2 tunnel. It means a tag will be inserted in the
> l2 header. Like below,
>    |31            24|23           16|15         8|7           0|
>   0|                   Destination MAC address                 |
>   4|     Dest MAC address(cont.)    |     Src MAC address      |
>   8|                  Source MAC address(cont.)                |
>  12| E-tag Etherenet type (0x893f)  |      E-tag header        |
>  16|                    E-tag header(cont.)                    |
>  20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
>  24|         Original type          |         ......           |
> ...|                              ......                       |
> The E-tag format is like below,
>    |0                    15|16   18|19 |20                   31|
>    |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |
> 
>    |32  33|34 35|36      47|48         55    |56             63|
>    |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |
> 
> The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
> and are effectively reserved.
> 
> The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
> replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
> It specifies the operation of Bridge Port Extenders, including
> management, protocols, and algorithms. Bridge Port Extenders
> operate in support of the MAC Service by Extended Bridges.
> The E-tag is added to l2 header to identify the VM channel and
> the virtual port.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>

Your introduction to e-tag needs to be in patch 1 rather than 2, and in the
cover letter, since both those earlier mails reference it.
Furthermore, it would be better if you could link to a web description of the
e-tag rather than try and explain it all in a commit message. Diagrams also work
better on a web-page.

/Bruce

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

* Re: [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-02 12:03     ` Bruce Richardson
@ 2016-02-03  1:05       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-03  1:05 UTC (permalink / raw)
  To: Richardson, Bruce; +Cc: dev

Hi Bruce,

> -----Original Message-----
> From: Richardson, Bruce
> Sent: Tuesday, February 2, 2016 8:03 PM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
> 
> On Tue, Feb 02, 2016 at 02:57:00PM +0800, Wenzhuo Lu wrote:
> > Add functions to support l2 tunnel configuration.
> > The support includes ether type modification and the tunnel support
> > enabling/disabling.
> > Ether type modification means modifying the ether type of a specific
> > type of tunnel. So the packet with this ether type will be parsed as
> > this type of tunnel.
> > Enabling/disabling a tunnel support means enabling/disabling the
> > ability of parsing the specific type of tunnel. This ability should be
> > enabled before we enable filtering, forwarding, offloading for this
> > specific type of tunnel.
> > Only support e-tag tunnel now.
> >
> > E-tag introduction,
> > E-tag means external tag which is defined in IEEEE 802.1BR
> > specification.
> > E-tag is a kind of l2 tunnel. It means a tag will be inserted in the
> > l2 header. Like below,
> >    |31            24|23           16|15         8|7           0|
> >   0|                   Destination MAC address                 |
> >   4|     Dest MAC address(cont.)    |     Src MAC address      |
> >   8|                  Source MAC address(cont.)                |
> >  12| E-tag Etherenet type (0x893f)  |      E-tag header        |
> >  16|                    E-tag header(cont.)                    |
> >  20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
> >  24|         Original type          |         ......           |
> > ...|                              ......                       |
> > The E-tag format is like below,
> >    |0                    15|16   18|19 |20                   31|
> >    |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |
> >
> >    |32  33|34 35|36      47|48         55    |56             63|
> >    |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |
> >
> > The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints and
> > are effectively reserved.
> >
> > The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
> > replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
> > It specifies the operation of Bridge Port Extenders, including
> > management, protocols, and algorithms. Bridge Port Extenders operate
> > in support of the MAC Service by Extended Bridges.
> > The E-tag is added to l2 header to identify the VM channel and the
> > virtual port.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> 
> Your introduction to e-tag needs to be in patch 1 rather than 2, and in the cover
> letter, since both those earlier mails reference it.
> Furthermore, it would be better if you could link to a web description of the e-
> tag rather than try and explain it all in a commit message. Diagrams also work
> better on a web-page.
O, my bad. I thought the patch 1 doesn't have something to do with E-tag directly.
But I do mention E-tag in the patch V1.
Thanks for the comments. I'll create  a V3.

> 
> /Bruce

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

* Re: [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-02  6:57   ` [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
  2016-02-02 12:03     ` Bruce Richardson
@ 2016-02-03  3:36     ` Stephen Hemminger
  2016-02-03  8:08       ` Lu, Wenzhuo
  1 sibling, 1 reply; 95+ messages in thread
From: Stephen Hemminger @ 2016-02-03  3:36 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev

On Tue,  2 Feb 2016 14:57:00 +0800
Wenzhuo Lu <wenzhuo.lu@intel.com> wrote:

> +/**
> + * l2 tunnel configuration.
> + */
> +struct rte_eth_l2_tunnel {
> +	enum rte_eth_l2_tunnel_type l2_tunnel_type;
> +	uint16_t ether_type;
> +};

Building an API with an indirect (structure) parameter with only two
elements seems like overkill. If you are building it to support future
features, that won't work because it will break ABI.

Why not just?

int
rte_eth_dev_etag_enable(uint8_t port_id, uint16_t ether_type)

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

* Re: [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-03  3:36     ` Stephen Hemminger
@ 2016-02-03  8:08       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-03  8:08 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

Hi Stephen,

> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Wednesday, February 3, 2016 11:36 AM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config
> 
> On Tue,  2 Feb 2016 14:57:00 +0800
> Wenzhuo Lu <wenzhuo.lu@intel.com> wrote:
> 
> > +/**
> > + * l2 tunnel configuration.
> > + */
> > +struct rte_eth_l2_tunnel {
> > +	enum rte_eth_l2_tunnel_type l2_tunnel_type;
> > +	uint16_t ether_type;
> > +};
> 
> Building an API with an indirect (structure) parameter with only two elements
> seems like overkill. If you are building it to support future features, that won't
> work because it will break ABI.
> 
> Why not just?
> 
> int
> rte_eth_dev_etag_enable(uint8_t port_id, uint16_t ether_type)
I'm trying to make the rte ops can support future features, because there're some similar technology 802.1Qbg, 802.1Qbh, 802.1BR, VN-tag. 
And after applying all the patches in this patch set, the  struct rte_eth_l2_tunnel will be like this,
struct rte_eth_l2_tunnel {
        enum rte_eth_l2_tunnel_type l2_tunnel_type;
        uint16_t ether_type;
       uint32_t tunnel_id; /* port tag id for e-tag */
 };
If we want to support a new type of tunnel which can be described by ether type and tunnel id, we need not to extend this structure. We
only need to add new value for l2_tunnel_type. I think it's not an ABI change.
And I think using a l2 tunnel to cover all these tunnels can make interface simple :)

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

* Re: [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
                     ` (6 preceding siblings ...)
  2016-02-02  6:57   ` [PATCH v2 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-02-12 13:50   ` De Lara Guarch, Pablo
  2016-02-15  1:21     ` Lu, Wenzhuo
  7 siblings, 1 reply; 95+ messages in thread
From: De Lara Guarch, Pablo @ 2016-02-12 13:50 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Tuesday, February 02, 2016 6:57 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and forwarding
> on Intel X550 NIC
> 
> This patch set adds the support of E-tag offloading and forwarding
> on X550.
> The offloading means E-tag can be inserted and stripped by HW.
> And E-tag packets can be recognized and forwarded to specific pools
> based on GRP and E-CID_base in E-tag.
> 
> Wenzhuo Lu (7):
>   ixgbe: select pool by MAC when using double VLAN
>   lib/librte_ether: support l2 tunnel config
>   ixgbe: support l2 tunnel config
>   app/testpmd: add CLIs for l2 tunnel config
>   lib/librte_ether: support new l2 tunnel operation
>   ixgbe: support l2 tunnel operation
>   app/testpmd: add CLIs for E-tag operation
> 
>  app/test-pmd/cmdline.c               | 599
> +++++++++++++++++++++++++++++++++++
>  doc/guides/rel_notes/release_2_3.rst |   6 +
>  drivers/net/ixgbe/ixgbe_ethdev.c     | 507
> +++++++++++++++++++++++++++++
>  lib/librte_ether/rte_eth_ctrl.h      |   9 +
>  lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
>  lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
>  6 files changed, 1648 insertions(+)
> 
> --
> 1.9.3

Could you add the new commands in testpmd documentation?
(and rebase your patchset, to include the new release_16_04.rst file)

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

* Re: [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-12 13:50   ` [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC De Lara Guarch, Pablo
@ 2016-02-15  1:21     ` Lu, Wenzhuo
  2016-02-15  9:39       ` De Lara Guarch, Pablo
  0 siblings, 1 reply; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-02-15  1:21 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev

Hi Pablo,

> -----Original Message-----
> From: De Lara Guarch, Pablo
> Sent: Friday, February 12, 2016 9:50 PM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and forwarding
> on Intel X550 NIC
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > Sent: Tuesday, February 02, 2016 6:57 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and
> > forwarding on Intel X550 NIC
> >
> > This patch set adds the support of E-tag offloading and forwarding on
> > X550.
> > The offloading means E-tag can be inserted and stripped by HW.
> > And E-tag packets can be recognized and forwarded to specific pools
> > based on GRP and E-CID_base in E-tag.
> >
> > Wenzhuo Lu (7):
> >   ixgbe: select pool by MAC when using double VLAN
> >   lib/librte_ether: support l2 tunnel config
> >   ixgbe: support l2 tunnel config
> >   app/testpmd: add CLIs for l2 tunnel config
> >   lib/librte_ether: support new l2 tunnel operation
> >   ixgbe: support l2 tunnel operation
> >   app/testpmd: add CLIs for E-tag operation
> >
> >  app/test-pmd/cmdline.c               | 599
> > +++++++++++++++++++++++++++++++++++
> >  doc/guides/rel_notes/release_2_3.rst |   6 +
> >  drivers/net/ixgbe/ixgbe_ethdev.c     | 507
> > +++++++++++++++++++++++++++++
> >  lib/librte_ether/rte_eth_ctrl.h      |   9 +
> >  lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
> >  lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
> >  6 files changed, 1648 insertions(+)
> >
> > --
> > 1.9.3
> 
> Could you add the new commands in testpmd documentation?
Thanks for the reminder. Just to confirm that the testpmd documentation you mentioned is doc/guides/testpmd_app_ug/testpmd_funcs.rst, right?

> (and rebase your patchset, to include the new release_16_04.rst file)

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

* Re: [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-15  1:21     ` Lu, Wenzhuo
@ 2016-02-15  9:39       ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 95+ messages in thread
From: De Lara Guarch, Pablo @ 2016-02-15  9:39 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Monday, February 15, 2016 1:21 AM
> To: De Lara Guarch, Pablo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and
> forwarding on Intel X550 NIC
> 
> Hi Pablo,
> 
> > -----Original Message-----
> > From: De Lara Guarch, Pablo
> > Sent: Friday, February 12, 2016 9:50 PM
> > To: Lu, Wenzhuo; dev@dpdk.org
> > Subject: RE: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and
> forwarding
> > on Intel X550 NIC
> >
> > Hi Wenzhuo,
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > > Sent: Tuesday, February 02, 2016 6:57 AM
> > > To: dev@dpdk.org
> > > Subject: [dpdk-dev] [PATCH v2 0/7] support E-tag offloading and
> > > forwarding on Intel X550 NIC
> > >
> > > This patch set adds the support of E-tag offloading and forwarding on
> > > X550.
> > > The offloading means E-tag can be inserted and stripped by HW.
> > > And E-tag packets can be recognized and forwarded to specific pools
> > > based on GRP and E-CID_base in E-tag.
> > >
> > > Wenzhuo Lu (7):
> > >   ixgbe: select pool by MAC when using double VLAN
> > >   lib/librte_ether: support l2 tunnel config
> > >   ixgbe: support l2 tunnel config
> > >   app/testpmd: add CLIs for l2 tunnel config
> > >   lib/librte_ether: support new l2 tunnel operation
> > >   ixgbe: support l2 tunnel operation
> > >   app/testpmd: add CLIs for E-tag operation
> > >
> > >  app/test-pmd/cmdline.c               | 599
> > > +++++++++++++++++++++++++++++++++++
> > >  doc/guides/rel_notes/release_2_3.rst |   6 +
> > >  drivers/net/ixgbe/ixgbe_ethdev.c     | 507
> > > +++++++++++++++++++++++++++++
> > >  lib/librte_ether/rte_eth_ctrl.h      |   9 +
> > >  lib/librte_ether/rte_ethdev.c        | 239 ++++++++++++++
> > >  lib/librte_ether/rte_ethdev.h        | 288 +++++++++++++++++
> > >  6 files changed, 1648 insertions(+)
> > >
> > > --
> > > 1.9.3
> >
> > Could you add the new commands in testpmd documentation?
> Thanks for the reminder. Just to confirm that the testpmd documentation
> you mentioned is doc/guides/testpmd_app_ug/testpmd_funcs.rst, right?
> 
That's correct.
Thanks!
> > (and rebase your patchset, to include the new release_16_04.rst file)

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

* [PATCH v3 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (9 preceding siblings ...)
  2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
@ 2016-02-16  8:20 ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (6 more replies)
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (4 subsequent siblings)
  15 siblings, 7 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

V2:
* Add the introduction for E-tag.

V3:
* Add the hlep info for the new CLIs.
* Update the doc for testpmd.
* Update the E-tag insertion setting. Should insert different tunnel
  id for every VF, not a common one for all.

Wenzhuo Lu (7):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel config
  ixgbe: support l2 tunnel config
  app/testpmd: add CLIs for l2 tunnel config
  lib/librte_ether: support new l2 tunnel operation
  ixgbe: support l2 tunnel operation
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 647 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_2_3.rst        |   6 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 518 ++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |   9 +
 lib/librte_ether/rte_ethdev.c               | 244 +++++++++++
 lib/librte_ether/rte_ethdev.h               | 298 +++++++++++++
 7 files changed, 1758 insertions(+), 1 deletion(-)

-- 
1.9.3

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

* [PATCH v3 1/7] ixgbe: select pool by MAC when using double VLAN
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4c4c6df..83df0c0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v3 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 3/7] ixgbe: " Wenzhuo Lu
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration.
The support includes ether type modification and the tunnel support
enabling/disabling.
Ether type modification means modifying the ether type of a specific
type of tunnel. So the packet with this ether type will be parsed as
this type of tunnel.
Enabling/disabling a tunnel support means enabling/disabling the
ability of parsing the specific type of tunnel. This ability should
be enabled before we enable filtering, forwarding, offloading for
this specific type of tunnel.
Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h |  9 +++++
 lib/librte_ether/rte_ethdev.c   | 61 ++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h   | 84 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index ed971b4..1b90e09 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3239,3 +3239,64 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_enable)(dev, l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index bada8ad..9b594b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,14 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1269,20 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable a type of l2 tunnel */
+
+typedef int (*eth_l2_tunnel_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable a type of l2 tunnel */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1465,12 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable a type of l2 tunnel */
+	eth_l2_tunnel_enable_t l2_tunnel_enable;
+	/** Disable a type of l2 tunnel */
+	eth_l2_tunnel_disable_t l2_tunnel_disable;
 };
 
 /**
@@ -3887,6 +3915,62 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets depend on
+ * this ability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets will not
+ * work either even if they're enabled.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v3 3/7] ixgbe: support l2 tunnel config
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration.
Support modifying ether type of a type of l2 tunnel.
Support enabling and disabling the support of a type of l2 tunnel.
Only E-tag tunnel is supported now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 83df0c0..55ab474 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,10 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
+	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
 };
 
 /*
@@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v3 4/7] app/testpmd: add CLIs for l2 tunnel config
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-02-16  8:20   ` [PATCH v3 3/7] ixgbe: " Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 269 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 73298c9..718fe93 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -570,7 +570,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9630,6 +9638,261 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	portid_t pid;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis)) {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_enable(pid, l2_tunnel_type);
+		}
+	} else {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_disable(pid, l2_tunnel_type);
+		}
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_enable(res->id, l2_tunnel_type);
+	else
+		rte_eth_dev_l2_tunnel_disable(res->id, l2_tunnel_type);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9771,6 +10034,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v3 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-02-16  8:20   ` [PATCH v3 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 6/7] ixgbe: support " Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add functions to support the new l2 tunnel operation.
1, Insertion and stripping for l2 tunnel tag.
2, Forwarding the packets to a pool based on l2 tunnel tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 183 ++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 214 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 397 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 1b90e09..4ab3fd3 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3300,3 +3300,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
 }
+
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
+							   l2_tunnel,
+							   vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
+					enum rte_eth_l2_tunnel_type
+						l2_tunnel_type,
+					uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
+							    l2_tunnel_type,
+							    vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
+				       enum rte_eth_l2_tunnel_type
+					       l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
+							   l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
+							     l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel,
+						     pool);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9b594b8..70fe632 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 struct rte_eth_l2_tunnel {
 	enum rte_eth_l2_tunnel_type l2_tunnel_type;
 	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
 };
 
 /*
@@ -1283,6 +1284,45 @@ typedef int (*eth_l2_tunnel_disable_t)
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 /**< @internal disable a type of l2 tunnel */
 
+typedef int (*eth_l2_tunnel_insertion_enable_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+/**< @internal enable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_insertion_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+/**< @internal disable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_enable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_forwarding_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_forwarding_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel,
+					  uint32_t pool);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1471,6 +1511,22 @@ struct eth_dev_ops {
 	eth_l2_tunnel_enable_t l2_tunnel_enable;
 	/** Disable a type of l2 tunnel */
 	eth_l2_tunnel_disable_t l2_tunnel_disable;
+	/** Enable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
+	/** Disable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
+	/** Enable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
+	/** Disable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
+	/** Enable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
+	/** Disable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3971,6 +4027,164 @@ int
 rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
+ /**
+ * Enable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id);
+
+ /**
+ * Disable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+
+ /**
+ * Enable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param pool
+ *   Destination pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v3 6/7] ixgbe: support l2 tunnel operation
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-02-16  8:20   ` [PATCH v3 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  2016-02-16  8:20   ` [PATCH v3 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel operation.
Support enabling/disabling l2 tunnel tag insertion/stripping.
Support enabling/disabling l2 tunnel packets forwarding.
Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_2_3.rst |   6 +
 drivers/net/ixgbe/ixgbe_ethdev.c     | 368 +++++++++++++++++++++++++++++++++++
 2 files changed, 374 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst
index 99de186..16bd80b 100644
--- a/doc/guides/rel_notes/release_2_3.rst
+++ b/doc/guides/rel_notes/release_2_3.rst
@@ -4,6 +4,12 @@ DPDK Release 2.3
 New Features
 ------------
 
+* **Added support for E-tag on X550.**
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
+
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 55ab474..6533d96 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,10 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
 #define DEFAULT_ETAG_ETYPE                     0x893f
 #define IXGBE_ETAG_ETYPE                       0x00005084
 #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
 #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -351,6 +358,33 @@ static int ixgbe_dev_l2_tunnel_enable
 static int ixgbe_dev_l2_tunnel_disable
 	(struct rte_eth_dev *dev,
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_insertion_enable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t pool);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -512,6 +546,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
 	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
 	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
+	.l2_tunnel_insertion_enable   = ixgbe_dev_l2_tunnel_insertion_enable,
+	.l2_tunnel_insertion_disable  = ixgbe_dev_l2_tunnel_insertion_disable,
+	.l2_tunnel_stripping_enable   = ixgbe_dev_l2_tunnel_stripping_enable,
+	.l2_tunnel_stripping_disable  = ixgbe_dev_l2_tunnel_stripping_disable,
+	.l2_tunnel_forwarding_enable  = ixgbe_dev_l2_tunnel_forwarding_enable,
+	.l2_tunnel_forwarding_disable = ixgbe_dev_l2_tunnel_forwarding_disable,
+	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6341,6 +6383,332 @@ ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel,
+		       uint32_t pool)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -1;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel,
+			       uint32_t pool)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "Don't find the matched entry in E-tag forwarding"
+		     " table.");
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     uint16_t vf_id,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should not be equal or larger than %u",
+			    vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel,
+				     uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, vf_id, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, vf_id, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v3 7/7] app/testpmd: add CLIs for E-tag operation
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
                     ` (5 preceding siblings ...)
  2016-02-16  8:20   ` [PATCH v3 6/7] ixgbe: support " Wenzhuo Lu
@ 2016-02-16  8:20   ` Wenzhuo Lu
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-16  8:20 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 378 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 404 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 718fe93..294f6d0 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -500,6 +500,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9893,6 +9914,357 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id,
+					       &entry,
+					       res->vf_id);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
+						RTE_L2_TUNNEL_TYPE_E_TAG,
+						res->vf_id);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_stripping_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_stripping_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_forwarding_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_forwarding_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry,
+					 res->dst_pool_val);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10038,6 +10410,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (10 preceding siblings ...)
  2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
@ 2016-02-18  2:46 ` Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (7 more replies)
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                   ` (3 subsequent siblings)
  15 siblings, 8 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

V2:
* Add the introduction for E-tag.

V3:
* Add the hlep info for the new CLIs.
* Update the doc for testpmd.
* Update the E-tag insertion setting. Should insert different tunnel
  id for every VF, not a common one for all.

V4:
* Fix strippig is not working issue.
* Update the filter adding function. Make sure there's only one filter
  entry for one tunnel entry.
* Update the release note to add some info about how to use this feature.

Wenzhuo Lu (7):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel config
  ixgbe: support l2 tunnel config
  app/testpmd: add CLIs for l2 tunnel config
  lib/librte_ether: support new l2 tunnel operation
  ixgbe: support l2 tunnel operation
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 647 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_16_04.rst      |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 521 ++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |   9 +
 lib/librte_ether/rte_ethdev.c               | 244 +++++++++++
 lib/librte_ether/rte_ethdev.h               | 298 +++++++++++++
 7 files changed, 1776 insertions(+), 1 deletion(-)

-- 
1.9.3

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

* [PATCH v4 1/7] ixgbe: select pool by MAC when using double VLAN
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3e6fe86..b99e48e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v4 2/7] lib/librte_ether: support l2 tunnel config
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 3/7] ixgbe: " Wenzhuo Lu
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration.
The support includes ether type modification and the tunnel support
enabling/disabling.
Ether type modification means modifying the ether type of a specific
type of tunnel. So the packet with this ether type will be parsed as
this type of tunnel.
Enabling/disabling a tunnel support means enabling/disabling the
ability of parsing the specific type of tunnel. This ability should
be enabled before we enable filtering, forwarding, offloading for
this specific type of tunnel.
Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h |  9 +++++
 lib/librte_ether/rte_ethdev.c   | 61 ++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h   | 84 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 756b234..c5c12cb 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3237,3 +3237,64 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_enable)(dev, l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16da821..709485a 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,14 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1269,20 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable a type of l2 tunnel */
+
+typedef int (*eth_l2_tunnel_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable a type of l2 tunnel */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1465,12 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable a type of l2 tunnel */
+	eth_l2_tunnel_enable_t l2_tunnel_enable;
+	/** Disable a type of l2 tunnel */
+	eth_l2_tunnel_disable_t l2_tunnel_disable;
 };
 
 /**
@@ -3880,6 +3908,62 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets depend on
+ * this ability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets will not
+ * work either even if they're enabled.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v4 3/7] ixgbe: support l2 tunnel config
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-03-04  1:47     ` He, Shaopeng
  2016-02-18  2:46   ` [PATCH v4 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration.
Support modifying ether type of a type of l2 tunnel.
Support enabling and disabling the support of a type of l2 tunnel.
Only E-tag tunnel is supported now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b99e48e..b15a4b6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,10 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
+	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
 };
 
 /*
@@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v4 4/7] app/testpmd: add CLIs for l2 tunnel config
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-02-18  2:46   ` [PATCH v4 3/7] ixgbe: " Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-02-18  2:46   ` [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 269 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..24a3169 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -572,7 +572,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9632,6 +9640,261 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	portid_t pid;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis)) {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_enable(pid, l2_tunnel_type);
+		}
+	} else {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_disable(pid, l2_tunnel_type);
+		}
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_enable(res->id, l2_tunnel_type);
+	else
+		rte_eth_dev_l2_tunnel_disable(res->id, l2_tunnel_type);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9773,6 +10036,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-02-18  2:46   ` [PATCH v4 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-03-04  1:47     ` He, Shaopeng
  2016-02-18  2:46   ` [PATCH v4 6/7] ixgbe: support " Wenzhuo Lu
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add functions to support the new l2 tunnel operation.
1, Insertion and stripping for l2 tunnel tag.
2, Forwarding the packets to a pool based on l2 tunnel tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 183 ++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 214 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 397 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index c5c12cb..6bc19d4 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
 }
+
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
+							   l2_tunnel,
+							   vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
+					enum rte_eth_l2_tunnel_type
+						l2_tunnel_type,
+					uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
+							    l2_tunnel_type,
+							    vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
+				       enum rte_eth_l2_tunnel_type
+					       l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
+							   l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
+							     l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel,
+						     pool);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 709485a..d482f8c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 struct rte_eth_l2_tunnel {
 	enum rte_eth_l2_tunnel_type l2_tunnel_type;
 	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
 };
 
 /*
@@ -1283,6 +1284,45 @@ typedef int (*eth_l2_tunnel_disable_t)
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 /**< @internal disable a type of l2 tunnel */
 
+typedef int (*eth_l2_tunnel_insertion_enable_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+/**< @internal enable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_insertion_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+/**< @internal disable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_enable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_forwarding_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_forwarding_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel,
+					  uint32_t pool);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1471,6 +1511,22 @@ struct eth_dev_ops {
 	eth_l2_tunnel_enable_t l2_tunnel_enable;
 	/** Disable a type of l2 tunnel */
 	eth_l2_tunnel_disable_t l2_tunnel_disable;
+	/** Enable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
+	/** Disable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
+	/** Enable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
+	/** Disable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
+	/** Enable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
+	/** Disable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3964,6 +4020,164 @@ int
 rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
+ /**
+ * Enable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id);
+
+ /**
+ * Disable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+
+ /**
+ * Enable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param pool
+ *   Destination pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v4 6/7] ixgbe: support l2 tunnel operation
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-02-18  2:46   ` [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-03-04  1:46     ` He, Shaopeng
  2016-02-18  2:46   ` [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  2016-03-04  9:23   ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Liu, Yong
  7 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel operation.
Support enabling/disabling l2 tunnel tag insertion/stripping.
Support enabling/disabling l2 tunnel packets forwarding.
Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 371 +++++++++++++++++++++++++++++++++
 2 files changed, 392 insertions(+)

diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst
index eb1b3b2..994da33 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -44,6 +44,27 @@ This section should contain new features added in this release. Sample format:
   Add the offload and negotiation of checksum and TSO between vhost-user and
   vanilla Linux virtio guest.
 
+* **Added support for E-tag on X550.**
+
+  E-tag is defined in 802.1br. Please reference
+  http://www.ieee802.org/1/pages/802.1br.html.
+
+  This feature is for VF, but please aware all the setting is on PF. It means
+  the CLIs should be used on PF, but some of their effect will be shown on VF.
+  The forwarding of E-tag packets based on GRP and E-CID_base will have effect
+  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
+  But normally we'd like to forward the packets to the pools/queues belonging
+  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
+  VF receives E-tag packets, it should strip the E-tag. When VF transmits
+  packets, it should insert the E-tag. Both can be offloaded.
+
+  When we want to use this E-tag support feature, the forwarding should be
+  enabled to forward the packets received by PF to indicated VFs. And insertion
+  and stripping should be enabled for VFs to offload the effort to HW.
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b15a4b6..aa00842 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,10 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
 #define DEFAULT_ETAG_ETYPE                     0x893f
 #define IXGBE_ETAG_ETYPE                       0x00005084
 #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
 #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -351,6 +358,33 @@ static int ixgbe_dev_l2_tunnel_enable
 static int ixgbe_dev_l2_tunnel_disable
 	(struct rte_eth_dev *dev,
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_insertion_enable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t pool);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -512,6 +546,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
 	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
 	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
+	.l2_tunnel_insertion_enable   = ixgbe_dev_l2_tunnel_insertion_enable,
+	.l2_tunnel_insertion_disable  = ixgbe_dev_l2_tunnel_insertion_disable,
+	.l2_tunnel_stripping_enable   = ixgbe_dev_l2_tunnel_stripping_enable,
+	.l2_tunnel_stripping_disable  = ixgbe_dev_l2_tunnel_stripping_disable,
+	.l2_tunnel_forwarding_enable  = ixgbe_dev_l2_tunnel_forwarding_enable,
+	.l2_tunnel_forwarding_disable = ixgbe_dev_l2_tunnel_forwarding_disable,
+	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6341,6 +6383,335 @@ ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel,
+		       uint32_t pool)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	/* One entry for one tunnel. Try to remove potential existing entry. */
+	ixgbe_e_tag_filter_del(dev, l2_tunnel);
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -1;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel,
+			       uint32_t pool)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     uint16_t vf_id,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should be less than %u",
+			    vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel,
+				     uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, vf_id, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, vf_id, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	qde &= ~IXGBE_QDE_READ;
+	qde |= IXGBE_QDE_WRITE;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                     ` (5 preceding siblings ...)
  2016-02-18  2:46   ` [PATCH v4 6/7] ixgbe: support " Wenzhuo Lu
@ 2016-02-18  2:46   ` Wenzhuo Lu
  2016-03-04  1:46     ` He, Shaopeng
  2016-03-04  9:23   ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Liu, Yong
  7 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-02-18  2:46 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 378 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 404 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 24a3169..02868f3 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9895,6 +9916,357 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id,
+					       &entry,
+					       res->vf_id);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
+						RTE_L2_TUNNEL_TYPE_E_TAG,
+						res->vf_id);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_stripping_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_stripping_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_forwarding_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_forwarding_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry,
+					 res->dst_pool_val);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10040,6 +10412,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* Re: [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation
  2016-02-18  2:46   ` [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-03-04  1:46     ` He, Shaopeng
  2016-03-04  3:11       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: He, Shaopeng @ 2016-03-04  1:46 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Thursday, February 18, 2016 10:46 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4 7/7] app/testpmd: add CLIs for E-tag
> operation
> 
> Add the CLIs to support the E-tag operation.
> 1, Offloading of E-tag insertion and stripping.
> 2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  app/test-pmd/cmdline.c                      | 378
> ++++++++++++++++++++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
>  2 files changed, 404 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 24a3169..02868f3 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void
> *parsed_result,
>  			"set link-down port (port_id)\n"
>  			"	Set link down for a port.\n\n"
> 
> +			"E-tag set insertion on port-tag-id (value)"
> +			" port (port_id) vf (vf_id)\n"
> +			"    Enable E-tag insertion for a VF on a port\n\n"
> +
> +			"E-tag set insertion off port (port_id) vf (vf_id)\n"
> +			"    Disable E-tag insertion for a VF on a port\n\n"
> +
> +			"E-tag set stripping (on|off) port (port_id)\n"
> +			"    Enable/disable E-tag stripping on a port\n\n"
> +
> +			"E-tag set forwarding (on|off) port (port_id)\n"
> +			"    Enable/disable E-tag based forwarding"
> +			" on a port\n\n"
> +
> +			"E-tag set filter add e-tag-id (value) dst-pool"
> +			" (pool_id) port (port_id)\n"
> +			"    Add an E-tag forwarding filter on a port\n\n"
> +
> +			"E-tag set filter del e-tag-id (value) port (port_id)\n"
> +			"    Delete an E-tag forwarding filter on a port\n\n"
> +
>  			, list_pkt_forwarding_modes()
>  		);
>  	}
> @@ -9895,6 +9916,357 @@ cmdline_parse_inst_t
> cmd_config_l2_tunnel_en_dis_specific = {
>  	},
>  };
> 
> +/* E-tag configuration */
> +
> +/* Common result structure for all E-tag configuration */
> +struct cmd_config_e_tag_result {
> +	cmdline_fixed_string_t e_tag;
> +	cmdline_fixed_string_t set;
> +	cmdline_fixed_string_t insertion;
> +	cmdline_fixed_string_t stripping;
> +	cmdline_fixed_string_t forwarding;
> +	cmdline_fixed_string_t filter;
> +	cmdline_fixed_string_t add;
> +	cmdline_fixed_string_t del;
> +	cmdline_fixed_string_t on;
> +	cmdline_fixed_string_t off;
> +	cmdline_fixed_string_t on_off;
> +	cmdline_fixed_string_t port_tag_id;
> +	uint32_t port_tag_id_val;
> +	cmdline_fixed_string_t e_tag_id;
> +	uint16_t e_tag_id_val;
> +	cmdline_fixed_string_t dst_pool;
> +	uint8_t dst_pool_val;
> +	cmdline_fixed_string_t port;
> +	uint8_t port_id;
> +	cmdline_fixed_string_t vf;
> +	uint8_t vf_id;
> +};
> +
> +/* Common CLI fields for all E-tag configuration */
> +cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 e_tag, "E-tag");
> +cmdline_parse_token_string_t cmd_config_e_tag_set =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 set, "set");
> +cmdline_parse_token_string_t cmd_config_e_tag_insertion =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 insertion, "insertion");
> +cmdline_parse_token_string_t cmd_config_e_tag_stripping =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 stripping, "stripping");
> +cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 forwarding, "forwarding");
> +cmdline_parse_token_string_t cmd_config_e_tag_filter =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 filter, "filter");
> +cmdline_parse_token_string_t cmd_config_e_tag_add =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 add, "add");
> +cmdline_parse_token_string_t cmd_config_e_tag_del =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 del, "del");
> +cmdline_parse_token_string_t cmd_config_e_tag_on =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 on, "on");
> +cmdline_parse_token_string_t cmd_config_e_tag_off =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 off, "off");
> +cmdline_parse_token_string_t cmd_config_e_tag_on_off =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 on_off, "on#off");
> +cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 port_tag_id, "port-tag-id");
> +cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
> +	TOKEN_NUM_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 port_tag_id_val, UINT32);
> +cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 e_tag_id, "e-tag-id");
> +cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
> +	TOKEN_NUM_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 e_tag_id_val, UINT16);
> +cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 dst_pool, "dst-pool");
> +cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
> +	TOKEN_NUM_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 dst_pool_val, UINT8);
> +cmdline_parse_token_string_t cmd_config_e_tag_port =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 port, "port");
> +cmdline_parse_token_num_t cmd_config_e_tag_port_id =
> +	TOKEN_NUM_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 port_id, UINT8);
> +cmdline_parse_token_string_t cmd_config_e_tag_vf =
> +	TOKEN_STRING_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 vf, "vf");
> +cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
> +	TOKEN_NUM_INITIALIZER
> +		(struct cmd_config_e_tag_result,
> +		 vf_id, UINT8);
> +
> +/* E-tag insertion configuration */
> +static void
> +cmd_config_e_tag_insertion_en_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +	struct rte_eth_l2_tunnel entry;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> +	entry.tunnel_id = res->port_tag_id_val;
> +	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id,
> +					       &entry,
> +					       res->vf_id);

several space in above 2 lines, better to replace to Tab

> +}
> +
> +static void
> +cmd_config_e_tag_insertion_dis_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
> +
> 	RTE_L2_TUNNEL_TYPE_E_TAG,
> +						res->vf_id);
> +}
> +
> +cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
> +	.f = cmd_config_e_tag_insertion_en_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag insertion enable",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_insertion,
> +		(void *)&cmd_config_e_tag_on,
> +		(void *)&cmd_config_e_tag_port_tag_id,
> +		(void *)&cmd_config_e_tag_port_tag_id_val,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		(void *)&cmd_config_e_tag_vf,
> +		(void *)&cmd_config_e_tag_vf_id,
> +		NULL,
> +	},
> +};
> +
> +cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
> +	.f = cmd_config_e_tag_insertion_dis_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag insertion disable",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_insertion,
> +		(void *)&cmd_config_e_tag_off,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		(void *)&cmd_config_e_tag_vf,
> +		(void *)&cmd_config_e_tag_vf_id,
> +		NULL,
> +	},
> +};
> +
> +/* E-tag stripping configuration */
> +static void
> +cmd_config_e_tag_stripping_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (!strcmp(res->on_off, "on"))
> +		rte_eth_dev_l2_tunnel_stripping_enable
> +			(res->port_id,
> +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> +	else
> +		rte_eth_dev_l2_tunnel_stripping_disable
> +			(res->port_id,
> +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> +}
> +
> +cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
> +	.f = cmd_config_e_tag_stripping_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag stripping enable/disable",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_stripping,
> +		(void *)&cmd_config_e_tag_on_off,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		NULL,
> +	},
> +};
> +
> +/* E-tag forwarding configuration */
> +static void
> +cmd_config_e_tag_forwarding_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (!strcmp(res->on_off, "on"))
> +		rte_eth_dev_l2_tunnel_forwarding_enable
> +			(res->port_id,
> +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> +	else
> +		rte_eth_dev_l2_tunnel_forwarding_disable
> +			(res->port_id,
> +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> +}
> +
> +cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
> +	.f = cmd_config_e_tag_forwarding_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag forwarding enable/disable",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_forwarding,
> +		(void *)&cmd_config_e_tag_on_off,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		NULL,
> +	},
> +};
> +
> +/* E-tag filter configuration */
> +static void
> +cmd_config_e_tag_filter_add_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +	struct rte_eth_l2_tunnel entry;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (res->e_tag_id_val > 0x3fff) {
> +		printf("e-tag-id must be less than 0x3fff.\n");

How about e-tag-id == 0x3fff? Error message seems to not allow, but the program actually does.

> +		return;
> +	}
> +
> +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> +	entry.tunnel_id = res->e_tag_id_val;
> +
> +	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
> +					 &entry,
> +					 res->dst_pool_val);
> +}
> +
> +cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
> +	.f = cmd_config_e_tag_filter_add_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag filter add",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_filter,
> +		(void *)&cmd_config_e_tag_add,
> +		(void *)&cmd_config_e_tag_e_tag_id,
> +		(void *)&cmd_config_e_tag_e_tag_id_val,
> +		(void *)&cmd_config_e_tag_dst_pool,
> +		(void *)&cmd_config_e_tag_dst_pool_val,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		NULL,
> +	},
> +};
> +
> +static void
> +cmd_config_e_tag_filter_del_parsed(
> +	void *parsed_result,
> +	__attribute__((unused)) struct cmdline *cl,
> +	__attribute__((unused)) void *data)
> +{
> +	struct cmd_config_e_tag_result *res =
> +		parsed_result;
> +	struct rte_eth_l2_tunnel entry;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (res->e_tag_id_val > 0x3fff) {
> +		printf("e-tag-id must be less than 0x3fff.\n");
> +		return;
> +	}
> +
> +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> +	entry.tunnel_id = res->e_tag_id_val;
> +
> +	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
> +					 &entry);
> +}
> +
> +cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
> +	.f = cmd_config_e_tag_filter_del_parsed,
> +	.data = NULL,
> +	.help_str = "E-tag filter delete",
> +	.tokens = {
> +		(void *)&cmd_config_e_tag_e_tag,
> +		(void *)&cmd_config_e_tag_set,
> +		(void *)&cmd_config_e_tag_filter,
> +		(void *)&cmd_config_e_tag_del,
> +		(void *)&cmd_config_e_tag_e_tag_id,
> +		(void *)&cmd_config_e_tag_e_tag_id_val,
> +		(void *)&cmd_config_e_tag_port,
> +		(void *)&cmd_config_e_tag_port_id,
> +		NULL,
> +	},
> +};
> +
>  /*
> **********************************************************
> ********************** */
> 
>  /* list of instructions */
> @@ -10040,6 +10412,12 @@ cmdline_parse_ctx_t main_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
>  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
>  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
> +	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
>  	NULL,
>  };
> 
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 5471ebe..e116d98 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -917,6 +917,32 @@ Set link down for a port::
> 
>     testpmd> set link-down port (port id)
> 
> +E-tag set
> +~~~~~~~~~
> +
> +Enable E-tag insertion for a VF on a port::
> +
> +   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
> +
> +Disable E-tag insertion for a VF on a port::
> +
> +   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
> +
> +Enable/disable E-tag stripping on a port::
> +
> +   testpmd> E-tag set stripping (on|off) port (port_id)
> +
> +Enable/disable E-tag based forwarding on a port::
> +
> +   testpmd> E-tag set forwarding (on|off) port (port_id)
> +
> +Add an E-tag forwarding filter on a port::
> +
> +   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port
> (port_id)
> +
> +Delete an E-tag forwarding filter on a port::
> +   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
> +
> 
>  Port Functions
>  --------------
> --
> 1.9.3

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

* Re: [PATCH v4 6/7] ixgbe: support l2 tunnel operation
  2016-02-18  2:46   ` [PATCH v4 6/7] ixgbe: support " Wenzhuo Lu
@ 2016-03-04  1:46     ` He, Shaopeng
  2016-03-04  3:15       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: He, Shaopeng @ 2016-03-04  1:46 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Thursday, February 18, 2016 10:46 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4 6/7] ixgbe: support l2 tunnel operation
> 
> Add support of l2 tunnel operation.
> Support enabling/disabling l2 tunnel tag insertion/stripping.
> Support enabling/disabling l2 tunnel packets forwarding.
> Support adding/deleting forwarding rules for l2 tunnel packets.
> Only support E-tag now.
> 
> Also update the release note.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  doc/guides/rel_notes/release_16_04.rst |  21 ++
>  drivers/net/ixgbe/ixgbe_ethdev.c       | 371
> +++++++++++++++++++++++++++++++++
>  2 files changed, 392 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_16_04.rst
> b/doc/guides/rel_notes/release_16_04.rst
> index eb1b3b2..994da33 100644
> --- a/doc/guides/rel_notes/release_16_04.rst
> +++ b/doc/guides/rel_notes/release_16_04.rst
> @@ -44,6 +44,27 @@ This section should contain new features added in this
> release. Sample format:
>    Add the offload and negotiation of checksum and TSO between vhost-user
> and
>    vanilla Linux virtio guest.
> 
> +* **Added support for E-tag on X550.**
> +
> +  E-tag is defined in 802.1br. Please reference
> +  http://www.ieee802.org/1/pages/802.1br.html.
> +
> +  This feature is for VF, but please aware all the setting is on PF. It means
> +  the CLIs should be used on PF, but some of their effect will be shown on
> VF.
> +  The forwarding of E-tag packets based on GRP and E-CID_base will have
> effect
> +  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
> +  But normally we'd like to forward the packets to the pools/queues
> belonging
> +  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
> +  VF receives E-tag packets, it should strip the E-tag. When VF transmits
> +  packets, it should insert the E-tag. Both can be offloaded.
> +
> +  When we want to use this E-tag support feature, the forwarding should be
> +  enabled to forward the packets received by PF to indicated VFs. And
> insertion
> +  and stripping should be enabled for VFs to offload the effort to HW.
> +
> +  * Support E-tag offloading of insertion and stripping.
> +  * Support Forwarding E-tag packets to pools based on
> +    GRP and E-CID_base.
> 
>  Resolved Issues
>  ---------------
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> b/drivers/net/ixgbe/ixgbe_ethdev.c
> index b15a4b6..aa00842 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -139,10 +139,17 @@
>  #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> 
>  #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
> +#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
>  #define DEFAULT_ETAG_ETYPE                     0x893f
>  #define IXGBE_ETAG_ETYPE                       0x00005084
>  #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
>  #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
> +#define IXGBE_RAH_ADTYPE                       0x40000000
> +#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
> +#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
> +#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
> +#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
> +#define IXGBE_QDE_STRIP_TAG                    0x00000004
> 
>  static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
>  static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
> @@ -351,6 +358,33 @@ static int ixgbe_dev_l2_tunnel_enable
>  static int ixgbe_dev_l2_tunnel_disable
>  	(struct rte_eth_dev *dev,
>  	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_insertion_enable
> +	(struct rte_eth_dev *dev,
> +	 struct rte_eth_l2_tunnel *l2_tunnel,
> +	 uint16_t vf_id);
> +static int ixgbe_dev_l2_tunnel_insertion_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> +	 uint16_t vf_id);
> +static int ixgbe_dev_l2_tunnel_stripping_enable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_stripping_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_forwarding_enable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_forwarding_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_filter_add
> +	(struct rte_eth_dev *dev,
> +	 struct rte_eth_l2_tunnel *l2_tunnel,
> +	 uint32_t pool);
> +static int ixgbe_dev_l2_tunnel_filter_del
> +	(struct rte_eth_dev *dev,
> +	 struct rte_eth_l2_tunnel *l2_tunnel);
> 
>  /*
>   * Define VF Stats MACRO for Non "cleared on read" register
> @@ -512,6 +546,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops
> = {
>  	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
>  	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
>  	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
> +	.l2_tunnel_insertion_enable   =
> ixgbe_dev_l2_tunnel_insertion_enable,
> +	.l2_tunnel_insertion_disable  =
> ixgbe_dev_l2_tunnel_insertion_disable,
> +	.l2_tunnel_stripping_enable   =
> ixgbe_dev_l2_tunnel_stripping_enable,
> +	.l2_tunnel_stripping_disable  =
> ixgbe_dev_l2_tunnel_stripping_disable,
> +	.l2_tunnel_forwarding_enable  =
> ixgbe_dev_l2_tunnel_forwarding_enable,
> +	.l2_tunnel_forwarding_disable =
> ixgbe_dev_l2_tunnel_forwarding_disable,
> +	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
> +	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
>  };
> 
>  /*
> @@ -6341,6 +6383,335 @@ ixgbe_dev_l2_tunnel_disable(struct
> rte_eth_dev *dev,
>  	return ret;
>  }
> 
> +static int
> +ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
> +		       struct rte_eth_l2_tunnel *l2_tunnel)
> +{
> +	int ret = 0;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +	u32 i, rar_entries;
> +	u32 rar_low, rar_high;
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	rar_entries = ixgbe_get_num_rx_addrs(hw);
> +
> +	for (i = 1; i < rar_entries; i++) {
> +		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
> +		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
> +		if ((rar_high & IXGBE_RAH_AV) &&
> +		    (rar_high & IXGBE_RAH_ADTYPE) &&
> +		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
> +		     l2_tunnel->tunnel_id)) {
> +			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
> +			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
> +
> +			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
> +
> +			return ret;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int
> +ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
> +		       struct rte_eth_l2_tunnel *l2_tunnel,
> +		       uint32_t pool)
> +{
> +	int ret = 0;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +	u32 i, rar_entries;
> +	u32 rar_low, rar_high;
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	/* One entry for one tunnel. Try to remove potential existing entry.
> */
> +	ixgbe_e_tag_filter_del(dev, l2_tunnel);
> +
> +	rar_entries = ixgbe_get_num_rx_addrs(hw);
> +
> +	for (i = 1; i < rar_entries; i++) {
> +		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
> +		if (rar_high & IXGBE_RAH_AV) {
> +			continue;
> +		} else {
> +			ixgbe_set_vmdq(hw, i, pool);

Do we need to check the return result here? 

> +			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
> +			rar_low = l2_tunnel->tunnel_id;
> +
> +			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
> +			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
> +
> +			return ret;
> +		}
> +	}
> +
> +	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
> +		     " Please remove a rule before adding a new one.");
> +	return -1;
> +}
> +
> +/* Add l2 tunnel filter */
> +static int
> +ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
> +			       struct rte_eth_l2_tunnel *l2_tunnel,
> +			       uint32_t pool)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel->l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Delete l2 tunnel filter */
> +static int
> +ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
> +			       struct rte_eth_l2_tunnel *l2_tunnel)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel->l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int
> +ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
> +{
> +	int ret = 0;
> +	uint32_t ctrl;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
> +	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
> +	if (en)
> +		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
> +	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
> +
> +	return ret;
> +}
> +
> +/* Enable l2 tunnel forwarding */
> +static int
> +ixgbe_dev_l2_tunnel_forwarding_enable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Disable l2 tunnel forwarding */
> +static int
> +ixgbe_dev_l2_tunnel_forwarding_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int
> +ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
> +			     struct rte_eth_l2_tunnel *l2_tunnel,
> +			     uint16_t vf_id,
> +			     bool en)
> +{
> +	int ret = 0;
> +	uint32_t vmtir, vmvir;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	if (vf_id >= dev->pci_dev->max_vfs) {
> +		PMD_DRV_LOG(ERR,
> +			    "VF id %u should be less than %u",
> +			    vf_id,
> +			    dev->pci_dev->max_vfs);
> +		return -EINVAL;
> +	}
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	if (en)
> +		vmtir = l2_tunnel->tunnel_id;
> +	else
> +		vmtir = 0;
> +
> +	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf_id), vmtir);
> +
> +	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf_id));
> +	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
> +	if (en)
> +		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
> +	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf_id), vmvir);
> +
> +	return ret;
> +}
> +
> +/* Enable l2 tunnel tag insertion */
> +static int
> +ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
> +				     struct rte_eth_l2_tunnel *l2_tunnel,
> +				     uint16_t vf_id)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel->l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, vf_id, 1);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Disable l2 tunnel tag insertion */
> +static int
> +ixgbe_dev_l2_tunnel_insertion_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> +	 uint16_t vf_id)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, vf_id, 0);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int
> +ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
> +			     bool en)
> +{
> +	int ret = 0;
> +	uint32_t qde;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
> +	if (en)
> +		qde |= IXGBE_QDE_STRIP_TAG;
> +	else
> +		qde &= ~IXGBE_QDE_STRIP_TAG;
> +	qde &= ~IXGBE_QDE_READ;
> +	qde |= IXGBE_QDE_WRITE;
> +	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
> +
> +	return ret;
> +}
> +
> +/* Enable l2 tunnel tag stripping */
> +static int
> +ixgbe_dev_l2_tunnel_stripping_enable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Disable l2 tunnel tag stripping */
> +static int
> +ixgbe_dev_l2_tunnel_stripping_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
>  static struct rte_driver rte_ixgbe_driver = {
>  	.type = PMD_PDEV,
>  	.init = rte_ixgbe_pmd_init,
> --
> 1.9.3

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

* Re: [PATCH v4 3/7] ixgbe: support l2 tunnel config
  2016-02-18  2:46   ` [PATCH v4 3/7] ixgbe: " Wenzhuo Lu
@ 2016-03-04  1:47     ` He, Shaopeng
  2016-03-04  3:17       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: He, Shaopeng @ 2016-03-04  1:47 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Thursday, February 18, 2016 10:46 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4 3/7] ixgbe: support l2 tunnel config
> 
> Add support of l2 tunnel configuration.
> Support modifying ether type of a type of l2 tunnel.
> Support enabling and disabling the support of a type of l2 tunnel.
> Only E-tag tunnel is supported now.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c | 140
> +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> b/drivers/net/ixgbe/ixgbe_ethdev.c
> index b99e48e..b15a4b6 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -139,6 +139,10 @@
>  #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> 
>  #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
> +#define DEFAULT_ETAG_ETYPE                     0x893f
> +#define IXGBE_ETAG_ETYPE                       0x00005084
> +#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
> +#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
> 
>  static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
>  static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
> @@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct
> rte_eth_dev *dev,
>  				   struct timespec *timestamp);
>  static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
>  				   const struct timespec *timestamp);
> +static int ixgbe_dev_l2_tunnel_eth_type_conf
> +	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
> +static int ixgbe_dev_l2_tunnel_enable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +static int ixgbe_dev_l2_tunnel_disable
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> 
>  /*
>   * Define VF Stats MACRO for Non "cleared on read" register
> @@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops =
> {
>  	.timesync_adjust_time = ixgbe_timesync_adjust_time,
>  	.timesync_read_time   = ixgbe_timesync_read_time,
>  	.timesync_write_time  = ixgbe_timesync_write_time,
> +	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
> +	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
> +	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
>  };
> 
>  /*
> @@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev
> *dev,
>  	return 0;
>  }
> 
> +/* Update e-tag ether type */
> +static int
> +ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
> +			    uint16_t ether_type)
> +{
> +	uint32_t etag_etype;
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> +	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
> +	etag_etype |= ether_type;
> +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> +	IXGBE_WRITE_FLUSH(hw);
> +
> +	return 0;
> +}
> +
> +/* Config l2 tunnel ether type */
> +static int
> +ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
> +				  struct rte_eth_l2_tunnel *l2_tunnel)
> +{
> +	int ret = 0;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	if (l2_tunnel == NULL)
> +		return -EINVAL;
> +
> +	switch (l2_tunnel->l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel-
> >ether_type);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;

Better to use: ret = -EINVAL?

> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Enable e-tag tunnel */
> +static int
> +ixgbe_e_tag_enable(struct ixgbe_hw *hw)
> +{
> +	uint32_t etag_etype;
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> +	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
> +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> +	IXGBE_WRITE_FLUSH(hw);
> +
> +	return 0;
> +}
> +
> +/* Enable l2 tunnel */
> +static int
> +ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
> +			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_enable(hw);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Disable e-tag tunnel */
> +static int
> +ixgbe_e_tag_disable(struct ixgbe_hw *hw)
> +{
> +	uint32_t etag_etype;
> +
> +	if (hw->mac.type != ixgbe_mac_X550 &&
> +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> +		return -ENOTSUP;
> +	}
> +
> +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> +	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
> +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> +	IXGBE_WRITE_FLUSH(hw);
> +
> +	return 0;
> +}
> +
> +/* Disable l2 tunnel */
> +static int
> +ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
> +			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
> +{
> +	int ret = 0;
> +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	switch (l2_tunnel_type) {
> +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> +		ret = ixgbe_e_tag_disable(hw);
> +		break;
> +	default:
> +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> +		ret = -1;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
>  static struct rte_driver rte_ixgbe_driver = {
>  	.type = PMD_PDEV,
>  	.init = rte_ixgbe_pmd_init,
> --
> 1.9.3

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

* Re: [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-02-18  2:46   ` [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-03-04  1:47     ` He, Shaopeng
  2016-03-04  3:31       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: He, Shaopeng @ 2016-03-04  1:47 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Thursday, February 18, 2016 10:46 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel
> operation
> 
> Add functions to support the new l2 tunnel operation.
> 1, Insertion and stripping for l2 tunnel tag.
> 2, Forwarding the packets to a pool based on l2 tunnel tag.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 183
> ++++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.h | 214
> ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 397 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index c5c12cb..6bc19d4 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
>  				-ENOTSUP);
>  	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);  }
> +
> +int
> +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> +				       struct rte_eth_l2_tunnel *l2_tunnel,
> +				       uint16_t vf_id)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	if (l2_tunnel == NULL) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> +		return -EINVAL;
> +	}
> +
> +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {

How about the value of RTE_L2_TUNNEL_TYPE_NONE here, is it an invalid type too?

> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_insertion_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
> +							   l2_tunnel,
> +							   vf_id);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
> +					enum rte_eth_l2_tunnel_type
> +						l2_tunnel_type,
> +					uint16_t vf_id)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_insertion_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
> +							    l2_tunnel_type,
> +							    vf_id);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
> +				       enum rte_eth_l2_tunnel_type
> +					       l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_stripping_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
> +							   l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_stripping_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
> +							    l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_forwarding_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
> +							    l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_forwarding_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
> +							     l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel,
> +				 uint32_t pool)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	if (l2_tunnel == NULL) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> +		return -EINVAL;
> +	}
> +
> +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_filter_add,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
> +						     l2_tunnel,
> +						     pool);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel) {
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	if (l2_tunnel == NULL) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> +		return -EINVAL;
> +	}
> +
> +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
> +						     l2_tunnel);
> +}
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 709485a..d482f8c 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list,
> rte_eth_dev_callback);  struct rte_eth_l2_tunnel {
>  	enum rte_eth_l2_tunnel_type l2_tunnel_type;
>  	uint16_t ether_type;
> +	uint32_t tunnel_id; /* port tag id for e-tag */
>  };
> 
>  /*
> @@ -1283,6 +1284,45 @@ typedef int (*eth_l2_tunnel_disable_t)
>  	 enum rte_eth_l2_tunnel_type l2_tunnel_type);  /**< @internal
> disable a type of l2 tunnel */
> 
> +typedef int (*eth_l2_tunnel_insertion_enable_t)
> +	(struct rte_eth_dev *dev,
> +	 struct rte_eth_l2_tunnel *l2_tunnel,
> +	 uint16_t vf_id);
> +/**< @internal enable insertion of l2 tunnel tag */
> +
> +typedef int (*eth_l2_tunnel_insertion_disable_t)
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> +	 uint16_t vf_id);
> +/**< @internal disable insertion of l2 tunnel tag */
> +
> +typedef int (*eth_l2_tunnel_stripping_enable_t)
> +	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type
> l2_tunnel_type);
> +/**< @internal enable stripping of l2 tunnel tag */
> +
> +typedef int (*eth_l2_tunnel_stripping_disable_t)
> +	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type
> l2_tunnel_type);
> +/**< @internal disable stripping of l2 tunnel tag */
> +
> +typedef int (*eth_l2_tunnel_forwarding_enable_t)
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); /**< @internal
> enable
> +forwarding of l2 tunnel packets */
> +
> +typedef int (*eth_l2_tunnel_forwarding_disable_t)
> +	(struct rte_eth_dev *dev,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); /**< @internal
> disable
> +forwarding of l2 tunnel packets */
> +
> +typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
> +					  struct rte_eth_l2_tunnel *l2_tunnel,
> +					  uint32_t pool);
> +/**< @internal add filter of l2 tunnel packets */
> +
> +typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
> +					  struct rte_eth_l2_tunnel
> *l2_tunnel); /**< @internal delete
> +filter of l2 tunnel packets */
> +
>  #ifdef RTE_NIC_BYPASS
> 
>  enum {
> @@ -1471,6 +1511,22 @@ struct eth_dev_ops {
>  	eth_l2_tunnel_enable_t l2_tunnel_enable;
>  	/** Disable a type of l2 tunnel */
>  	eth_l2_tunnel_disable_t l2_tunnel_disable;
> +	/** Enable insertion of l2 tunnel tag */
> +	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
> +	/** Disable insertion of l2 tunnel tag */
> +	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
> +	/** Enable stripping of l2 tunnel tag */
> +	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
> +	/** Disable stripping of l2 tunnel tag */
> +	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
> +	/** Enable forwarding of l2 tunnel packets */
> +	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
> +	/** Disable forwarding of l2 tunnel packets */
> +	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
> +	/** Add filter of l2 tunnel packets */
> +	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
> +	/** Delete filter of l2 tunnel packets */
> +	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
>  };
> 
>  /**
> @@ -3964,6 +4020,164 @@ int
>  rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
>  			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
> 
> + /**
> + * Enable l2 tunnel tag insertion of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + * @param vf_id
> + *   vf id.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> +				       struct rte_eth_l2_tunnel *l2_tunnel,
> +				       uint16_t vf_id);
> +
> + /**
> + * Disable l2 tunnel tag insertion of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel_type
> + *   l2 tunnel type.
> + * @param vf_id
> + *   vf id.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_insertion_disable
> +	(uint8_t port_id,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> +	 uint16_t vf_id);
> +
> + /**
> + * Enable l2 tunnel tag stripping of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel_type
> + *   l2 tunnel type.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_stripping_enable
> +	(uint8_t port_id,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +
> + /**
> + * Disable l2 tunnel tag stripping of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel_type
> + *   l2 tunnel type.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_stripping_disable
> +	(uint8_t port_id,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +
> + /**
> + * Enable l2 tunnel tag forwarding of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel_type
> + *   l2 tunnel type.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_forwarding_enable
> +	(uint8_t port_id,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +
> + /**
> + * Disable l2 tunnel tag forwarding of an Ethernet device for specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel_type
> + *   l2 tunnel type.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_forwarding_disable
> +	(uint8_t port_id,
> +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> +
> + /**
> + * Add a filter for packet forwarding based on l2 tunnel tag of an
> +Ethernet
> + * device for specific tunnel packets.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + * @param pool
> + *   Destination pool.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel,
> +				 uint32_t pool);
> +
> + /**
> + * Delete a filter for packet forwarding based on l2 tunnel tag of an
> +Ethernet
> + * device for specific tunnel packets.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> --
> 1.9.3

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

* Re: [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation
  2016-03-04  1:46     ` He, Shaopeng
@ 2016-03-04  3:11       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-04  3:11 UTC (permalink / raw)
  To: He, Shaopeng, dev

Hi Shaopeng,


> -----Original Message-----
> From: He, Shaopeng
> Sent: Friday, March 4, 2016 9:46 AM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v4 7/7] app/testpmd: add CLIs for E-tag
> operation
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > Sent: Thursday, February 18, 2016 10:46 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v4 7/7] app/testpmd: add CLIs for E-tag
> > operation
> >
> > Add the CLIs to support the E-tag operation.
> > 1, Offloading of E-tag insertion and stripping.
> > 2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  app/test-pmd/cmdline.c                      | 378
> > ++++++++++++++++++++++++++++
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
> >  2 files changed, 404 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 24a3169..02868f3 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void
> > *parsed_result,
> >  			"set link-down port (port_id)\n"
> >  			"	Set link down for a port.\n\n"
> >
> > +			"E-tag set insertion on port-tag-id (value)"
> > +			" port (port_id) vf (vf_id)\n"
> > +			"    Enable E-tag insertion for a VF on a port\n\n"
> > +
> > +			"E-tag set insertion off port (port_id) vf (vf_id)\n"
> > +			"    Disable E-tag insertion for a VF on a port\n\n"
> > +
> > +			"E-tag set stripping (on|off) port (port_id)\n"
> > +			"    Enable/disable E-tag stripping on a port\n\n"
> > +
> > +			"E-tag set forwarding (on|off) port (port_id)\n"
> > +			"    Enable/disable E-tag based forwarding"
> > +			" on a port\n\n"
> > +
> > +			"E-tag set filter add e-tag-id (value) dst-pool"
> > +			" (pool_id) port (port_id)\n"
> > +			"    Add an E-tag forwarding filter on a port\n\n"
> > +
> > +			"E-tag set filter del e-tag-id (value) port (port_id)\n"
> > +			"    Delete an E-tag forwarding filter on a port\n\n"
> > +
> >  			, list_pkt_forwarding_modes()
> >  		);
> >  	}
> > @@ -9895,6 +9916,357 @@ cmdline_parse_inst_t
> > cmd_config_l2_tunnel_en_dis_specific = {
> >  	},
> >  };
> >
> > +/* E-tag configuration */
> > +
> > +/* Common result structure for all E-tag configuration */ struct
> > +cmd_config_e_tag_result {
> > +	cmdline_fixed_string_t e_tag;
> > +	cmdline_fixed_string_t set;
> > +	cmdline_fixed_string_t insertion;
> > +	cmdline_fixed_string_t stripping;
> > +	cmdline_fixed_string_t forwarding;
> > +	cmdline_fixed_string_t filter;
> > +	cmdline_fixed_string_t add;
> > +	cmdline_fixed_string_t del;
> > +	cmdline_fixed_string_t on;
> > +	cmdline_fixed_string_t off;
> > +	cmdline_fixed_string_t on_off;
> > +	cmdline_fixed_string_t port_tag_id;
> > +	uint32_t port_tag_id_val;
> > +	cmdline_fixed_string_t e_tag_id;
> > +	uint16_t e_tag_id_val;
> > +	cmdline_fixed_string_t dst_pool;
> > +	uint8_t dst_pool_val;
> > +	cmdline_fixed_string_t port;
> > +	uint8_t port_id;
> > +	cmdline_fixed_string_t vf;
> > +	uint8_t vf_id;
> > +};
> > +
> > +/* Common CLI fields for all E-tag configuration */
> > +cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 e_tag, "E-tag");
> > +cmdline_parse_token_string_t cmd_config_e_tag_set =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 set, "set");
> > +cmdline_parse_token_string_t cmd_config_e_tag_insertion =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 insertion, "insertion");
> > +cmdline_parse_token_string_t cmd_config_e_tag_stripping =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 stripping, "stripping");
> > +cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 forwarding, "forwarding");
> > +cmdline_parse_token_string_t cmd_config_e_tag_filter =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 filter, "filter");
> > +cmdline_parse_token_string_t cmd_config_e_tag_add =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 add, "add");
> > +cmdline_parse_token_string_t cmd_config_e_tag_del =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 del, "del");
> > +cmdline_parse_token_string_t cmd_config_e_tag_on =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 on, "on");
> > +cmdline_parse_token_string_t cmd_config_e_tag_off =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 off, "off");
> > +cmdline_parse_token_string_t cmd_config_e_tag_on_off =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 on_off, "on#off");
> > +cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 port_tag_id, "port-tag-id");
> > +cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
> > +	TOKEN_NUM_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 port_tag_id_val, UINT32);
> > +cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 e_tag_id, "e-tag-id");
> > +cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
> > +	TOKEN_NUM_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 e_tag_id_val, UINT16);
> > +cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 dst_pool, "dst-pool");
> > +cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
> > +	TOKEN_NUM_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 dst_pool_val, UINT8);
> > +cmdline_parse_token_string_t cmd_config_e_tag_port =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 port, "port");
> > +cmdline_parse_token_num_t cmd_config_e_tag_port_id =
> > +	TOKEN_NUM_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 port_id, UINT8);
> > +cmdline_parse_token_string_t cmd_config_e_tag_vf =
> > +	TOKEN_STRING_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 vf, "vf");
> > +cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
> > +	TOKEN_NUM_INITIALIZER
> > +		(struct cmd_config_e_tag_result,
> > +		 vf_id, UINT8);
> > +
> > +/* E-tag insertion configuration */
> > +static void
> > +cmd_config_e_tag_insertion_en_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +	struct rte_eth_l2_tunnel entry;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> > +	entry.tunnel_id = res->port_tag_id_val;
> > +	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id,
> > +					       &entry,
> > +					       res->vf_id);
> 
> several space in above 2 lines, better to replace to Tab
O, I'll change it. Thanks.

> 
> > +}
> > +
> > +static void
> > +cmd_config_e_tag_insertion_dis_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
> > +
> > 	RTE_L2_TUNNEL_TYPE_E_TAG,
> > +						res->vf_id);
> > +}
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
> > +	.f = cmd_config_e_tag_insertion_en_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag insertion enable",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_insertion,
> > +		(void *)&cmd_config_e_tag_on,
> > +		(void *)&cmd_config_e_tag_port_tag_id,
> > +		(void *)&cmd_config_e_tag_port_tag_id_val,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		(void *)&cmd_config_e_tag_vf,
> > +		(void *)&cmd_config_e_tag_vf_id,
> > +		NULL,
> > +	},
> > +};
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
> > +	.f = cmd_config_e_tag_insertion_dis_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag insertion disable",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_insertion,
> > +		(void *)&cmd_config_e_tag_off,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		(void *)&cmd_config_e_tag_vf,
> > +		(void *)&cmd_config_e_tag_vf_id,
> > +		NULL,
> > +	},
> > +};
> > +
> > +/* E-tag stripping configuration */
> > +static void
> > +cmd_config_e_tag_stripping_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	if (!strcmp(res->on_off, "on"))
> > +		rte_eth_dev_l2_tunnel_stripping_enable
> > +			(res->port_id,
> > +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> > +	else
> > +		rte_eth_dev_l2_tunnel_stripping_disable
> > +			(res->port_id,
> > +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> > +}
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
> > +	.f = cmd_config_e_tag_stripping_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag stripping enable/disable",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_stripping,
> > +		(void *)&cmd_config_e_tag_on_off,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		NULL,
> > +	},
> > +};
> > +
> > +/* E-tag forwarding configuration */
> > +static void
> > +cmd_config_e_tag_forwarding_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	if (!strcmp(res->on_off, "on"))
> > +		rte_eth_dev_l2_tunnel_forwarding_enable
> > +			(res->port_id,
> > +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> > +	else
> > +		rte_eth_dev_l2_tunnel_forwarding_disable
> > +			(res->port_id,
> > +			 RTE_L2_TUNNEL_TYPE_E_TAG);
> > +}
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
> > +	.f = cmd_config_e_tag_forwarding_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag forwarding enable/disable",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_forwarding,
> > +		(void *)&cmd_config_e_tag_on_off,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		NULL,
> > +	},
> > +};
> > +
> > +/* E-tag filter configuration */
> > +static void
> > +cmd_config_e_tag_filter_add_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +	struct rte_eth_l2_tunnel entry;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	if (res->e_tag_id_val > 0x3fff) {
> > +		printf("e-tag-id must be less than 0x3fff.\n");
> 
> How about e-tag-id == 0x3fff? Error message seems to not allow, but the
> program actually does.
O, the print is not accurate. Will correct it, thanks.

> 
> > +		return;
> > +	}
> > +
> > +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> > +	entry.tunnel_id = res->e_tag_id_val;
> > +
> > +	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
> > +					 &entry,
> > +					 res->dst_pool_val);
> > +}
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
> > +	.f = cmd_config_e_tag_filter_add_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag filter add",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_filter,
> > +		(void *)&cmd_config_e_tag_add,
> > +		(void *)&cmd_config_e_tag_e_tag_id,
> > +		(void *)&cmd_config_e_tag_e_tag_id_val,
> > +		(void *)&cmd_config_e_tag_dst_pool,
> > +		(void *)&cmd_config_e_tag_dst_pool_val,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		NULL,
> > +	},
> > +};
> > +
> > +static void
> > +cmd_config_e_tag_filter_del_parsed(
> > +	void *parsed_result,
> > +	__attribute__((unused)) struct cmdline *cl,
> > +	__attribute__((unused)) void *data)
> > +{
> > +	struct cmd_config_e_tag_result *res =
> > +		parsed_result;
> > +	struct rte_eth_l2_tunnel entry;
> > +
> > +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +		return;
> > +
> > +	if (res->e_tag_id_val > 0x3fff) {
> > +		printf("e-tag-id must be less than 0x3fff.\n");
> > +		return;
> > +	}
> > +
> > +	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
> > +	entry.tunnel_id = res->e_tag_id_val;
> > +
> > +	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
> > +					 &entry);
> > +}
> > +
> > +cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
> > +	.f = cmd_config_e_tag_filter_del_parsed,
> > +	.data = NULL,
> > +	.help_str = "E-tag filter delete",
> > +	.tokens = {
> > +		(void *)&cmd_config_e_tag_e_tag,
> > +		(void *)&cmd_config_e_tag_set,
> > +		(void *)&cmd_config_e_tag_filter,
> > +		(void *)&cmd_config_e_tag_del,
> > +		(void *)&cmd_config_e_tag_e_tag_id,
> > +		(void *)&cmd_config_e_tag_e_tag_id_val,
> > +		(void *)&cmd_config_e_tag_port,
> > +		(void *)&cmd_config_e_tag_port_id,
> > +		NULL,
> > +	},
> > +};
> > +
> >  /*
> > **********************************************************
> > ********************** */
> >
> >  /* list of instructions */
> > @@ -10040,6 +10412,12 @@ cmdline_parse_ctx_t main_ctx[] = {
> >  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
> >  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
> >  	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
> > +	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
> >  	NULL,
> >  };
> >
> > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > index 5471ebe..e116d98 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -917,6 +917,32 @@ Set link down for a port::
> >
> >     testpmd> set link-down port (port id)
> >
> > +E-tag set
> > +~~~~~~~~~
> > +
> > +Enable E-tag insertion for a VF on a port::
> > +
> > +   testpmd> E-tag set insertion on port-tag-id (value) port (port_id)
> > + vf (vf_id)
> > +
> > +Disable E-tag insertion for a VF on a port::
> > +
> > +   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
> > +
> > +Enable/disable E-tag stripping on a port::
> > +
> > +   testpmd> E-tag set stripping (on|off) port (port_id)
> > +
> > +Enable/disable E-tag based forwarding on a port::
> > +
> > +   testpmd> E-tag set forwarding (on|off) port (port_id)
> > +
> > +Add an E-tag forwarding filter on a port::
> > +
> > +   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id)
> > + port
> > (port_id)
> > +
> > +Delete an E-tag forwarding filter on a port::
> > +   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
> > +
> >
> >  Port Functions
> >  --------------
> > --
> > 1.9.3

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

* Re: [PATCH v4 6/7] ixgbe: support l2 tunnel operation
  2016-03-04  1:46     ` He, Shaopeng
@ 2016-03-04  3:15       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-04  3:15 UTC (permalink / raw)
  To: He, Shaopeng, dev

Hi Shaopeng,


> -----Original Message-----
> From: He, Shaopeng
> Sent: Friday, March 4, 2016 9:47 AM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v4 6/7] ixgbe: support l2 tunnel operation
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > Sent: Thursday, February 18, 2016 10:46 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v4 6/7] ixgbe: support l2 tunnel operation
> >
> > Add support of l2 tunnel operation.
> > Support enabling/disabling l2 tunnel tag insertion/stripping.
> > Support enabling/disabling l2 tunnel packets forwarding.
> > Support adding/deleting forwarding rules for l2 tunnel packets.
> > Only support E-tag now.
> >
> > Also update the release note.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  doc/guides/rel_notes/release_16_04.rst |  21 ++
> >  drivers/net/ixgbe/ixgbe_ethdev.c       | 371
> > +++++++++++++++++++++++++++++++++
> >  2 files changed, 392 insertions(+)
> >
> > diff --git a/doc/guides/rel_notes/release_16_04.rst
> > b/doc/guides/rel_notes/release_16_04.rst
> > index eb1b3b2..994da33 100644
> > --- a/doc/guides/rel_notes/release_16_04.rst
> > +++ b/doc/guides/rel_notes/release_16_04.rst
> > @@ -44,6 +44,27 @@ This section should contain new features added in
> > this release. Sample format:
> >    Add the offload and negotiation of checksum and TSO between
> > vhost-user and
> >    vanilla Linux virtio guest.
> >
> > +* **Added support for E-tag on X550.**
> > +
> > +  E-tag is defined in 802.1br. Please reference
> > + http://www.ieee802.org/1/pages/802.1br.html.
> > +
> > +  This feature is for VF, but please aware all the setting is on PF.
> > + It means  the CLIs should be used on PF, but some of their effect
> > + will be shown on
> > VF.
> > +  The forwarding of E-tag packets based on GRP and E-CID_base will
> > + have
> > effect
> > +  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
> > +  But normally we'd like to forward the packets to the pools/queues
> > belonging
> > +  to the VFs. And E-tag insertion and stripping will have effect on
> > + VFs. When  VF receives E-tag packets, it should strip the E-tag.
> > + When VF transmits  packets, it should insert the E-tag. Both can be offloaded.
> > +
> > +  When we want to use this E-tag support feature, the forwarding
> > + should be  enabled to forward the packets received by PF to
> > + indicated VFs. And
> > insertion
> > +  and stripping should be enabled for VFs to offload the effort to HW.
> > +
> > +  * Support E-tag offloading of insertion and stripping.
> > +  * Support Forwarding E-tag packets to pools based on
> > +    GRP and E-CID_base.
> >
> >  Resolved Issues
> >  ---------------
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index b15a4b6..aa00842 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -139,10 +139,17 @@
> >  #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> >
> >  #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
> > +#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
> >  #define DEFAULT_ETAG_ETYPE                     0x893f
> >  #define IXGBE_ETAG_ETYPE                       0x00005084
> >  #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
> >  #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
> > +#define IXGBE_RAH_ADTYPE                       0x40000000
> > +#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
> > +#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
> > +#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
> > +#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
> > +#define IXGBE_QDE_STRIP_TAG                    0x00000004
> >
> >  static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);  static
> > int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev); @@ -351,6
> > +358,33 @@ static int ixgbe_dev_l2_tunnel_enable  static int
> > ixgbe_dev_l2_tunnel_disable
> >  	(struct rte_eth_dev *dev,
> >  	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> > +static int ixgbe_dev_l2_tunnel_insertion_enable
> > +	(struct rte_eth_dev *dev,
> > +	 struct rte_eth_l2_tunnel *l2_tunnel,
> > +	 uint16_t vf_id);
> > +static int ixgbe_dev_l2_tunnel_insertion_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> > +	 uint16_t vf_id);
> > +static int ixgbe_dev_l2_tunnel_stripping_enable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); static int
> > +ixgbe_dev_l2_tunnel_stripping_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); static int
> > +ixgbe_dev_l2_tunnel_forwarding_enable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); static int
> > +ixgbe_dev_l2_tunnel_forwarding_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); static int
> > +ixgbe_dev_l2_tunnel_filter_add
> > +	(struct rte_eth_dev *dev,
> > +	 struct rte_eth_l2_tunnel *l2_tunnel,
> > +	 uint32_t pool);
> > +static int ixgbe_dev_l2_tunnel_filter_del
> > +	(struct rte_eth_dev *dev,
> > +	 struct rte_eth_l2_tunnel *l2_tunnel);
> >
> >  /*
> >   * Define VF Stats MACRO for Non "cleared on read" register @@ -512,6
> > +546,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
> >  	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
> >  	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
> >  	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
> > +	.l2_tunnel_insertion_enable   =
> > ixgbe_dev_l2_tunnel_insertion_enable,
> > +	.l2_tunnel_insertion_disable  =
> > ixgbe_dev_l2_tunnel_insertion_disable,
> > +	.l2_tunnel_stripping_enable   =
> > ixgbe_dev_l2_tunnel_stripping_enable,
> > +	.l2_tunnel_stripping_disable  =
> > ixgbe_dev_l2_tunnel_stripping_disable,
> > +	.l2_tunnel_forwarding_enable  =
> > ixgbe_dev_l2_tunnel_forwarding_enable,
> > +	.l2_tunnel_forwarding_disable =
> > ixgbe_dev_l2_tunnel_forwarding_disable,
> > +	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
> > +	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
> >  };
> >
> >  /*
> > @@ -6341,6 +6383,335 @@ ixgbe_dev_l2_tunnel_disable(struct
> > rte_eth_dev *dev,
> >  	return ret;
> >  }
> >
> > +static int
> > +ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
> > +		       struct rte_eth_l2_tunnel *l2_tunnel) {
> > +	int ret = 0;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +	u32 i, rar_entries;
> > +	u32 rar_low, rar_high;
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	rar_entries = ixgbe_get_num_rx_addrs(hw);
> > +
> > +	for (i = 1; i < rar_entries; i++) {
> > +		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
> > +		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
> > +		if ((rar_high & IXGBE_RAH_AV) &&
> > +		    (rar_high & IXGBE_RAH_ADTYPE) &&
> > +		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
> > +		     l2_tunnel->tunnel_id)) {
> > +			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
> > +			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
> > +
> > +			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
> > +
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
> > +		       struct rte_eth_l2_tunnel *l2_tunnel,
> > +		       uint32_t pool)
> > +{
> > +	int ret = 0;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +	u32 i, rar_entries;
> > +	u32 rar_low, rar_high;
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	/* One entry for one tunnel. Try to remove potential existing entry.
> > */
> > +	ixgbe_e_tag_filter_del(dev, l2_tunnel);
> > +
> > +	rar_entries = ixgbe_get_num_rx_addrs(hw);
> > +
> > +	for (i = 1; i < rar_entries; i++) {
> > +		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
> > +		if (rar_high & IXGBE_RAH_AV) {
> > +			continue;
> > +		} else {
> > +			ixgbe_set_vmdq(hw, i, pool);
> 
> Do we need to check the return result here?
I think we need not to do that. Because ixgbe_set_vmdq is not supported or rar is out of range. I believe we already guaranteed that will not happen :)

> 
> > +			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
> > +			rar_low = l2_tunnel->tunnel_id;
> > +
> > +			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
> > +			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
> > +
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
> > +		     " Please remove a rule before adding a new one.");
> > +	return -1;
> > +}
> > +
> > +/* Add l2 tunnel filter */
> > +static int
> > +ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
> > +			       struct rte_eth_l2_tunnel *l2_tunnel,
> > +			       uint32_t pool)
> > +{
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel->l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Delete l2 tunnel filter */
> > +static int
> > +ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
> > +			       struct rte_eth_l2_tunnel *l2_tunnel) {
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel->l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en) {
> > +	int ret = 0;
> > +	uint32_t ctrl;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
> > +	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
> > +	if (en)
> > +		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
> > +	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
> > +
> > +	return ret;
> > +}
> > +
> > +/* Enable l2 tunnel forwarding */
> > +static int
> > +ixgbe_dev_l2_tunnel_forwarding_enable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Disable l2 tunnel forwarding */
> > +static int
> > +ixgbe_dev_l2_tunnel_forwarding_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
> > +			     struct rte_eth_l2_tunnel *l2_tunnel,
> > +			     uint16_t vf_id,
> > +			     bool en)
> > +{
> > +	int ret = 0;
> > +	uint32_t vmtir, vmvir;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	if (vf_id >= dev->pci_dev->max_vfs) {
> > +		PMD_DRV_LOG(ERR,
> > +			    "VF id %u should be less than %u",
> > +			    vf_id,
> > +			    dev->pci_dev->max_vfs);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	if (en)
> > +		vmtir = l2_tunnel->tunnel_id;
> > +	else
> > +		vmtir = 0;
> > +
> > +	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf_id), vmtir);
> > +
> > +	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf_id));
> > +	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
> > +	if (en)
> > +		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
> > +	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf_id), vmvir);
> > +
> > +	return ret;
> > +}
> > +
> > +/* Enable l2 tunnel tag insertion */
> > +static int
> > +ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
> > +				     struct rte_eth_l2_tunnel *l2_tunnel,
> > +				     uint16_t vf_id)
> > +{
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel->l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, vf_id, 1);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Disable l2 tunnel tag insertion */ static int
> > +ixgbe_dev_l2_tunnel_insertion_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> > +	 uint16_t vf_id)
> > +{
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, vf_id, 0);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
> > +			     bool en)
> > +{
> > +	int ret = 0;
> > +	uint32_t qde;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
> > +	if (en)
> > +		qde |= IXGBE_QDE_STRIP_TAG;
> > +	else
> > +		qde &= ~IXGBE_QDE_STRIP_TAG;
> > +	qde &= ~IXGBE_QDE_READ;
> > +	qde |= IXGBE_QDE_WRITE;
> > +	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
> > +
> > +	return ret;
> > +}
> > +
> > +/* Enable l2 tunnel tag stripping */
> > +static int
> > +ixgbe_dev_l2_tunnel_stripping_enable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Disable l2 tunnel tag stripping */ static int
> > +ixgbe_dev_l2_tunnel_stripping_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> >  static struct rte_driver rte_ixgbe_driver = {
> >  	.type = PMD_PDEV,
> >  	.init = rte_ixgbe_pmd_init,
> > --
> > 1.9.3

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

* Re: [PATCH v4 3/7] ixgbe: support l2 tunnel config
  2016-03-04  1:47     ` He, Shaopeng
@ 2016-03-04  3:17       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-04  3:17 UTC (permalink / raw)
  To: He, Shaopeng, dev

Hi Shaopeng,


> -----Original Message-----
> From: He, Shaopeng
> Sent: Friday, March 4, 2016 9:47 AM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v4 3/7] ixgbe: support l2 tunnel config
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > Sent: Thursday, February 18, 2016 10:46 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v4 3/7] ixgbe: support l2 tunnel config
> >
> > Add support of l2 tunnel configuration.
> > Support modifying ether type of a type of l2 tunnel.
> > Support enabling and disabling the support of a type of l2 tunnel.
> > Only E-tag tunnel is supported now.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  drivers/net/ixgbe/ixgbe_ethdev.c | 140
> > +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 140 insertions(+)
> >
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index b99e48e..b15a4b6 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -139,6 +139,10 @@
> >  #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> >
> >  #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
> > +#define DEFAULT_ETAG_ETYPE                     0x893f
> > +#define IXGBE_ETAG_ETYPE                       0x00005084
> > +#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
> > +#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
> >
> >  static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);  static
> > int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev); @@ -339,6
> > +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev
> > *dev,
> >  				   struct timespec *timestamp);
> >  static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
> >  				   const struct timespec *timestamp);
> > +static int ixgbe_dev_l2_tunnel_eth_type_conf
> > +	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
> > +static int ixgbe_dev_l2_tunnel_enable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); static int
> > +ixgbe_dev_l2_tunnel_disable
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> >
> >  /*
> >   * Define VF Stats MACRO for Non "cleared on read" register @@ -497,6
> > +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
> >  	.timesync_adjust_time = ixgbe_timesync_adjust_time,
> >  	.timesync_read_time   = ixgbe_timesync_read_time,
> >  	.timesync_write_time  = ixgbe_timesync_write_time,
> > +	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
> > +	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
> > +	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
> >  };
> >
> >  /*
> > @@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev
> > *dev,
> >  	return 0;
> >  }
> >
> > +/* Update e-tag ether type */
> > +static int
> > +ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
> > +			    uint16_t ether_type)
> > +{
> > +	uint32_t etag_etype;
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> > +	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
> > +	etag_etype |= ether_type;
> > +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> > +	IXGBE_WRITE_FLUSH(hw);
> > +
> > +	return 0;
> > +}
> > +
> > +/* Config l2 tunnel ether type */
> > +static int
> > +ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
> > +				  struct rte_eth_l2_tunnel *l2_tunnel) {
> > +	int ret = 0;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	if (l2_tunnel == NULL)
> > +		return -EINVAL;
> > +
> > +	switch (l2_tunnel->l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel-
> > >ether_type);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> 
> Better to use: ret = -EINVAL?
Yes, it's the bad side of copying code. I'll correct it :)

> 
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Enable e-tag tunnel */
> > +static int
> > +ixgbe_e_tag_enable(struct ixgbe_hw *hw) {
> > +	uint32_t etag_etype;
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> > +	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
> > +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> > +	IXGBE_WRITE_FLUSH(hw);
> > +
> > +	return 0;
> > +}
> > +
> > +/* Enable l2 tunnel */
> > +static int
> > +ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
> > +			   enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_enable(hw);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/* Disable e-tag tunnel */
> > +static int
> > +ixgbe_e_tag_disable(struct ixgbe_hw *hw) {
> > +	uint32_t etag_etype;
> > +
> > +	if (hw->mac.type != ixgbe_mac_X550 &&
> > +	    hw->mac.type != ixgbe_mac_X550EM_x) {
> > +		return -ENOTSUP;
> > +	}
> > +
> > +	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
> > +	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
> > +	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
> > +	IXGBE_WRITE_FLUSH(hw);
> > +
> > +	return 0;
> > +}
> > +
> > +/* Disable l2 tunnel */
> > +static int
> > +ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
> > +			    enum rte_eth_l2_tunnel_type l2_tunnel_type) {
> > +	int ret = 0;
> > +	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +
> > +	switch (l2_tunnel_type) {
> > +	case RTE_L2_TUNNEL_TYPE_E_TAG:
> > +		ret = ixgbe_e_tag_disable(hw);
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(ERR, "Invalid tunnel type");
> > +		ret = -1;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> >  static struct rte_driver rte_ixgbe_driver = {
> >  	.type = PMD_PDEV,
> >  	.init = rte_ixgbe_pmd_init,
> > --
> > 1.9.3

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

* Re: [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-03-04  1:47     ` He, Shaopeng
@ 2016-03-04  3:31       ` Lu, Wenzhuo
  2016-03-07  2:04         ` He, Shaopeng
  0 siblings, 1 reply; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-04  3:31 UTC (permalink / raw)
  To: He, Shaopeng, dev

Hi Shaopeng,


> -----Original Message-----
> From: He, Shaopeng
> Sent: Friday, March 4, 2016 9:47 AM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel
> operation
> 
> Hi Wenzhuo,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > Sent: Thursday, February 18, 2016 10:46 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new l2
> > tunnel operation
> >
> > Add functions to support the new l2 tunnel operation.
> > 1, Insertion and stripping for l2 tunnel tag.
> > 2, Forwarding the packets to a pool based on l2 tunnel tag.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  lib/librte_ether/rte_ethdev.c | 183
> > ++++++++++++++++++++++++++++++++++++
> >  lib/librte_ether/rte_ethdev.h | 214
> > ++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 397 insertions(+)
> >
> > diff --git a/lib/librte_ether/rte_ethdev.c
> > b/lib/librte_ether/rte_ethdev.c index c5c12cb..6bc19d4 100644
> > --- a/lib/librte_ether/rte_ethdev.c
> > +++ b/lib/librte_ether/rte_ethdev.c
> > @@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
> >  				-ENOTSUP);
> >  	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);  }
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> > +				       struct rte_eth_l2_tunnel *l2_tunnel,
> > +				       uint16_t vf_id)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +	if (l2_tunnel == NULL) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> 
> How about the value of RTE_L2_TUNNEL_TYPE_NONE here, is it an invalid type
> too?
Honestly, the purpose I check this tunnel type here is to avoid the subscript out of bound error if some NIC create an array which index is tunnel type.
So, although type_none is an invalid type, I don't check it here. How do you think about it? Thanks.

> 
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_insertion_enable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
> > +							   l2_tunnel,
> > +							   vf_id);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
> > +					enum rte_eth_l2_tunnel_type
> > +						l2_tunnel_type,
> > +					uint16_t vf_id)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_insertion_disable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
> > +							    l2_tunnel_type,
> > +							    vf_id);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
> > +				       enum rte_eth_l2_tunnel_type
> > +					       l2_tunnel_type)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_stripping_enable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
> > +							   l2_tunnel_type);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
> > +					 enum rte_eth_l2_tunnel_type
> > +						 l2_tunnel_type)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_stripping_disable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
> > +							    l2_tunnel_type);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
> > +					 enum rte_eth_l2_tunnel_type
> > +						 l2_tunnel_type)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_forwarding_enable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
> > +							    l2_tunnel_type);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
> > +					 enum rte_eth_l2_tunnel_type
> > +						 l2_tunnel_type)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_forwarding_disable,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
> > +							     l2_tunnel_type);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel,
> > +				 uint32_t pool)
> > +{
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +	if (l2_tunnel == NULL) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >l2_tunnel_filter_add,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
> > +						     l2_tunnel,
> > +						     pool);
> > +}
> > +
> > +int
> > +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel) {
> > +	struct rte_eth_dev *dev;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +	if (l2_tunnel == NULL) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> > +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev = &rte_eth_devices[port_id];
> > +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
> > +				-ENOTSUP);
> > +	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
> > +						     l2_tunnel);
> > +}
> > diff --git a/lib/librte_ether/rte_ethdev.h
> > b/lib/librte_ether/rte_ethdev.h index 709485a..d482f8c 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list,
> > rte_eth_dev_callback);  struct rte_eth_l2_tunnel {
> >  	enum rte_eth_l2_tunnel_type l2_tunnel_type;
> >  	uint16_t ether_type;
> > +	uint32_t tunnel_id; /* port tag id for e-tag */
> >  };
> >
> >  /*
> > @@ -1283,6 +1284,45 @@ typedef int (*eth_l2_tunnel_disable_t)
> >  	 enum rte_eth_l2_tunnel_type l2_tunnel_type);  /**< @internal
> > disable a type of l2 tunnel */
> >
> > +typedef int (*eth_l2_tunnel_insertion_enable_t)
> > +	(struct rte_eth_dev *dev,
> > +	 struct rte_eth_l2_tunnel *l2_tunnel,
> > +	 uint16_t vf_id);
> > +/**< @internal enable insertion of l2 tunnel tag */
> > +
> > +typedef int (*eth_l2_tunnel_insertion_disable_t)
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> > +	 uint16_t vf_id);
> > +/**< @internal disable insertion of l2 tunnel tag */
> > +
> > +typedef int (*eth_l2_tunnel_stripping_enable_t)
> > +	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type
> > l2_tunnel_type);
> > +/**< @internal enable stripping of l2 tunnel tag */
> > +
> > +typedef int (*eth_l2_tunnel_stripping_disable_t)
> > +	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type
> > l2_tunnel_type);
> > +/**< @internal disable stripping of l2 tunnel tag */
> > +
> > +typedef int (*eth_l2_tunnel_forwarding_enable_t)
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); /**< @internal
> > enable
> > +forwarding of l2 tunnel packets */
> > +
> > +typedef int (*eth_l2_tunnel_forwarding_disable_t)
> > +	(struct rte_eth_dev *dev,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type); /**< @internal
> > disable
> > +forwarding of l2 tunnel packets */
> > +
> > +typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
> > +					  struct rte_eth_l2_tunnel *l2_tunnel,
> > +					  uint32_t pool);
> > +/**< @internal add filter of l2 tunnel packets */
> > +
> > +typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
> > +					  struct rte_eth_l2_tunnel
> > *l2_tunnel); /**< @internal delete
> > +filter of l2 tunnel packets */
> > +
> >  #ifdef RTE_NIC_BYPASS
> >
> >  enum {
> > @@ -1471,6 +1511,22 @@ struct eth_dev_ops {
> >  	eth_l2_tunnel_enable_t l2_tunnel_enable;
> >  	/** Disable a type of l2 tunnel */
> >  	eth_l2_tunnel_disable_t l2_tunnel_disable;
> > +	/** Enable insertion of l2 tunnel tag */
> > +	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
> > +	/** Disable insertion of l2 tunnel tag */
> > +	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
> > +	/** Enable stripping of l2 tunnel tag */
> > +	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
> > +	/** Disable stripping of l2 tunnel tag */
> > +	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
> > +	/** Enable forwarding of l2 tunnel packets */
> > +	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
> > +	/** Disable forwarding of l2 tunnel packets */
> > +	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
> > +	/** Add filter of l2 tunnel packets */
> > +	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
> > +	/** Delete filter of l2 tunnel packets */
> > +	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
> >  };
> >
> >  /**
> > @@ -3964,6 +4020,164 @@ int
> >  rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
> >  			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
> >
> > + /**
> > + * Enable l2 tunnel tag insertion of an Ethernet device for specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + * @param vf_id
> > + *   vf id.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> > +				       struct rte_eth_l2_tunnel *l2_tunnel,
> > +				       uint16_t vf_id);
> > +
> > + /**
> > + * Disable l2 tunnel tag insertion of an Ethernet device for specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel_type
> > + *   l2 tunnel type.
> > + * @param vf_id
> > + *   vf id.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_insertion_disable
> > +	(uint8_t port_id,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
> > +	 uint16_t vf_id);
> > +
> > + /**
> > + * Enable l2 tunnel tag stripping of an Ethernet device for specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel_type
> > + *   l2 tunnel type.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_stripping_enable
> > +	(uint8_t port_id,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> > +
> > + /**
> > + * Disable l2 tunnel tag stripping of an Ethernet device for specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel_type
> > + *   l2 tunnel type.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_stripping_disable
> > +	(uint8_t port_id,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> > +
> > + /**
> > + * Enable l2 tunnel tag forwarding of an Ethernet device for specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel_type
> > + *   l2 tunnel type.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_forwarding_enable
> > +	(uint8_t port_id,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> > +
> > + /**
> > + * Disable l2 tunnel tag forwarding of an Ethernet device for
> > +specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel_type
> > + *   l2 tunnel type.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_forwarding_disable
> > +	(uint8_t port_id,
> > +	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
> > +
> > + /**
> > + * Add a filter for packet forwarding based on l2 tunnel tag of an
> > +Ethernet
> > + * device for specific tunnel packets.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + * @param pool
> > + *   Destination pool.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel,
> > +				 uint32_t pool);
> > +
> > + /**
> > + * Delete a filter for packet forwarding based on l2 tunnel tag of an
> > +Ethernet
> > + * device for specific tunnel packets.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel);
> > +
> >  #ifdef __cplusplus
> >  }
> >  #endif
> > --
> > 1.9.3

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

* Re: [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                     ` (6 preceding siblings ...)
  2016-02-18  2:46   ` [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-03-04  9:23   ` Liu, Yong
  7 siblings, 0 replies; 95+ messages in thread
From: Liu, Yong @ 2016-03-04  9:23 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Tested-by: Yong Liu <yong.liu@intel.com>

- Tested Branch: dpdk-next-net
- Tested Commit: 5fa83b5398e26af7537b09605432fcb3d0cc1d41
- OS: Fedora21 3.17.4-301.fc21.x86_64
- GCC: gcc version 4.9.2 20150212
- CPU: Intel(R) Xeon(R) CPU D-1540 @ 2.00GHz
- NIC: Intel Corporation Device Sageville [8086:15ad]
- Default x86_64-native-linuxapp-gcc configuration
- Total 4 cases, 4 passed, 0 failed

- Prerequisites command / instruction:
  Bound PF device to igb_uio
    ./tools/dpdk_nic_bind.py --bind=igb_uio 03:00.0
  Create 2VF devices from PF device.
    echo 2 > /sys/bus/pci/devices/0000\:03\:00.0/max_vfs
  Detach VFs from the host, bind them to pci-stub driver
    virsh # nodedev-dettach pci_0000_03_10_0
    virsh # nodedev-dettach pci_0000_03_10_2
  Passthrough VF 03:10.0 & 03:10.2 to vm0 and start vm0
    /usr/bin/qemu-system-x86_64  -name vm0 -enable-kvm \
    -cpu host -smp 4 -m 2048 -drive file=/home/image/fedora20.img -vnc :1 \
    -device pci-assign,host=03:10.0 \
    -device pci-assign,host=03:10.2
  Login vm0 and them bind VF devices to igb_uio driver.
    ./tools/dpdk_nic_bind.py --bind=igb_uio 00:04.0 00:05.0
  Bind PF to vfio-pci and start testpmd in host
    testpmd -c f -n 3 -- -i
  Config to rxonly mode and enable verbose output
    testpmd> set fwd rxonly
    testpmd> set verbose 1
    testpmd> start
  Start testpmd in guest, configured to mac forward mode
    testpmd -c 0x3 -n 1  -- -i  --txqflags=0x0
    testpmd> set fwd mac
    testpmd> start

- Case: E-tag tunnel filter
  Description: check that E-tag tunnel filter can work as expected
  Command / instruction:
    Enable E-tag l2 tunnel support means enabling ability of parsing E-tag
    packet. This ability should be enabled before we enable filtering,
    forwarding, offloading for this specific type of tunnel
      host testpmd> port config 0 l2-tunnel E-tag enable
    Send 802.1BR packet to PF and VFs, check packet normally received

- Case: E-tag filter and forwarding
  Description: check that E-tag forwarding work as expected
  Command / instruction:
    Enable E-tag packet forwarding and enable E-tag 1000 packet forward to VF0
      testpmd> E-tag set forwarding on port 0
      testpmd> E-tag set filter add e-tag-id 1000 dst-pool 0 port 0
    Send E-tag packet with broadcast mac and check packet only received on VF0
  
    Set E-tag with ID 1000 forwarding to VF1
      testpmd> E-tag set filter add e-tag-id 1000 dst-pool 1 port 0
    Send 802.1BR packet with broadcast mac and check packet only received on VF1

    Set E-tag with ID 1000 PF0
      testpmd> E-tag set filter add e-tag-id 1000 dst-pool 2 port 0
    Send 802.1BR packet with broadcast mac and check packet only received on PF
    
    Remove E-tag
      testpmd> E-tag set filter del e-tag-id 1000 port 0
    Send 802.1BR packet with broadcast mac and check packet not received

- Case: E-tag insertion
  Description: check that E-tag insertion feature can work as expected
  Command / instruction:
    Enable E-tag insertion in VF0
      testpmd> E-tag set insertion on port-tag-id 1000 port 0 vf 0
    Send normal packet to VF1 and check forwarded packet contain E-tag
    Remove E-tag insertion in VF0
      testpmd> E-tag set insertion off port 0 vf 0
    Send normal packet to VF1 and check forwarded packet not include E-tag
    
- Case: E-tag strip
  Description: check that E-tag strip feature can work as expected
    Enable E-tag strip on PF
      testpmd> E-tag set filter add e-tag-id 1000 dst-pool 0 port 0
      testpmd> E-tag set stripping on port 0
    Send 802.1BR packet to VF and check forwarded packet without E-tag
    Disable E-tag strip on PF
      testpmd> E-tag set stripping off port 0
    Send 802.1BR packet and check forwarded packet with E-tag.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Thursday, February 18, 2016 10:46 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4 0/7] support E-tag offloading and
> forwarding on Intel X550 NIC
> 
> This patch set adds the support of E-tag offloading and forwarding
> on X550.
> The offloading means E-tag can be inserted and stripped by HW.
> And E-tag packets can be recognized and forwarded to specific pools
> based on GRP and E-CID_base in E-tag.
> 
> E-tag is defined in IEEE802.1br. Please reference
> http://www.ieee802.org/1/pages/802.1br.html.
> 
> V2:
> * Add the introduction for E-tag.
> 
> V3:
> * Add the hlep info for the new CLIs.
> * Update the doc for testpmd.
> * Update the E-tag insertion setting. Should insert different tunnel
>   id for every VF, not a common one for all.
> 
> V4:
> * Fix strippig is not working issue.
> * Update the filter adding function. Make sure there's only one filter
>   entry for one tunnel entry.
> * Update the release note to add some info about how to use this feature.
> 
> Wenzhuo Lu (7):
>   ixgbe: select pool by MAC when using double VLAN
>   lib/librte_ether: support l2 tunnel config
>   ixgbe: support l2 tunnel config
>   app/testpmd: add CLIs for l2 tunnel config
>   lib/librte_ether: support new l2 tunnel operation
>   ixgbe: support l2 tunnel operation
>   app/testpmd: add CLIs for E-tag operation
> 
>  app/test-pmd/cmdline.c                      | 647
> +++++++++++++++++++++++++++-
>  doc/guides/rel_notes/release_16_04.rst      |  21 +
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
>  drivers/net/ixgbe/ixgbe_ethdev.c            | 521 ++++++++++++++++++++++
>  lib/librte_ether/rte_eth_ctrl.h             |   9 +
>  lib/librte_ether/rte_ethdev.c               | 244 +++++++++++
>  lib/librte_ether/rte_ethdev.h               | 298 +++++++++++++
>  7 files changed, 1776 insertions(+), 1 deletion(-)
> 
> --
> 1.9.3

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

* Re: [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-03-04  3:31       ` Lu, Wenzhuo
@ 2016-03-07  2:04         ` He, Shaopeng
  0 siblings, 0 replies; 95+ messages in thread
From: He, Shaopeng @ 2016-03-07  2:04 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi Wenzhuo,

> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Friday, March 04, 2016 11:31 AM
> To: He, Shaopeng <shaopeng.he@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new l2
> tunnel operation
> 
> Hi Shaopeng,
> 
> 
> > -----Original Message-----
> > From: He, Shaopeng
> > Sent: Friday, March 4, 2016 9:47 AM
> > To: Lu, Wenzhuo; dev@dpdk.org
> > Subject: RE: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new
> > l2 tunnel operation
> >
> > Hi Wenzhuo,
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> > > Sent: Thursday, February 18, 2016 10:46 AM
> > > To: dev@dpdk.org
> > > Subject: [dpdk-dev] [PATCH v4 5/7] lib/librte_ether: support new l2
> > > tunnel operation
> > >
> > > Add functions to support the new l2 tunnel operation.
> > > 1, Insertion and stripping for l2 tunnel tag.
> > > 2, Forwarding the packets to a pool based on l2 tunnel tag.
> > >
> > > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > > ---
> > >  lib/librte_ether/rte_ethdev.c | 183
> > > ++++++++++++++++++++++++++++++++++++
> > >  lib/librte_ether/rte_ethdev.h | 214
> > > ++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 397 insertions(+)
> > >
> > > diff --git a/lib/librte_ether/rte_ethdev.c
> > > b/lib/librte_ether/rte_ethdev.c index c5c12cb..6bc19d4 100644
> > > --- a/lib/librte_ether/rte_ethdev.c
> > > +++ b/lib/librte_ether/rte_ethdev.c
> > > @@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t
> port_id,
> > >  				-ENOTSUP);
> > >  	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);  }
> > > +
> > > +int
> > > +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> > > +				       struct rte_eth_l2_tunnel *l2_tunnel,
> > > +				       uint16_t vf_id)
> > > +{
> > > +	struct rte_eth_dev *dev;
> > > +
> > > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > > +	if (l2_tunnel == NULL) {
> > > +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> >
> > How about the value of RTE_L2_TUNNEL_TYPE_NONE here, is it an invalid
> > type too?
> Honestly, the purpose I check this tunnel type here is to avoid the subscript
> out of bound error if some NIC create an array which index is tunnel type.
> So, although type_none is an invalid type, I don't check it here. How do you
> think about it? Thanks.
Ok for me if it will not cause problem and be checked in other place

Thanks,
--Shaopeng

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

* [PATCH v5 0/7] support E-tag offloading and forwarding on X550
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (11 preceding siblings ...)
  2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
@ 2016-03-07  2:42 ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (6 more replies)
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                   ` (2 subsequent siblings)
  15 siblings, 7 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

v2:
- Add the introduction for E-tag.

v3:
- Add the hlep info for the new CLIs.
- Update the doc for testpmd.
- Update the E-tag insertion setting.

v4:
- Fix strippig is not working issue.
- Update the filter adding function. One filter for one tunnel entry.
- Update the release note to add some info about how to use this feature.

v5:
- Use macro for return value.
- Correct print info.

Wenzhuo Lu (7):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel config
  ixgbe: support l2 tunnel config
  app/testpmd: add CLIs for l2 tunnel config
  lib/librte_ether: support new l2 tunnel operation
  ixgbe: support l2 tunnel operation
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 647 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_16_04.rst      |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 521 ++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |   9 +
 lib/librte_ether/rte_ethdev.c               | 244 +++++++++++
 lib/librte_ether/rte_ethdev.h               | 298 +++++++++++++
 7 files changed, 1776 insertions(+), 1 deletion(-)

Tested-by: Yong Liu <yong.liu@intel.com>

-- 
1.9.3

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

* [PATCH v5 1/7] ixgbe: select pool by MAC when using double VLAN
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3e6fe86..b99e48e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v5 2/7] lib/librte_ether: support l2 tunnel config
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 3/7] ixgbe: " Wenzhuo Lu
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration.
The support includes ether type modification and the tunnel support
enabling/disabling.
Ether type modification means modifying the ether type of a specific
type of tunnel. So the packet with this ether type will be parsed as
this type of tunnel.
Enabling/disabling a tunnel support means enabling/disabling the
ability of parsing the specific type of tunnel. This ability should
be enabled before we enable filtering, forwarding, offloading for
this specific type of tunnel.
Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h |  9 +++++
 lib/librte_ether/rte_ethdev.c   | 61 ++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h   | 84 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 756b234..c5c12cb 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3237,3 +3237,64 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_enable)(dev, l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16da821..709485a 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,14 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1269,20 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable a type of l2 tunnel */
+
+typedef int (*eth_l2_tunnel_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable a type of l2 tunnel */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1465,12 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable a type of l2 tunnel */
+	eth_l2_tunnel_enable_t l2_tunnel_enable;
+	/** Disable a type of l2 tunnel */
+	eth_l2_tunnel_disable_t l2_tunnel_disable;
 };
 
 /**
@@ -3880,6 +3908,62 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets depend on
+ * this ability.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_enable(uint8_t port_id,
+			     enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable the ability of parsing a type of l2 tunnel of an Ethernet device.
+ * Filtering, forwarding and offloading this type of tunnel packets will not
+ * work either even if they're enabled.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   The type of l2 tunnel.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
+			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v5 3/7] ixgbe: support l2 tunnel config
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration.
Support modifying ether type of a type of l2 tunnel.
Support enabling and disabling the support of a type of l2 tunnel.
Only E-tag tunnel is supported now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 140 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b99e48e..4d7404e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,10 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +343,14 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +509,9 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
+	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
 };
 
 /*
@@ -6201,6 +6216,131 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v5 4/7] app/testpmd: add CLIs for l2 tunnel config
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-03-07  2:42   ` [PATCH v5 3/7] ixgbe: " Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 269 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..24a3169 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -572,7 +572,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9632,6 +9640,261 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	portid_t pid;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis)) {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_enable(pid, l2_tunnel_type);
+		}
+	} else {
+		FOREACH_PORT(pid, ports) {
+			rte_eth_dev_l2_tunnel_disable(pid, l2_tunnel_type);
+		}
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_enable(res->id, l2_tunnel_type);
+	else
+		rte_eth_dev_l2_tunnel_disable(res->id, l2_tunnel_type);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9773,6 +10036,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-03-07  2:42   ` [PATCH v5 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  3:29     ` Wu, Jingjing
  2016-03-07  2:42   ` [PATCH v5 6/7] ixgbe: support " Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  6 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add functions to support the new l2 tunnel operation.
1, Insertion and stripping for l2 tunnel tag.
2, Forwarding the packets to a pool based on l2 tunnel tag.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 183 ++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 214 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 397 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index c5c12cb..6bc19d4 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 				-ENOTSUP);
 	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);
 }
+
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
+							   l2_tunnel,
+							   vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
+					enum rte_eth_l2_tunnel_type
+						l2_tunnel_type,
+					uint16_t vf_id)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_insertion_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
+							    l2_tunnel_type,
+							    vf_id);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
+				       enum rte_eth_l2_tunnel_type
+					       l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
+							   l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_stripping_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_enable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
+							    l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
+					 enum rte_eth_l2_tunnel_type
+						 l2_tunnel_type)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_forwarding_disable,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
+							     l2_tunnel_type);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel,
+						     pool);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 709485a..d482f8c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -963,6 +963,7 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 struct rte_eth_l2_tunnel {
 	enum rte_eth_l2_tunnel_type l2_tunnel_type;
 	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
 };
 
 /*
@@ -1283,6 +1284,45 @@ typedef int (*eth_l2_tunnel_disable_t)
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
 /**< @internal disable a type of l2 tunnel */
 
+typedef int (*eth_l2_tunnel_insertion_enable_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+/**< @internal enable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_insertion_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+/**< @internal disable insertion of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_enable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_stripping_disable_t)
+	(struct rte_eth_dev *dev, enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable stripping of l2 tunnel tag */
+
+typedef int (*eth_l2_tunnel_forwarding_enable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal enable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_forwarding_disable_t)
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+/**< @internal disable forwarding of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel,
+					  uint32_t pool);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1471,6 +1511,22 @@ struct eth_dev_ops {
 	eth_l2_tunnel_enable_t l2_tunnel_enable;
 	/** Disable a type of l2 tunnel */
 	eth_l2_tunnel_disable_t l2_tunnel_disable;
+	/** Enable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_enable_t l2_tunnel_insertion_enable;
+	/** Disable insertion of l2 tunnel tag */
+	eth_l2_tunnel_insertion_disable_t l2_tunnel_insertion_disable;
+	/** Enable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_enable_t l2_tunnel_stripping_enable;
+	/** Disable stripping of l2 tunnel tag */
+	eth_l2_tunnel_stripping_disable_t l2_tunnel_stripping_disable;
+	/** Enable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_enable_t l2_tunnel_forwarding_enable;
+	/** Disable forwarding of l2 tunnel packets */
+	eth_l2_tunnel_forwarding_disable_t l2_tunnel_forwarding_disable;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3964,6 +4020,164 @@ int
 rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
 			      enum rte_eth_l2_tunnel_type l2_tunnel_type);
 
+ /**
+ * Enable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
+				       struct rte_eth_l2_tunnel *l2_tunnel,
+				       uint16_t vf_id);
+
+ /**
+ * Disable l2 tunnel tag insertion of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ * @param vf_id
+ *   vf id.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_insertion_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+
+ /**
+ * Enable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag stripping of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_stripping_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Enable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_enable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Disable l2 tunnel tag forwarding of an Ethernet device for specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel_type
+ *   l2 tunnel type.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_forwarding_disable
+	(uint8_t port_id,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ * @param pool
+ *   Destination pool.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel,
+				 uint32_t pool);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3

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

* [PATCH v5 6/7] ixgbe: support l2 tunnel operation
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-03-07  2:42   ` [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  2016-03-07  2:42   ` [PATCH v5 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel operation.
Support enabling/disabling l2 tunnel tag insertion/stripping.
Support enabling/disabling l2 tunnel packets forwarding.
Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 371 +++++++++++++++++++++++++++++++++
 2 files changed, 392 insertions(+)

diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst
index eb1b3b2..994da33 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -44,6 +44,27 @@ This section should contain new features added in this release. Sample format:
   Add the offload and negotiation of checksum and TSO between vhost-user and
   vanilla Linux virtio guest.
 
+* **Added support for E-tag on X550.**
+
+  E-tag is defined in 802.1br. Please reference
+  http://www.ieee802.org/1/pages/802.1br.html.
+
+  This feature is for VF, but please aware all the setting is on PF. It means
+  the CLIs should be used on PF, but some of their effect will be shown on VF.
+  The forwarding of E-tag packets based on GRP and E-CID_base will have effect
+  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
+  But normally we'd like to forward the packets to the pools/queues belonging
+  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
+  VF receives E-tag packets, it should strip the E-tag. When VF transmits
+  packets, it should insert the E-tag. Both can be offloaded.
+
+  When we want to use this E-tag support feature, the forwarding should be
+  enabled to forward the packets received by PF to indicated VFs. And insertion
+  and stripping should be enabled for VFs to offload the effort to HW.
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4d7404e..6c51adc 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,10 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
 #define DEFAULT_ETAG_ETYPE                     0x893f
 #define IXGBE_ETAG_ETYPE                       0x00005084
 #define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
 #define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -351,6 +358,33 @@ static int ixgbe_dev_l2_tunnel_enable
 static int ixgbe_dev_l2_tunnel_disable
 	(struct rte_eth_dev *dev,
 	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_insertion_enable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id);
+static int ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t pool);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -512,6 +546,14 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
 	.l2_tunnel_enable        = ixgbe_dev_l2_tunnel_enable,
 	.l2_tunnel_disable       = ixgbe_dev_l2_tunnel_disable,
+	.l2_tunnel_insertion_enable   = ixgbe_dev_l2_tunnel_insertion_enable,
+	.l2_tunnel_insertion_disable  = ixgbe_dev_l2_tunnel_insertion_disable,
+	.l2_tunnel_stripping_enable   = ixgbe_dev_l2_tunnel_stripping_enable,
+	.l2_tunnel_stripping_disable  = ixgbe_dev_l2_tunnel_stripping_disable,
+	.l2_tunnel_forwarding_enable  = ixgbe_dev_l2_tunnel_forwarding_enable,
+	.l2_tunnel_forwarding_disable = ixgbe_dev_l2_tunnel_forwarding_disable,
+	.l2_tunnel_filter_add         = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del         = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6341,6 +6383,335 @@ ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel,
+		       uint32_t pool)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 i, rar_entries;
+	u32 rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	/* One entry for one tunnel. Try to remove potential existing entry. */
+	ixgbe_e_tag_filter_del(dev, l2_tunnel);
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -EINVAL;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel,
+			       uint32_t pool)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel, pool);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     uint16_t vf_id,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should be less than %u",
+			    vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel,
+				     uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, vf_id, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type,
+	 uint16_t vf_id)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, NULL, vf_id, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	qde &= ~IXGBE_QDE_READ;
+	qde |= IXGBE_QDE_WRITE;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v5 7/7] app/testpmd: add CLIs for E-tag operation
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (5 preceding siblings ...)
  2016-03-07  2:42   ` [PATCH v5 6/7] ixgbe: support " Wenzhuo Lu
@ 2016-03-07  2:42   ` Wenzhuo Lu
  6 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-07  2:42 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 378 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 404 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 24a3169..cf60612 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9895,6 +9916,357 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	rte_eth_dev_l2_tunnel_insertion_enable(res->port_id,
+					       &entry,
+					       res->vf_id);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	rte_eth_dev_l2_tunnel_insertion_disable(res->port_id,
+						RTE_L2_TUNNEL_TYPE_E_TAG,
+						res->vf_id);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_stripping_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_stripping_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_forwarding_enable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+	else
+		rte_eth_dev_l2_tunnel_forwarding_disable
+			(res->port_id,
+			 RTE_L2_TUNNEL_TYPE_E_TAG);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be equal or less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry,
+					 res->dst_pool_val);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10040,6 +10412,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* Re: [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-03-07  2:42   ` [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
@ 2016-03-07  3:29     ` Wu, Jingjing
  2016-03-07  5:29       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: Wu, Jingjing @ 2016-03-07  3:29 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev

Hi, wenzhuo

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Monday, March 07, 2016 10:43 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel
> operation
> 
> Add functions to support the new l2 tunnel operation.
> 1, Insertion and stripping for l2 tunnel tag.
> 2, Forwarding the packets to a pool based on l2 tunnel tag.
> 
> Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 183
> ++++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.h | 214
> ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 397 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index c5c12cb..6bc19d4 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -3298,3 +3298,186 @@ rte_eth_dev_l2_tunnel_disable(uint8_t port_id,
>  				-ENOTSUP);
>  	return (*dev->dev_ops->l2_tunnel_disable)(dev, l2_tunnel_type);  }
> +
> +int
> +rte_eth_dev_l2_tunnel_insertion_enable(uint8_t port_id,
> +				       struct rte_eth_l2_tunnel *l2_tunnel,
> +				       uint16_t vf_id)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	if (l2_tunnel == NULL) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> +		return -EINVAL;
> +	}
> +
> +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_insertion_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_insertion_enable)(dev,
> +							   l2_tunnel,
> +							   vf_id);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_insertion_disable(uint8_t port_id,
> +					enum rte_eth_l2_tunnel_type
> +						l2_tunnel_type,
> +					uint16_t vf_id)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_insertion_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_insertion_disable)(dev,
> +							    l2_tunnel_type,
> +							    vf_id);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_stripping_enable(uint8_t port_id,
> +				       enum rte_eth_l2_tunnel_type
> +					       l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_stripping_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_stripping_enable)(dev,
> +							   l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_stripping_disable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_stripping_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_stripping_disable)(dev,
> +							    l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_forwarding_enable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_forwarding_enable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_forwarding_enable)(dev,
> +							    l2_tunnel_type);
> +}
> +
> +int
> +rte_eth_dev_l2_tunnel_forwarding_disable(uint8_t port_id,
> +					 enum rte_eth_l2_tunnel_type
> +						 l2_tunnel_type)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_forwarding_disable,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_forwarding_disable)(dev,
> +							     l2_tunnel_type);
> +}
> +

How about to merge the above six APIs rte_eth_dev_l2_tunnel_XXX_enable/disable
to one, may call rte_eth_dev_l2_tunnel_offload_set?
Just like the rte_eth_dev_set_vlan_offload.


> +int
> +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel,
> +				 uint32_t pool)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	if (l2_tunnel == NULL) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
> +		return -EINVAL;
> +	}
> +
> +	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
> +		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
> +		return -EINVAL;
> +	}
> +
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >l2_tunnel_filter_add,
> +				-ENOTSUP);
> +	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
> +						     l2_tunnel,
> +						     pool);
> +}

Pool is used here, but vf_id is used above. Suggest to put such arguments into structure, maybe in l2_tunnel.

Thanks
Jingjing

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

* Re: [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation
  2016-03-07  3:29     ` Wu, Jingjing
@ 2016-03-07  5:29       ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-07  5:29 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Hi Jingjing,
> 
> How about to merge the above six APIs
> rte_eth_dev_l2_tunnel_XXX_enable/disable
> to one, may call rte_eth_dev_l2_tunnel_offload_set?
> Just like the rte_eth_dev_set_vlan_offload.
Good suggestion. I'll do it.

> 
> 
> Pool is used here, but vf_id is used above. Suggest to put such arguments into
> structure, maybe in l2_tunnel.
Agree, seems better. I'll send a new version.

> 
> Thanks
> Jingjing

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

* [PATCH v6 0/5] support E-tag offloading and forwarding on X550
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (12 preceding siblings ...)
  2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
@ 2016-03-08  6:53 ` Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (5 more replies)
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
  15 siblings, 6 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

v2:
- Add the introduction for E-tag.

v3:
- Add the hlep info for the new CLIs.
- Update the doc for testpmd.
- Update the E-tag insertion setting.

v4:
- Fix strippig is not working issue.
- Update the filter adding function. One filter for one tunnel entry.
- Update the release note to add some info about how to use this feature.

v5:
- Use macro for return value.
- Correct print info.

v6:
- Merge some rte ops.

Wenzhuo Lu (5):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel operations
  ixgbe: support l2 tunnel operations
  app/testpmd: add CLIs for l2 tunnel config
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 677 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_16_04.rst      |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 548 ++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |   9 +
 lib/librte_ether/rte_ethdev.c               | 102 +++++
 lib/librte_ether/rte_ethdev.h               | 131 ++++++
 lib/librte_ether/rte_ether_version.map      |   4 +
 8 files changed, 1528 insertions(+), 1 deletion(-)

Tested-by: Yong Liu <yong.liu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>

-- 
1.9.3

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

* [PATCH v6 1/5] ixgbe: select pool by MAC when using double VLAN
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
@ 2016-03-08  6:53   ` Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3e6fe86..b99e48e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-03-08  6:53   ` Wenzhuo Lu
  2016-03-09  0:14     ` Thomas Monjalon
  2016-03-08  6:53   ` [PATCH v6 3/5] ixgbe: " Wenzhuo Lu
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration and operations.
1, L2 tunnel ether type modification.
   It means modifying the ether type of a specific type of tunnel.
   So the packet with this ether type will be parsed as this type
   of tunnel.
2, Enabling/disabling l2 tunnel support.
   It means enabling/disabling the ability of parsing the specific
   type of tunnel. This ability should be enabled before we enable
   filtering, forwarding, offloading for this specific type of
   tunnel.
3, Insertion and stripping for l2 tunnel tag.
4, Forwarding the packets to a pool based on l2 tunnel tag.

Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h        |   9 +++
 lib/librte_ether/rte_ethdev.c          | 102 +++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 131 +++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |   4 +
 4 files changed, 246 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..09af6fb 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -804,6 +804,15 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 756b234..729841f 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3237,3 +3237,105 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type.\n");
+		return -EINVAL;
+	}
+
+	if (mask == 0) {
+		RTE_PMD_DEBUG_TRACE("Mask should have a value.\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_offload_set,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_add,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_add)(dev,
+						     l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_filter_del,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_filter_del)(dev,
+						     l2_tunnel);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16da821..e990954 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,27 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+
+/**< l2 tunnel enable mask */
+#define ETH_L2_TUNNEL_ENABLE_MASK       0x00000001
+/**< l2 tunnel insertion mask */
+#define ETH_L2_TUNNEL_INSERTION_MASK    0x00000002
+/**< l2 tunnel stripping mask */
+#define ETH_L2_TUNNEL_STRIPPING_MASK    0x00000004
+/**< l2 tunnel forwarding mask */
+#define ETH_L2_TUNNEL_FORWARDING_MASK   0x00000008
+
+struct rte_eth_l2_tunnel {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
+	uint16_t vf_id;
+	uint32_t pool;
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1282,25 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_offload_set_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+/**< @internal enable/disable the l2 tunnel offload functions */
+
+typedef int (*eth_l2_tunnel_filter_add_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal add filter of l2 tunnel packets */
+
+typedef int (*eth_l2_tunnel_filter_del_t)(struct rte_eth_dev *dev,
+					  struct rte_eth_l2_tunnel *l2_tunnel);
+/**< @internal delete filter of l2 tunnel packets */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1483,14 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable/disable l2 tunnel offload functions */
+	eth_l2_tunnel_offload_set_t l2_tunnel_offload_set;
+	/** Add filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_add_t l2_tunnel_filter_add;
+	/** Delete filter of l2 tunnel packets */
+	eth_l2_tunnel_filter_del_t l2_tunnel_filter_del;
 };
 
 /**
@@ -3880,6 +3928,89 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Enable/disable l2 tunnel offload functions. Include,
+ * 1, The ability of parsing a type of l2 tunnel of an Ethernet device.
+ *    Filtering, forwarding and offloading this type of tunnel packets depend on
+ *    this ability.
+ * 2, Stripping the l2 tunnel tag.
+ * 3, Insertion of the l2 tunnel tag.
+ * 4, Forwarding the packets based on the l2 tunnel tag.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel parameters.
+ * @param mask
+ *   Indicate the offload function.
+ * @param en
+ *   Enable or disable this function.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en);
+
+ /**
+ * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
+ /**
+ * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
+ * device for specific tunnel packets.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
+				 struct rte_eth_l2_tunnel *l2_tunnel);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index d8db24d..8961597 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -114,6 +114,10 @@ DPDK_2.2 {
 	rte_eth_tx_queue_setup;
 	rte_eth_xstats_get;
 	rte_eth_xstats_reset;
+	rte_eth_dev_l2_tunnel_eth_type_conf;
+	rte_eth_dev_l2_tunnel_offload_set;
+	rte_eth_dev_l2_tunnel_filter_add;
+	rte_eth_dev_l2_tunnel_filter_del;
 
 	local: *;
 };
-- 
1.9.3

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

* [PATCH v6 3/5] ixgbe: support l2 tunnel operations
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
@ 2016-03-08  6:53   ` Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration and operations.
1, Support modifying ether type of a type of l2 tunnel.
2, Support enabling and disabling the support of a type of l2 tunnel.
3, Support enabling/disabling l2 tunnel tag insertion/stripping.
4, Support enabling/disabling l2 tunnel packets forwarding.
5, Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 538 +++++++++++++++++++++++++++++++++
 2 files changed, 559 insertions(+)

diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst
index eb1b3b2..994da33 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -44,6 +44,27 @@ This section should contain new features added in this release. Sample format:
   Add the offload and negotiation of checksum and TSO between vhost-user and
   vanilla Linux virtio guest.
 
+* **Added support for E-tag on X550.**
+
+  E-tag is defined in 802.1br. Please reference
+  http://www.ieee802.org/1/pages/802.1br.html.
+
+  This feature is for VF, but please aware all the setting is on PF. It means
+  the CLIs should be used on PF, but some of their effect will be shown on VF.
+  The forwarding of E-tag packets based on GRP and E-CID_base will have effect
+  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
+  But normally we'd like to forward the packets to the pools/queues belonging
+  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
+  VF receives E-tag packets, it should strip the E-tag. When VF transmits
+  packets, it should insert the E-tag. Both can be offloaded.
+
+  When we want to use this E-tag support feature, the forwarding should be
+  enabled to forward the packets received by PF to indicated VFs. And insertion
+  and stripping should be enabled for VFs to offload the effort to HW.
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b99e48e..b3299e6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +350,19 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+static int ixgbe_dev_l2_tunnel_filter_add
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_filter_del
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +521,10 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_offload_set   = ixgbe_dev_l2_tunnel_offload_set,
+	.l2_tunnel_filter_add    = ixgbe_dev_l2_tunnel_filter_add,
+	.l2_tunnel_filter_del    = ixgbe_dev_l2_tunnel_filter_del,
 };
 
 /*
@@ -6201,6 +6229,516 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	/* One entry for one tunnel. Try to remove potential existing entry. */
+	ixgbe_e_tag_filter_del(dev, l2_tunnel);
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, l2_tunnel->pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -EINVAL;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel *l2_tunnel,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel->vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should be less than %u",
+			    l2_tunnel->vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(l2_tunnel->vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	qde &= ~IXGBE_QDE_READ;
+	qde |= IXGBE_QDE_WRITE;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable/disable l2 tunnel offload functions */
+static int
+ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en)
+{
+	int ret = 0;
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	ret = -EINVAL;
+	if (mask & ETH_L2_TUNNEL_ENABLE_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_INSERTION_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_insertion_enable(
+				dev,
+				l2_tunnel);
+		else
+			ret = ixgbe_dev_l2_tunnel_insertion_disable(
+				dev,
+				l2_tunnel);
+	}
+
+	if (mask & ETH_L2_TUNNEL_STRIPPING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_stripping_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_stripping_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_FORWARDING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_forwarding_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_forwarding_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v6 4/5] app/testpmd: add CLIs for l2 tunnel config
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-03-08  6:53   ` [PATCH v6 3/5] ixgbe: " Wenzhuo Lu
@ 2016-03-08  6:53   ` Wenzhuo Lu
  2016-03-08  6:53   ` [PATCH v6 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  2016-03-08  8:08   ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wu, Jingjing
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 278 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 288 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..031db11 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -572,7 +572,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9632,6 +9640,270 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	struct rte_eth_l2_tunnel entry;
+	portid_t pid;
+	uint8_t en;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		en = 1;
+	else
+		en = 0;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_offload_set(pid,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  en);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  0);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9773,6 +10045,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v6 5/5] app/testpmd: add CLIs for E-tag operation
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-03-08  6:53   ` [PATCH v6 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
@ 2016-03-08  6:53   ` Wenzhuo Lu
  2016-03-08  8:08   ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wu, Jingjing
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-08  6:53 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 399 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 425 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 031db11..74552ca 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9904,6 +9925,378 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	entry.vf_id = res->vf_id;
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  1);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.vf_id = res->vf_id;
+
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be equal or less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+	entry.pool = res->dst_pool_val;
+
+	rte_eth_dev_l2_tunnel_filter_add(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	rte_eth_dev_l2_tunnel_filter_del(res->port_id,
+					 &entry);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10049,6 +10442,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* Re: [PATCH v6 0/5] support E-tag offloading and forwarding on X550
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-03-08  6:53   ` [PATCH v6 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-03-08  8:08   ` Wu, Jingjing
  5 siblings, 0 replies; 95+ messages in thread
From: Wu, Jingjing @ 2016-03-08  8:08 UTC (permalink / raw)
  To: Lu, Wenzhuo, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wenzhuo Lu
> Sent: Tuesday, March 08, 2016 2:54 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v6 0/5] support E-tag offloading and forwarding
> on X550
> 
> This patch set adds the support of E-tag offloading and forwarding on X550.
> The offloading means E-tag can be inserted and stripped by HW.
> And E-tag packets can be recognized and forwarded to specific pools based
> on GRP and E-CID_base in E-tag.
> 
> E-tag is defined in IEEE802.1br. Please reference
> http://www.ieee802.org/1/pages/802.1br.html.
> 
> v2:
> - Add the introduction for E-tag.
> 
> v3:
> - Add the hlep info for the new CLIs.
> - Update the doc for testpmd.
> - Update the E-tag insertion setting.
> 
> v4:
> - Fix strippig is not working issue.
> - Update the filter adding function. One filter for one tunnel entry.
> - Update the release note to add some info about how to use this feature.
> 
> v5:
> - Use macro for return value.
> - Correct print info.
> 
> v6:
> - Merge some rte ops.
> 
> Wenzhuo Lu (5):
>   ixgbe: select pool by MAC when using double VLAN
>   lib/librte_ether: support l2 tunnel operations
>   ixgbe: support l2 tunnel operations
>   app/testpmd: add CLIs for l2 tunnel config
>   app/testpmd: add CLIs for E-tag operation
> 
>  app/test-pmd/cmdline.c                      | 677
> +++++++++++++++++++++++++++-
>  doc/guides/rel_notes/release_16_04.rst      |  21 +
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
>  drivers/net/ixgbe/ixgbe_ethdev.c            | 548 ++++++++++++++++++++++
>  lib/librte_ether/rte_eth_ctrl.h             |   9 +
>  lib/librte_ether/rte_ethdev.c               | 102 +++++
>  lib/librte_ether/rte_ethdev.h               | 131 ++++++
>  lib/librte_ether/rte_ether_version.map      |   4 +
>  8 files changed, 1528 insertions(+), 1 deletion(-)
> 
> Tested-by: Yong Liu <yong.liu@intel.com>
> Acked-by: Shaopeng He <shaopeng.he@intel.com>
> 
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
> --
> 1.9.3

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

* Re: [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-08  6:53   ` [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
@ 2016-03-09  0:14     ` Thomas Monjalon
  2016-03-09  1:15       ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: Thomas Monjalon @ 2016-03-09  0:14 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev

2016-03-08 14:53, Wenzhuo Lu:
> +/**
> + * l2 tunnel type.
> + */
> +enum rte_eth_l2_tunnel_type {
> +	RTE_L2_TUNNEL_TYPE_NONE = 0,
> +	RTE_L2_TUNNEL_TYPE_E_TAG,
> +	RTE_L2_TUNNEL_TYPE_MAX,
> +};

We already have rte_eth_tunnel_type.
Why this struct is in rte_eth_ctrl.h and not used with rte_eth_dev_filter_ctrl?

> + /**
> + * Config l2 tunnel ether type of an Ethernet device for filtering specific
> + * tunnel packets by ether type.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
> +				    struct rte_eth_l2_tunnel *l2_tunnel);
> +
> + /**
> + * Enable/disable l2 tunnel offload functions. Include,
> + * 1, The ability of parsing a type of l2 tunnel of an Ethernet device.
> + *    Filtering, forwarding and offloading this type of tunnel packets depend on
> + *    this ability.
> + * 2, Stripping the l2 tunnel tag.
> + * 3, Insertion of the l2 tunnel tag.
> + * 4, Forwarding the packets based on the l2 tunnel tag.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel parameters.
> + * @param mask
> + *   Indicate the offload function.
> + * @param en
> + *   Enable or disable this function.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
> +				  struct rte_eth_l2_tunnel *l2_tunnel,
> +				  uint32_t mask,
> +				  uint8_t en);
> +
> + /**
> + * Add a filter for packet forwarding based on l2 tunnel tag of an Ethernet
> + * device for specific tunnel packets.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel);
> +
> + /**
> + * Delete a filter for packet forwarding based on l2 tunnel tag of an Ethernet
> + * device for specific tunnel packets.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param l2_tunnel
> + *   l2 tunnel configuration.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> +				 struct rte_eth_l2_tunnel *l2_tunnel);
> +

Why are we still adding some filtering functions after having the assertion that
the new filtering API in lib/librte_ether/rte_eth_ctrl.h was generic enough?
The filtering API v2 was a total failure.
Are we going to add new functions each time a new bit of a header must be parsed
by an offloaded filtering?
Are we going to add new functions for each new filter of a NIC?


> --- a/lib/librte_ether/rte_ether_version.map
> +++ b/lib/librte_ether/rte_ether_version.map
> @@ -114,6 +114,10 @@ DPDK_2.2 {
>  	rte_eth_tx_queue_setup;
>  	rte_eth_xstats_get;
>  	rte_eth_xstats_reset;
> +	rte_eth_dev_l2_tunnel_eth_type_conf;
> +	rte_eth_dev_l2_tunnel_offload_set;
> +	rte_eth_dev_l2_tunnel_filter_add;
> +	rte_eth_dev_l2_tunnel_filter_del;

It is not the right section but it doesn't really matter.

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

* Re: [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-09  0:14     ` Thomas Monjalon
@ 2016-03-09  1:15       ` Lu, Wenzhuo
  2016-03-09  9:27         ` Thomas Monjalon
  0 siblings, 1 reply; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-09  1:15 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi Thomas,


> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, March 9, 2016 8:15 AM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v6 2/5] lib/librte_ether: support l2 tunnel
> operations
> 
> 2016-03-08 14:53, Wenzhuo Lu:
> > +/**
> > + * l2 tunnel type.
> > + */
> > +enum rte_eth_l2_tunnel_type {
> > +	RTE_L2_TUNNEL_TYPE_NONE = 0,
> > +	RTE_L2_TUNNEL_TYPE_E_TAG,
> > +	RTE_L2_TUNNEL_TYPE_MAX,
> > +};
> 
> We already have rte_eth_tunnel_type.
Seems the tunnels in rte_eth_tunnel_type are all L3 packets. So, I want to add a new type for e-tag, s-tag... as they're l2 packets.
Do you suggest to merge it into rte_eth_tunnel_type?

> Why this struct is in rte_eth_ctrl.h and not used with rte_eth_dev_filter_ctrl?
Just want to put it together with rte_eth_tunnel_type :)

> 
> > + /**
> > + * Config l2 tunnel ether type of an Ethernet device for filtering
> > +specific
> > + * tunnel packets by ether type.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
> > +				    struct rte_eth_l2_tunnel *l2_tunnel);
> > +
> > + /**
> > + * Enable/disable l2 tunnel offload functions. Include,
> > + * 1, The ability of parsing a type of l2 tunnel of an Ethernet device.
> > + *    Filtering, forwarding and offloading this type of tunnel packets depend on
> > + *    this ability.
> > + * 2, Stripping the l2 tunnel tag.
> > + * 3, Insertion of the l2 tunnel tag.
> > + * 4, Forwarding the packets based on the l2 tunnel tag.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel parameters.
> > + * @param mask
> > + *   Indicate the offload function.
> > + * @param en
> > + *   Enable or disable this function.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
> > +				  struct rte_eth_l2_tunnel *l2_tunnel,
> > +				  uint32_t mask,
> > +				  uint8_t en);
> > +
> > + /**
> > + * Add a filter for packet forwarding based on l2 tunnel tag of an
> > +Ethernet
> > + * device for specific tunnel packets.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_filter_add(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel);
> > +
> > + /**
> > + * Delete a filter for packet forwarding based on l2 tunnel tag of an
> > +Ethernet
> > + * device for specific tunnel packets.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param l2_tunnel
> > + *   l2 tunnel configuration.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENODEV) if port identifier is invalid.
> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> > + */
> > +int
> > +rte_eth_dev_l2_tunnel_filter_del(uint8_t port_id,
> > +				 struct rte_eth_l2_tunnel *l2_tunnel);
> > +
> 
> Why are we still adding some filtering functions after having the assertion that
> the new filtering API in lib/librte_ether/rte_eth_ctrl.h was generic enough?
> The filtering API v2 was a total failure.
> Are we going to add new functions each time a new bit of a header must be
> parsed by an offloaded filtering?
> Are we going to add new functions for each new filter of a NIC?
Sorry, my bad. I'll try to use the existing filter API. Thanks.

> 
> 
> > --- a/lib/librte_ether/rte_ether_version.map
> > +++ b/lib/librte_ether/rte_ether_version.map
> > @@ -114,6 +114,10 @@ DPDK_2.2 {
> >  	rte_eth_tx_queue_setup;
> >  	rte_eth_xstats_get;
> >  	rte_eth_xstats_reset;
> > +	rte_eth_dev_l2_tunnel_eth_type_conf;
> > +	rte_eth_dev_l2_tunnel_offload_set;
> > +	rte_eth_dev_l2_tunnel_filter_add;
> > +	rte_eth_dev_l2_tunnel_filter_del;
> 
> It is not the right section but it doesn't really matter.
I didn't notice the DPDK_2.2. I'll do it correctly.

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

* [PATCH v7 0/5] support E-tag offloading and forwarding on X550
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (13 preceding siblings ...)
  2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
@ 2016-03-09  7:44 ` Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (5 more replies)
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
  15 siblings, 6 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

v2:
- Add the introduction for E-tag.

v3:
- Add the hlep info for the new CLIs.
- Update the doc for testpmd.
- Update the E-tag insertion setting.

v4:
- Fix strippig is not working issue.
- Update the filter adding function. One filter for one tunnel entry.
- Update the release note to add some info about how to use this feature.

v5:
- Use macro for return value.
- Correct print info.

v6:
- Merge some rte ops.

v7:
- Squash the l2 tunnel filter ops to filter ctrl ops.

Wenzhuo Lu (5):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel operations
  ixgbe: support l2 tunnel operations
  app/testpmd: add CLIs for l2 tunnel config
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 702 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_16_04.rst      |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 587 +++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |  18 +
 lib/librte_ether/rte_ethdev.c               |  54 +++
 lib/librte_ether/rte_ethdev.h               |  75 +++
 lib/librte_ether/rte_ether_version.map      |   7 +
 8 files changed, 1500 insertions(+), 1 deletion(-)

-- 
1.9.3

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

* [PATCH v7 1/5] ixgbe: select pool by MAC when using double VLAN
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
@ 2016-03-09  7:44   ` Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3e6fe86..b99e48e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v7 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-03-09  7:44   ` Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 3/5] ixgbe: " Wenzhuo Lu
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration and operations.
1, L2 tunnel ether type modification.
   It means modifying the ether type of a specific type of tunnel.
   So the packet with this ether type will be parsed as this type
   of tunnel.
2, Enabling/disabling l2 tunnel support.
   It means enabling/disabling the ability of parsing the specific
   type of tunnel. This ability should be enabled before we enable
   filtering, forwarding, offloading for this specific type of
   tunnel.
3, Insertion and stripping for l2 tunnel tag.
4, Forwarding the packets to a pool based on l2 tunnel tag.

Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h        | 18 ++++++++
 lib/librte_ether/rte_ethdev.c          | 54 ++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 75 ++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 ++++
 4 files changed, 154 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..0b71f47 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -89,6 +89,7 @@ enum rte_filter_type {
 	RTE_ETH_FILTER_TUNNEL,
 	RTE_ETH_FILTER_FDIR,
 	RTE_ETH_FILTER_HASH,
+	RTE_ETH_FILTER_L2_TUNNEL,
 	RTE_ETH_FILTER_MAX
 };
 
@@ -804,6 +805,23 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel type.
+ */
+enum rte_eth_l2_tunnel_type {
+	RTE_L2_TUNNEL_TYPE_NONE = 0,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
+	RTE_L2_TUNNEL_TYPE_MAX,
+};
+
+struct rte_eth_l2_tunnel_conf {
+	enum rte_eth_l2_tunnel_type l2_tunnel_type;
+	uint16_t ether_type;
+	uint32_t tunnel_id; /* port tag id for e-tag */
+	uint16_t vf_id;
+	uint32_t pool;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 756b234..dfd4541 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3237,3 +3237,57 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_L2_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2 tunnel type.\n");
+		return -EINVAL;
+	}
+
+	if (mask == 0) {
+		RTE_PMD_DEBUG_TRACE("Mask should have a value.\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_offload_set,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16da821..2008f1c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,19 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+
+/**< l2 tunnel enable mask */
+#define ETH_L2_TUNNEL_ENABLE_MASK       0x00000001
+/**< l2 tunnel insertion mask */
+#define ETH_L2_TUNNEL_INSERTION_MASK    0x00000002
+/**< l2 tunnel stripping mask */
+#define ETH_L2_TUNNEL_STRIPPING_MASK    0x00000004
+/**< l2 tunnel forwarding mask */
+#define ETH_L2_TUNNEL_FORWARDING_MASK   0x00000008
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1274,17 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_offload_set_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+/**< @internal enable/disable the l2 tunnel offload functions */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1467,10 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable/disable l2 tunnel offload functions */
+	eth_l2_tunnel_offload_set_t l2_tunnel_offload_set;
 };
 
 /**
@@ -3880,6 +3908,53 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel_conf *l2_tunnel);
+
+ /**
+ * Enable/disable l2 tunnel offload functions. Include,
+ * 1, The ability of parsing a type of l2 tunnel of an Ethernet device.
+ *    Filtering, forwarding and offloading this type of tunnel packets depend on
+ *    this ability.
+ * 2, Stripping the l2 tunnel tag.
+ * 3, Insertion of the l2 tunnel tag.
+ * 4, Forwarding the packets based on the l2 tunnel tag.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel parameters.
+ * @param mask
+ *   Indicate the offload function.
+ * @param en
+ *   Enable or disable this function.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index d8db24d..3a8aa94 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -117,3 +117,10 @@ DPDK_2.2 {
 
 	local: *;
 };
+
+DPDK_2.3 {
+	global:
+
+	rte_eth_dev_l2_tunnel_eth_type_conf;
+	rte_eth_dev_l2_tunnel_offload_set;
+}DPDK_2.2;
-- 
1.9.3

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

* [PATCH v7 3/5] ixgbe: support l2 tunnel operations
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
@ 2016-03-09  7:44   ` Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration and operations.
1, Support modifying ether type of a type of l2 tunnel.
2, Support enabling and disabling the support of a type of l2 tunnel.
3, Support enabling/disabling l2 tunnel tag insertion/stripping.
4, Support enabling/disabling l2 tunnel packets forwarding.
5, Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 577 +++++++++++++++++++++++++++++++++
 2 files changed, 598 insertions(+)

diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst
index eb1b3b2..994da33 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -44,6 +44,27 @@ This section should contain new features added in this release. Sample format:
   Add the offload and negotiation of checksum and TSO between vhost-user and
   vanilla Linux virtio guest.
 
+* **Added support for E-tag on X550.**
+
+  E-tag is defined in 802.1br. Please reference
+  http://www.ieee802.org/1/pages/802.1br.html.
+
+  This feature is for VF, but please aware all the setting is on PF. It means
+  the CLIs should be used on PF, but some of their effect will be shown on VF.
+  The forwarding of E-tag packets based on GRP and E-CID_base will have effect
+  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
+  But normally we'd like to forward the packets to the pools/queues belonging
+  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
+  VF receives E-tag packets, it should strip the E-tag. When VF transmits
+  packets, it should insert the E-tag. Both can be offloaded.
+
+  When we want to use this E-tag support feature, the forwarding should be
+  enabled to forward the packets received by PF to indicated VFs. And insertion
+  and stripping should be enabled for VFs to offload the effort to HW.
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b99e48e..a1ae338 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +350,16 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+static int ixgbe_dev_l2_tunnel_filter_handle(struct rte_eth_dev *dev,
+					     enum rte_filter_op filter_op,
+					     void *arg);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +518,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_offload_set   = ixgbe_dev_l2_tunnel_offload_set,
 };
 
 /*
@@ -5606,6 +5629,9 @@ ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
 	case RTE_ETH_FILTER_FDIR:
 		ret = ixgbe_fdir_ctrl_func(dev, filter_op, arg);
 		break;
+	case RTE_ETH_FILTER_L2_TUNNEL:
+		ret = ixgbe_dev_l2_tunnel_filter_handle(dev, filter_op, arg);
+		break;
 	default:
 		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
 							filter_type);
@@ -6201,6 +6227,557 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	/* One entry for one tunnel. Try to remove potential existing entry. */
+	ixgbe_e_tag_filter_del(dev, l2_tunnel);
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, l2_tunnel->pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -EINVAL;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * ixgbe_dev_l2_tunnel_filter_handle - Handle operations for l2 tunnel filter.
+ * @dev: pointer to rte_eth_dev structure
+ * @filter_op:operation will be taken.
+ * @arg: a pointer to specific structure corresponding to the filter_op
+ */
+static int
+ixgbe_dev_l2_tunnel_filter_handle(struct rte_eth_dev *dev,
+				  enum rte_filter_op filter_op,
+				  void *arg)
+{
+	int ret = 0;
+
+	if (filter_op == RTE_ETH_FILTER_NOP)
+		return 0;
+
+	if (arg == NULL) {
+		PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.",
+			    filter_op);
+		return -EINVAL;
+	}
+
+	switch (filter_op) {
+	case RTE_ETH_FILTER_ADD:
+		ret = ixgbe_dev_l2_tunnel_filter_add
+			(dev,
+			 (struct rte_eth_l2_tunnel_conf *)arg);
+		break;
+	case RTE_ETH_FILTER_DELETE:
+		ret = ixgbe_dev_l2_tunnel_filter_del
+			(dev,
+			 (struct rte_eth_l2_tunnel_conf *)arg);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel_conf *l2_tunnel,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel->vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should be less than %u",
+			    l2_tunnel->vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(l2_tunnel->vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	qde &= ~IXGBE_QDE_READ;
+	qde |= IXGBE_QDE_WRITE;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_l2_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable/disable l2 tunnel offload functions */
+static int
+ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en)
+{
+	int ret = 0;
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	ret = -EINVAL;
+	if (mask & ETH_L2_TUNNEL_ENABLE_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_INSERTION_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_insertion_enable(
+				dev,
+				l2_tunnel);
+		else
+			ret = ixgbe_dev_l2_tunnel_insertion_disable(
+				dev,
+				l2_tunnel);
+	}
+
+	if (mask & ETH_L2_TUNNEL_STRIPPING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_stripping_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_stripping_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_FORWARDING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_forwarding_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_forwarding_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v7 4/5] app/testpmd: add CLIs for l2 tunnel config
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-03-09  7:44   ` [PATCH v7 3/5] ixgbe: " Wenzhuo Lu
@ 2016-03-09  7:44   ` Wenzhuo Lu
  2016-03-09  7:44   ` [PATCH v7 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  2016-03-09 10:07   ` [PATCH v7 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 278 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 288 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..28be8e5 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -572,7 +572,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9632,6 +9640,270 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_L2_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	portid_t pid;
+	uint8_t en;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		en = 1;
+	else
+		en = 0;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_offload_set(pid,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  en);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  0);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9773,6 +10045,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v7 5/5] app/testpmd: add CLIs for E-tag operation
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-03-09  7:44   ` [PATCH v7 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
@ 2016-03-09  7:44   ` Wenzhuo Lu
  2016-03-09 10:07   ` [PATCH v7 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-09  7:44 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 450 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 28be8e5..e4fd617 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9904,6 +9925,403 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	entry.vf_id = res->vf_id;
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  1);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.vf_id = res->vf_id;
+
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be equal or less than 0x3fff.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_filter_supported(res->port_id,
+					   RTE_ETH_FILTER_L2_TUNNEL);
+	if (ret < 0) {
+		printf("E-tag filter is not supported on port %u.\n",
+		       res->port_id);
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+	entry.pool = res->dst_pool_val;
+
+	ret = rte_eth_dev_filter_ctrl(res->port_id,
+				      RTE_ETH_FILTER_L2_TUNNEL,
+				      RTE_ETH_FILTER_ADD,
+				      &entry);
+	if (ret < 0)
+		printf("E-tag filter programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_filter_supported(res->port_id,
+					   RTE_ETH_FILTER_L2_TUNNEL);
+	if (ret < 0) {
+		printf("E-tag filter is not supported on port %u.\n",
+		       res->port_id);
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	ret = rte_eth_dev_filter_ctrl(res->port_id,
+				      RTE_ETH_FILTER_L2_TUNNEL,
+				      RTE_ETH_FILTER_DELETE,
+				      &entry);
+	if (ret < 0)
+		printf("E-tag filter programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10049,6 +10467,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* Re: [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-09  1:15       ` Lu, Wenzhuo
@ 2016-03-09  9:27         ` Thomas Monjalon
  2016-03-10  0:54           ` Lu, Wenzhuo
  0 siblings, 1 reply; 95+ messages in thread
From: Thomas Monjalon @ 2016-03-09  9:27 UTC (permalink / raw)
  To: Lu, Wenzhuo; +Cc: dev

2016-03-09 01:15, Lu, Wenzhuo:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2016-03-08 14:53, Wenzhuo Lu:
> > > +/**
> > > + * l2 tunnel type.
> > > + */
> > > +enum rte_eth_l2_tunnel_type {
> > > +	RTE_L2_TUNNEL_TYPE_NONE = 0,
> > > +	RTE_L2_TUNNEL_TYPE_E_TAG,
> > > +	RTE_L2_TUNNEL_TYPE_MAX,
> > > +};
> > 
> > We already have rte_eth_tunnel_type.
> Seems the tunnels in rte_eth_tunnel_type are all L3 packets. So, I want to add a new type for e-tag, s-tag... as they're l2 packets.
> Do you suggest to merge it into rte_eth_tunnel_type?

Maybe you can keep the L2 prefix and add it in the same enum.
It depends wether the rest of the API is specific to L2 or not.

> > Why this struct is in rte_eth_ctrl.h and not used with rte_eth_dev_filter_ctrl?
> Just want to put it together with rte_eth_tunnel_type :)

> > Why are we still adding some filtering functions after having the assertion that
> > the new filtering API in lib/librte_ether/rte_eth_ctrl.h was generic enough?
> > The filtering API v2 was a total failure.
> > Are we going to add new functions each time a new bit of a header must be
> > parsed by an offloaded filtering?
> > Are we going to add new functions for each new filter of a NIC?
> 
> Sorry, my bad. I'll try to use the existing filter API. Thanks.

OK, using the filtering API v2 is better.
But I'm not confident it is a good API.
If you have any concern, please discuss them. Because we need to
discuss how to make a really generic API which fits with any filtering
(flow steering) offload of any vendor while being descriptive enough
and easy to use.

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

* Re: [PATCH v7 0/5] support E-tag offloading and forwarding on X550
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-03-09  7:44   ` [PATCH v7 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-03-09 10:07   ` Thomas Monjalon
  2016-03-10  0:44     ` Lu, Wenzhuo
  5 siblings, 1 reply; 95+ messages in thread
From: Thomas Monjalon @ 2016-03-09 10:07 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev

2016-03-09 15:44, Wenzhuo Lu:
> v7:
> - Squash the l2 tunnel filter ops to filter ctrl ops.

No you have not.
Please check rte_eth_dev_filter_ctrl()

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

* Re: [PATCH v7 0/5] support E-tag offloading and forwarding on X550
  2016-03-09 10:07   ` [PATCH v7 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
@ 2016-03-10  0:44     ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-10  0:44 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi Thomas,


> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, March 9, 2016 6:07 PM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v7 0/5] support E-tag offloading and forwarding
> on X550
> 
> 2016-03-09 15:44, Wenzhuo Lu:
> > v7:
> > - Squash the l2 tunnel filter ops to filter ctrl ops.
> 
> No you have not.
> Please check rte_eth_dev_filter_ctrl()
Do you mean these two should be replaced too? But they're not filter. So, have to say I'm confused.
rte_eth_dev_l2_tunnel_eth_type_conf;
rte_eth_dev_l2_tunnel_offload_set;

I've replaced rte_eth_dev_l2_tunnel_filter_add and rte_eth_dev_l2_tunnel_filter_del with rte_eth_dev_filter_ctrl.

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

* Re: [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-09  9:27         ` Thomas Monjalon
@ 2016-03-10  0:54           ` Lu, Wenzhuo
  0 siblings, 0 replies; 95+ messages in thread
From: Lu, Wenzhuo @ 2016-03-10  0:54 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi Thomas,


> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, March 9, 2016 5:28 PM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v6 2/5] lib/librte_ether: support l2 tunnel
> operations
> 
> 2016-03-09 01:15, Lu, Wenzhuo:
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > 2016-03-08 14:53, Wenzhuo Lu:
> > > > +/**
> > > > + * l2 tunnel type.
> > > > + */
> > > > +enum rte_eth_l2_tunnel_type {
> > > > +	RTE_L2_TUNNEL_TYPE_NONE = 0,
> > > > +	RTE_L2_TUNNEL_TYPE_E_TAG,
> > > > +	RTE_L2_TUNNEL_TYPE_MAX,
> > > > +};
> > >
> > > We already have rte_eth_tunnel_type.
> > Seems the tunnels in rte_eth_tunnel_type are all L3 packets. So, I want to add
> a new type for e-tag, s-tag... as they're l2 packets.
> > Do you suggest to merge it into rte_eth_tunnel_type?
> 
> Maybe you can keep the L2 prefix and add it in the same enum.
> It depends wether the rest of the API is specific to L2 or not.
OK, I'll keep the L2 prefix and merge it to the enum rte_eth_tunnel_type.

> 
> > > Why this struct is in rte_eth_ctrl.h and not used with rte_eth_dev_filter_ctrl?
> > Just want to put it together with rte_eth_tunnel_type :)
> 
> > > Why are we still adding some filtering functions after having the
> > > assertion that the new filtering API in lib/librte_ether/rte_eth_ctrl.h was
> generic enough?
> > > The filtering API v2 was a total failure.
> > > Are we going to add new functions each time a new bit of a header
> > > must be parsed by an offloaded filtering?
> > > Are we going to add new functions for each new filter of a NIC?
> >
> > Sorry, my bad. I'll try to use the existing filter API. Thanks.
> 
> OK, using the filtering API v2 is better.
> But I'm not confident it is a good API.
> If you have any concern, please discuss them. Because we need to discuss how
> to make a really generic API which fits with any filtering (flow steering) offload
> of any vendor while being descriptive enough and easy to use.
It's OK for me to use rte_eth_dev_filter_ctrl :)

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

* [PATCH v8 0/5] support E-tag offloading and forwarding on X550
  2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
                   ` (14 preceding siblings ...)
  2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
@ 2016-03-11  1:10 ` Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
                     ` (5 more replies)
  15 siblings, 6 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

This patch set adds the support of E-tag offloading and forwarding
on X550.
The offloading means E-tag can be inserted and stripped by HW.
And E-tag packets can be recognized and forwarded to specific pools
based on GRP and E-CID_base in E-tag.

E-tag is defined in IEEE802.1br. Please reference
http://www.ieee802.org/1/pages/802.1br.html.

v2:
- Add the introduction for E-tag.

v3:
- Add the hlep info for the new CLIs.
- Update the doc for testpmd.
- Update the E-tag insertion setting.

v4:
- Fix strippig is not working issue.
- Update the filter adding function. One filter for one tunnel entry.
- Update the release note to add some info about how to use this feature.

v5:
- Use macro for return value.
- Correct print info.

v6:
- Merge some rte ops.

v7:
- Squash the l2 tunnel filter ops to filter ctrl ops.

v8:
- Merge the rte_eth_l2_tunnel_type to rte_eth_tunnel_type.

Wenzhuo Lu (5):
  ixgbe: select pool by MAC when using double VLAN
  lib/librte_ether: support l2 tunnel operations
  ixgbe: support l2 tunnel operations
  app/testpmd: add CLIs for l2 tunnel config
  app/testpmd: add CLIs for E-tag operation

 app/test-pmd/cmdline.c                      | 702 +++++++++++++++++++++++++++-
 doc/guides/rel_notes/release_16_04.rst      |  21 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  37 ++
 drivers/net/ixgbe/ixgbe_ethdev.c            | 587 +++++++++++++++++++++++
 lib/librte_ether/rte_eth_ctrl.h             |  13 +
 lib/librte_ether/rte_ethdev.c               |  54 +++
 lib/librte_ether/rte_ethdev.h               |  75 +++
 lib/librte_ether/rte_ether_version.map      |   7 +
 8 files changed, 1495 insertions(+), 1 deletion(-)

-- 
1.9.3

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

* [PATCH v8 1/5] ixgbe: select pool by MAC when using double VLAN
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
@ 2016-03-11  1:10   ` Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

On X550, as required by datasheet, E-tag packets are not expected
when double VLAN are used. So modify the register PFVTCTL after
enabling double VLAN to select pool by MAC but not MAC or E-tag.

An introduction of E-tag:
It's defined in IEEE802.1br. Please reference this website,
http://www.ieee802.org/1/pages/802.1br.html.

A brief description.
E-tag means external tag, and it's a kind of l2 tunnel. It means a
tag will be inserted in the l2 header. Like below,
   |31            24|23           16|15         8|7           0|
  0|                   Destination MAC address                 |
  4|     Dest MAC address(cont.)    |     Src MAC address      |
  8|                  Source MAC address(cont.)                |
 12| E-tag Etherenet type (0x893f)  |      E-tag header        |
 16|                    E-tag header(cont.)                    |
 20|   VLAN Ethertype(optional)     |   VLAN header(optional)  |
 24|         Original type          |         ......           |
...|                              ......                       |
The E-tag format is like below,
   |0                    15|16   18|19 |20                   31|
   |   Ethertype - 0x893f  | E-PCP |DEI|   Ingress E-CID_base  |

   |32  33|34 35|36      47|48         55    |56             63|
   |  RSV | GRP |E-CID_base|Ingress_E-CID_ext|    E-CID_ext    |

The Ingess_E-CID_ext and E-CID_ext are always zero for endpoints
and are effectively reserved.

The more details of E-tag is in IEEE 802.1BR. 802.1BR is used to
replace 802.1Qbh. 802.1BR is a standard for Bridge Port Extension.
It specifies the operation of Bridge Port Extenders, including
management, protocols, and algorithms. Bridge Port Extenders
operate in support of the MAC Service by Extended Bridges.
The E-tag is added to l2 header to identify the VM channel and
the virtual port.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Tested-by: Yong Liu <yong.liu@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3e6fe86..b99e48e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -138,6 +138,8 @@
 
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
+#define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev);
@@ -1725,6 +1727,14 @@ ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
 	ctrl |= IXGBE_EXTENDED_VLAN;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl);
 
+	/* Clear pooling mode of PFVTCTL. It's required by X550. */
+	if (hw->mac.type == ixgbe_mac_X550 ||
+	    hw->mac.type == ixgbe_mac_X550EM_x) {
+		ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+		ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+	}
+
 	/*
 	 * VET EXT field in the EXVET register = 0x8100 by default
 	 * So no need to change. Same to VT field of DMATXCTL register
-- 
1.9.3

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

* [PATCH v8 2/5] lib/librte_ether: support l2 tunnel operations
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
@ 2016-03-11  1:10   ` Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 3/5] ixgbe: " Wenzhuo Lu
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

Add functions to support l2 tunnel configuration and operations.
1, L2 tunnel ether type modification.
   It means modifying the ether type of a specific type of tunnel.
   So the packet with this ether type will be parsed as this type
   of tunnel.
2, Enabling/disabling l2 tunnel support.
   It means enabling/disabling the ability of parsing the specific
   type of tunnel. This ability should be enabled before we enable
   filtering, forwarding, offloading for this specific type of
   tunnel.
3, Insertion and stripping for l2 tunnel tag.
4, Forwarding the packets to a pool based on l2 tunnel tag.

Only support e-tag tunnel now.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Tested-by: Yong Liu <yong.liu@intel.com>
---
 lib/librte_ether/rte_eth_ctrl.h        | 13 ++++++
 lib/librte_ether/rte_ethdev.c          | 54 ++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h          | 75 ++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 ++++
 4 files changed, 149 insertions(+)

diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index ce224ad..3c4920f 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -89,6 +89,7 @@ enum rte_filter_type {
 	RTE_ETH_FILTER_TUNNEL,
 	RTE_ETH_FILTER_FDIR,
 	RTE_ETH_FILTER_HASH,
+	RTE_ETH_FILTER_L2_TUNNEL,
 	RTE_ETH_FILTER_MAX
 };
 
@@ -244,6 +245,7 @@ enum rte_eth_tunnel_type {
 	RTE_TUNNEL_TYPE_GENEVE,
 	RTE_TUNNEL_TYPE_TEREDO,
 	RTE_TUNNEL_TYPE_NVGRE,
+	RTE_L2_TUNNEL_TYPE_E_TAG,
 	RTE_TUNNEL_TYPE_MAX,
 };
 
@@ -804,6 +806,17 @@ struct rte_eth_hash_filter_info {
 	} info;
 };
 
+/**
+ * l2 tunnel configuration.
+ */
+struct rte_eth_l2_tunnel_conf {
+	enum rte_eth_tunnel_type l2_tunnel_type;
+	uint16_t ether_type; /* ether type in l2 header */
+	uint32_t tunnel_id; /* port tag id for e-tag */
+	uint16_t vf_id; /* VF id for tag insertion */
+	uint32_t pool; /* destination pool for tag based forwarding */
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 756b234..84d4160 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3237,3 +3237,57 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
 	eth_dev->data->numa_node = pci_dev->numa_node;
 	eth_dev->data->drv_name = pci_dev->driver->name;
 }
+
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid tunnel type\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_eth_type_conf,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_eth_type_conf)(dev, l2_tunnel);
+}
+
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (l2_tunnel == NULL) {
+		RTE_PMD_DEBUG_TRACE("Invalid l2_tunnel parameter\n");
+		return -EINVAL;
+	}
+
+	if (l2_tunnel->l2_tunnel_type >= RTE_TUNNEL_TYPE_MAX) {
+		RTE_PMD_DEBUG_TRACE("Invalid tunnel type.\n");
+		return -EINVAL;
+	}
+
+	if (mask == 0) {
+		RTE_PMD_DEBUG_TRACE("Mask should have a value.\n");
+		return -EINVAL;
+	}
+
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->l2_tunnel_offload_set,
+				-ENOTSUP);
+	return (*dev->dev_ops->l2_tunnel_offload_set)(dev, l2_tunnel, mask, en);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 16da821..2008f1c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -957,6 +957,19 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 	} \
 } while (0)
 
+/**
+ * l2 tunnel configuration.
+ */
+
+/**< l2 tunnel enable mask */
+#define ETH_L2_TUNNEL_ENABLE_MASK       0x00000001
+/**< l2 tunnel insertion mask */
+#define ETH_L2_TUNNEL_INSERTION_MASK    0x00000002
+/**< l2 tunnel stripping mask */
+#define ETH_L2_TUNNEL_STRIPPING_MASK    0x00000004
+/**< l2 tunnel forwarding mask */
+#define ETH_L2_TUNNEL_FORWARDING_MASK   0x00000008
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1261,6 +1274,17 @@ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev,
 				struct rte_dev_eeprom_info *info);
 /**< @internal Program eeprom data  */
 
+typedef int (*eth_l2_tunnel_eth_type_conf_t)
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
+/**< @internal config l2 tunnel ether type */
+
+typedef int (*eth_l2_tunnel_offload_set_t)
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+/**< @internal enable/disable the l2 tunnel offload functions */
+
 #ifdef RTE_NIC_BYPASS
 
 enum {
@@ -1443,6 +1467,10 @@ struct eth_dev_ops {
 	eth_timesync_read_time timesync_read_time;
 	/** Set the device clock time. */
 	eth_timesync_write_time timesync_write_time;
+	/** Config ether type of l2 tunnel */
+	eth_l2_tunnel_eth_type_conf_t l2_tunnel_eth_type_conf;
+	/** Enable/disable l2 tunnel offload functions */
+	eth_l2_tunnel_offload_set_t l2_tunnel_offload_set;
 };
 
 /**
@@ -3880,6 +3908,53 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *eth_dev, const char *name,
 			 uint16_t queue_id, size_t size,
 			 unsigned align, int socket_id);
 
+ /**
+ * Config l2 tunnel ether type of an Ethernet device for filtering specific
+ * tunnel packets by ether type.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel configuration.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
+				    struct rte_eth_l2_tunnel_conf *l2_tunnel);
+
+ /**
+ * Enable/disable l2 tunnel offload functions. Include,
+ * 1, The ability of parsing a type of l2 tunnel of an Ethernet device.
+ *    Filtering, forwarding and offloading this type of tunnel packets depend on
+ *    this ability.
+ * 2, Stripping the l2 tunnel tag.
+ * 3, Insertion of the l2 tunnel tag.
+ * 4, Forwarding the packets based on the l2 tunnel tag.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param l2_tunnel
+ *   l2 tunnel parameters.
+ * @param mask
+ *   Indicate the offload function.
+ * @param en
+ *   Enable or disable this function.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_l2_tunnel_offload_set(uint8_t port_id,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel,
+				  uint32_t mask,
+				  uint8_t en);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index d8db24d..871221c 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -117,3 +117,10 @@ DPDK_2.2 {
 
 	local: *;
 };
+
+DPDK_16.04 {
+	global:
+
+	rte_eth_dev_l2_tunnel_eth_type_conf;
+	rte_eth_dev_l2_tunnel_offload_set;
+}DPDK_2.2;
-- 
1.9.3

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

* [PATCH v8 3/5] ixgbe: support l2 tunnel operations
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
@ 2016-03-11  1:10   ` Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

Add support of l2 tunnel configuration and operations.
1, Support modifying ether type of a type of l2 tunnel.
2, Support enabling and disabling the support of a type of l2 tunnel.
3, Support enabling/disabling l2 tunnel tag insertion/stripping.
4, Support enabling/disabling l2 tunnel packets forwarding.
5, Support adding/deleting forwarding rules for l2 tunnel packets.
Only support E-tag now.

Also update the release note.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Tested-by: Yong Liu <yong.liu@intel.com>
---
 doc/guides/rel_notes/release_16_04.rst |  21 ++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 577 +++++++++++++++++++++++++++++++++
 2 files changed, 598 insertions(+)

diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst
index eb1b3b2..994da33 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -44,6 +44,27 @@ This section should contain new features added in this release. Sample format:
   Add the offload and negotiation of checksum and TSO between vhost-user and
   vanilla Linux virtio guest.
 
+* **Added support for E-tag on X550.**
+
+  E-tag is defined in 802.1br. Please reference
+  http://www.ieee802.org/1/pages/802.1br.html.
+
+  This feature is for VF, but please aware all the setting is on PF. It means
+  the CLIs should be used on PF, but some of their effect will be shown on VF.
+  The forwarding of E-tag packets based on GRP and E-CID_base will have effect
+  on PF. Theoretically the E-tag packets can be forwarded to any pool/queue.
+  But normally we'd like to forward the packets to the pools/queues belonging
+  to the VFs. And E-tag insertion and stripping will have effect on VFs. When
+  VF receives E-tag packets, it should strip the E-tag. When VF transmits
+  packets, it should insert the E-tag. Both can be offloaded.
+
+  When we want to use this E-tag support feature, the forwarding should be
+  enabled to forward the packets received by PF to indicated VFs. And insertion
+  and stripping should be enabled for VFs to offload the effort to HW.
+
+  * Support E-tag offloading of insertion and stripping.
+  * Support Forwarding E-tag packets to pools based on
+    GRP and E-CID_base.
 
 Resolved Issues
 ---------------
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b99e48e..d82609c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -139,6 +139,17 @@
 #define IXGBE_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
 #define IXGBE_VT_CTL_POOLING_MODE_MASK         0x00030000
+#define IXGBE_VT_CTL_POOLING_MODE_ETAG         0x00010000
+#define DEFAULT_ETAG_ETYPE                     0x893f
+#define IXGBE_ETAG_ETYPE                       0x00005084
+#define IXGBE_ETAG_ETYPE_MASK                  0x0000ffff
+#define IXGBE_ETAG_ETYPE_VALID                 0x80000000
+#define IXGBE_RAH_ADTYPE                       0x40000000
+#define IXGBE_RAL_ETAG_FILTER_MASK             0x00003fff
+#define IXGBE_VMVIR_TAGA_MASK                  0x18000000
+#define IXGBE_VMVIR_TAGA_ETAG_INSERT           0x08000000
+#define IXGBE_VMTIR(_i) (0x00017000 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_QDE_STRIP_TAG                    0x00000004
 
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -339,6 +350,16 @@ static int ixgbe_timesync_read_time(struct rte_eth_dev *dev,
 				   struct timespec *timestamp);
 static int ixgbe_timesync_write_time(struct rte_eth_dev *dev,
 				   const struct timespec *timestamp);
+static int ixgbe_dev_l2_tunnel_eth_type_conf
+	(struct rte_eth_dev *dev, struct rte_eth_l2_tunnel_conf *l2_tunnel);
+static int ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en);
+static int ixgbe_dev_l2_tunnel_filter_handle(struct rte_eth_dev *dev,
+					     enum rte_filter_op filter_op,
+					     void *arg);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -497,6 +518,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.timesync_adjust_time = ixgbe_timesync_adjust_time,
 	.timesync_read_time   = ixgbe_timesync_read_time,
 	.timesync_write_time  = ixgbe_timesync_write_time,
+	.l2_tunnel_eth_type_conf = ixgbe_dev_l2_tunnel_eth_type_conf,
+	.l2_tunnel_offload_set   = ixgbe_dev_l2_tunnel_offload_set,
 };
 
 /*
@@ -5606,6 +5629,9 @@ ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
 	case RTE_ETH_FILTER_FDIR:
 		ret = ixgbe_fdir_ctrl_func(dev, filter_op, arg);
 		break;
+	case RTE_ETH_FILTER_L2_TUNNEL:
+		ret = ixgbe_dev_l2_tunnel_filter_handle(dev, filter_op, arg);
+		break;
 	default:
 		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
 							filter_type);
@@ -6201,6 +6227,557 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* Update e-tag ether type */
+static int
+ixgbe_update_e_tag_eth_type(struct ixgbe_hw *hw,
+			    uint16_t ether_type)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_MASK;
+	etag_etype |= ether_type;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Config l2 tunnel ether type */
+static int
+ixgbe_dev_l2_tunnel_eth_type_conf(struct rte_eth_dev *dev,
+				  struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_update_e_tag_eth_type(hw, l2_tunnel->ether_type);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable e-tag tunnel */
+static int
+ixgbe_e_tag_enable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype |= IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Enable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_enable(struct rte_eth_dev *dev,
+			   enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_enable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable e-tag tunnel */
+static int
+ixgbe_e_tag_disable(struct ixgbe_hw *hw)
+{
+	uint32_t etag_etype;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	etag_etype = IXGBE_READ_REG(hw, IXGBE_ETAG_ETYPE);
+	etag_etype &= ~IXGBE_ETAG_ETYPE_VALID;
+	IXGBE_WRITE_REG(hw, IXGBE_ETAG_ETYPE, etag_etype);
+	IXGBE_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+/* Disable l2 tunnel */
+static int
+ixgbe_dev_l2_tunnel_disable(struct rte_eth_dev *dev,
+			    enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_disable(hw);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_del(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		rar_low  = IXGBE_READ_REG(hw, IXGBE_RAL(i));
+		if ((rar_high & IXGBE_RAH_AV) &&
+		    (rar_high & IXGBE_RAH_ADTYPE) &&
+		    ((rar_low & IXGBE_RAL_ETAG_FILTER_MASK) ==
+		     l2_tunnel->tunnel_id)) {
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
+
+			ixgbe_clear_vmdq(hw, i, IXGBE_CLEAR_VMDQ_ALL);
+
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_filter_add(struct rte_eth_dev *dev,
+		       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t i, rar_entries;
+	uint32_t rar_low, rar_high;
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	/* One entry for one tunnel. Try to remove potential existing entry. */
+	ixgbe_e_tag_filter_del(dev, l2_tunnel);
+
+	rar_entries = ixgbe_get_num_rx_addrs(hw);
+
+	for (i = 1; i < rar_entries; i++) {
+		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(i));
+		if (rar_high & IXGBE_RAH_AV) {
+			continue;
+		} else {
+			ixgbe_set_vmdq(hw, i, l2_tunnel->pool);
+			rar_high = IXGBE_RAH_AV | IXGBE_RAH_ADTYPE;
+			rar_low = l2_tunnel->tunnel_id;
+
+			IXGBE_WRITE_REG(hw, IXGBE_RAL(i), rar_low);
+			IXGBE_WRITE_REG(hw, IXGBE_RAH(i), rar_high);
+
+			return ret;
+		}
+	}
+
+	PMD_INIT_LOG(NOTICE, "The table of E-tag forwarding rule is full."
+		     " Please remove a rule before adding a new one.");
+	return -EINVAL;
+}
+
+/* Add l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_add(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_add(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Delete l2 tunnel filter */
+static int
+ixgbe_dev_l2_tunnel_filter_del(struct rte_eth_dev *dev,
+			       struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_filter_del(dev, l2_tunnel);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * ixgbe_dev_l2_tunnel_filter_handle - Handle operations for l2 tunnel filter.
+ * @dev: pointer to rte_eth_dev structure
+ * @filter_op:operation will be taken.
+ * @arg: a pointer to specific structure corresponding to the filter_op
+ */
+static int
+ixgbe_dev_l2_tunnel_filter_handle(struct rte_eth_dev *dev,
+				  enum rte_filter_op filter_op,
+				  void *arg)
+{
+	int ret = 0;
+
+	if (filter_op == RTE_ETH_FILTER_NOP)
+		return 0;
+
+	if (arg == NULL) {
+		PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.",
+			    filter_op);
+		return -EINVAL;
+	}
+
+	switch (filter_op) {
+	case RTE_ETH_FILTER_ADD:
+		ret = ixgbe_dev_l2_tunnel_filter_add
+			(dev,
+			 (struct rte_eth_l2_tunnel_conf *)arg);
+		break;
+	case RTE_ETH_FILTER_DELETE:
+		ret = ixgbe_dev_l2_tunnel_filter_del
+			(dev,
+			 (struct rte_eth_l2_tunnel_conf *)arg);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int
+ixgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
+{
+	int ret = 0;
+	uint32_t ctrl;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	ctrl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+	ctrl &= ~IXGBE_VT_CTL_POOLING_MODE_MASK;
+	if (en)
+		ctrl |= IXGBE_VT_CTL_POOLING_MODE_ETAG;
+	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, ctrl);
+
+	return ret;
+}
+
+/* Enable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel forwarding */
+static int
+ixgbe_dev_l2_tunnel_forwarding_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_forwarding_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_insertion_en_dis(struct rte_eth_dev *dev,
+			     struct rte_eth_l2_tunnel_conf *l2_tunnel,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t vmtir, vmvir;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (l2_tunnel->vf_id >= dev->pci_dev->max_vfs) {
+		PMD_DRV_LOG(ERR,
+			    "VF id %u should be less than %u",
+			    l2_tunnel->vf_id,
+			    dev->pci_dev->max_vfs);
+		return -EINVAL;
+	}
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	if (en)
+		vmtir = l2_tunnel->tunnel_id;
+	else
+		vmtir = 0;
+
+	IXGBE_WRITE_REG(hw, IXGBE_VMTIR(l2_tunnel->vf_id), vmtir);
+
+	vmvir = IXGBE_READ_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id));
+	vmvir &= ~IXGBE_VMVIR_TAGA_MASK;
+	if (en)
+		vmvir |= IXGBE_VMVIR_TAGA_ETAG_INSERT;
+	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(l2_tunnel->vf_id), vmvir);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_enable(struct rte_eth_dev *dev,
+				     struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag insertion */
+static int
+ixgbe_dev_l2_tunnel_insertion_disable
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel)
+{
+	int ret = 0;
+
+	switch (l2_tunnel->l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_insertion_en_dis(dev, l2_tunnel, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+ixgbe_e_tag_stripping_en_dis(struct rte_eth_dev *dev,
+			     bool en)
+{
+	int ret = 0;
+	uint32_t qde;
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x) {
+		return -ENOTSUP;
+	}
+
+	qde = IXGBE_READ_REG(hw, IXGBE_QDE);
+	if (en)
+		qde |= IXGBE_QDE_STRIP_TAG;
+	else
+		qde &= ~IXGBE_QDE_STRIP_TAG;
+	qde &= ~IXGBE_QDE_READ;
+	qde |= IXGBE_QDE_WRITE;
+	IXGBE_WRITE_REG(hw, IXGBE_QDE, qde);
+
+	return ret;
+}
+
+/* Enable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_enable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 1);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Disable l2 tunnel tag stripping */
+static int
+ixgbe_dev_l2_tunnel_stripping_disable
+	(struct rte_eth_dev *dev,
+	 enum rte_eth_tunnel_type l2_tunnel_type)
+{
+	int ret = 0;
+
+	switch (l2_tunnel_type) {
+	case RTE_L2_TUNNEL_TYPE_E_TAG:
+		ret = ixgbe_e_tag_stripping_en_dis(dev, 0);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid tunnel type");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Enable/disable l2 tunnel offload functions */
+static int
+ixgbe_dev_l2_tunnel_offload_set
+	(struct rte_eth_dev *dev,
+	 struct rte_eth_l2_tunnel_conf *l2_tunnel,
+	 uint32_t mask,
+	 uint8_t en)
+{
+	int ret = 0;
+
+	if (l2_tunnel == NULL)
+		return -EINVAL;
+
+	ret = -EINVAL;
+	if (mask & ETH_L2_TUNNEL_ENABLE_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_INSERTION_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_insertion_enable(
+				dev,
+				l2_tunnel);
+		else
+			ret = ixgbe_dev_l2_tunnel_insertion_disable(
+				dev,
+				l2_tunnel);
+	}
+
+	if (mask & ETH_L2_TUNNEL_STRIPPING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_stripping_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_stripping_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	if (mask & ETH_L2_TUNNEL_FORWARDING_MASK) {
+		if (en)
+			ret = ixgbe_dev_l2_tunnel_forwarding_enable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+		else
+			ret = ixgbe_dev_l2_tunnel_forwarding_disable(
+				dev,
+				l2_tunnel->l2_tunnel_type);
+	}
+
+	return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
-- 
1.9.3

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

* [PATCH v8 4/5] app/testpmd: add CLIs for l2 tunnel config
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
                     ` (2 preceding siblings ...)
  2016-03-11  1:10   ` [PATCH v8 3/5] ixgbe: " Wenzhuo Lu
@ 2016-03-11  1:10   ` Wenzhuo Lu
  2016-03-11  1:10   ` [PATCH v8 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
  2016-03-11 22:27   ` [PATCH v8 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

Add CLIs to config ether type of l2 tunnel, and to enable/disable
a type of l2 tunnel.
Now only e-tag tunnel is supported.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Tested-by: Yong Liu <yong.liu@intel.com>
---
 app/test-pmd/cmdline.c                      | 278 +++++++++++++++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  11 ++
 2 files changed, 288 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 52e9f5f..0c16305 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -572,7 +572,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
 			"    Start/stop a rx/tx queue of port X. Only take effect"
-			" when port X is started\n"
+			" when port X is started\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag ether-type"
+			" (value)\n"
+			"    Set the value of E-tag ether-type.\n\n"
+
+			"port config (port_id|all) l2-tunnel E-tag"
+			" (enable|disable)\n"
+			"    Enable/disable the E-tag support.\n\n"
 		);
 	}
 
@@ -9632,6 +9640,270 @@ cmdline_parse_inst_t cmd_mcast_addr = {
 	},
 };
 
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t eth_type;
+	uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_eth_type_result,
+		 eth_type_val, UINT16);
+
+static uint32_t
+str2fdir_l2_tunnel_type(char *string)
+{
+	uint32_t i = 0;
+
+	static const struct {
+		char str[32];
+		uint32_t type;
+	} l2_tunnel_type_str[] = {
+		{"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+	};
+
+	for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+		if (!strcmp(l2_tunnel_type_str[i].str, string))
+			return l2_tunnel_type_str[i].type;
+	}
+	return RTE_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+	(void *parsed_result,
+	 __attribute__((unused)) struct cmdline *cl,
+	 __attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	portid_t pid;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+	.f = cmd_config_l2_tunnel_eth_type_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_all_str,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_eth_type_result *res =
+		 parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+	entry.ether_type = res->eth_type_val;
+
+	rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+	.f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel ether-type",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_eth_type_port,
+		(void *)&cmd_config_l2_tunnel_eth_type_config,
+		(void *)&cmd_config_l2_tunnel_eth_type_id,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+		(void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+		NULL,
+	},
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t config;
+	cmdline_fixed_string_t all;
+	uint8_t id;
+	cmdline_fixed_string_t l2_tunnel;
+	cmdline_fixed_string_t l2_tunnel_type;
+	cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_l2_tunnel_en_dis_result,
+		 en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	portid_t pid;
+	uint8_t en;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		en = 1;
+	else
+		en = 0;
+
+	FOREACH_PORT(pid, ports) {
+		rte_eth_dev_l2_tunnel_offload_set(pid,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  en);
+	}
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+	.f = cmd_config_l2_tunnel_en_dis_all_parsed,
+	.data = NULL,
+	.help_str = "port config all l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_all_str,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_l2_tunnel_en_dis_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+	if (!strcmp("enable", res->en_dis))
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set(res->id,
+						  &entry,
+						  ETH_L2_TUNNEL_ENABLE_MASK,
+						  0);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+	.f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+	.data = NULL,
+	.help_str = "port config l2-tunnel enable/disable",
+	.tokens = {
+		(void *)&cmd_config_l2_tunnel_en_dis_port,
+		(void *)&cmd_config_l2_tunnel_en_dis_config,
+		(void *)&cmd_config_l2_tunnel_en_dis_id,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+		(void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+		(void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -9773,6 +10045,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_hash_input_set,
 	(cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
 	(cmdline_parse_inst_t *)&cmd_mcast_addr,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a520cc5..5471ebe 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1268,6 +1268,17 @@ Where the threshold type can be:
 
 These threshold options are also available from the command-line.
 
+port config - E-tag
+~~~~~~~~~~~~~~~~~~~
+
+Set the value of ether-type for E-tag::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag ether-type (value)
+
+Enable/disable the E-tag support::
+
+   testpmd> port config (port_id|all) l2-tunnel E-tag (enable|disable)
+
 
 Link Bonding Functions
 ----------------------
-- 
1.9.3

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

* [PATCH v8 5/5] app/testpmd: add CLIs for E-tag operation
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
                     ` (3 preceding siblings ...)
  2016-03-11  1:10   ` [PATCH v8 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
@ 2016-03-11  1:10   ` Wenzhuo Lu
  2016-03-11 22:27   ` [PATCH v8 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
  5 siblings, 0 replies; 95+ messages in thread
From: Wenzhuo Lu @ 2016-03-11  1:10 UTC (permalink / raw)
  To: dev

Add the CLIs to support the E-tag operation.
1, Offloading of E-tag insertion and stripping.
2, Forwarding the E-tag packets to pools based on the GRP and E-CID_base.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Tested-by: Yong Liu <yong.liu@intel.com>
---
 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  26 ++
 2 files changed, 450 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0c16305..4361116 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -502,6 +502,27 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set link-down port (port_id)\n"
 			"	Set link down for a port.\n\n"
 
+			"E-tag set insertion on port-tag-id (value)"
+			" port (port_id) vf (vf_id)\n"
+			"    Enable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set insertion off port (port_id) vf (vf_id)\n"
+			"    Disable E-tag insertion for a VF on a port\n\n"
+
+			"E-tag set stripping (on|off) port (port_id)\n"
+			"    Enable/disable E-tag stripping on a port\n\n"
+
+			"E-tag set forwarding (on|off) port (port_id)\n"
+			"    Enable/disable E-tag based forwarding"
+			" on a port\n\n"
+
+			"E-tag set filter add e-tag-id (value) dst-pool"
+			" (pool_id) port (port_id)\n"
+			"    Add an E-tag forwarding filter on a port\n\n"
+
+			"E-tag set filter del e-tag-id (value) port (port_id)\n"
+			"    Delete an E-tag forwarding filter on a port\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -9904,6 +9925,403 @@ cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
 	},
 };
 
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+	cmdline_fixed_string_t e_tag;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t insertion;
+	cmdline_fixed_string_t stripping;
+	cmdline_fixed_string_t forwarding;
+	cmdline_fixed_string_t filter;
+	cmdline_fixed_string_t add;
+	cmdline_fixed_string_t del;
+	cmdline_fixed_string_t on;
+	cmdline_fixed_string_t off;
+	cmdline_fixed_string_t on_off;
+	cmdline_fixed_string_t port_tag_id;
+	uint32_t port_tag_id_val;
+	cmdline_fixed_string_t e_tag_id;
+	uint16_t e_tag_id_val;
+	cmdline_fixed_string_t dst_pool;
+	uint8_t dst_pool_val;
+	cmdline_fixed_string_t port;
+	uint8_t port_id;
+	cmdline_fixed_string_t vf;
+	uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+	TOKEN_STRING_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+	TOKEN_NUM_INITIALIZER
+		(struct cmd_config_e_tag_result,
+		 vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->port_tag_id_val;
+	entry.vf_id = res->vf_id;
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  1);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.vf_id = res->vf_id;
+
+	rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+					  &entry,
+					  ETH_L2_TUNNEL_INSERTION_MASK,
+					  0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+	.f = cmd_config_e_tag_insertion_en_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion enable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_on,
+		(void *)&cmd_config_e_tag_port_tag_id,
+		(void *)&cmd_config_e_tag_port_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+	.f = cmd_config_e_tag_insertion_dis_parsed,
+	.data = NULL,
+	.help_str = "E-tag insertion disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_insertion,
+		(void *)&cmd_config_e_tag_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		(void *)&cmd_config_e_tag_vf,
+		(void *)&cmd_config_e_tag_vf_id,
+		NULL,
+	},
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res =
+		parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_STRIPPING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+	.f = cmd_config_e_tag_stripping_parsed,
+	.data = NULL,
+	.help_str = "E-tag stripping enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_stripping,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+	if (!strcmp(res->on_off, "on"))
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 1);
+	else
+		rte_eth_dev_l2_tunnel_offload_set
+			(res->port_id,
+			 &entry,
+			 ETH_L2_TUNNEL_FORWARDING_MASK,
+			 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+	.f = cmd_config_e_tag_forwarding_parsed,
+	.data = NULL,
+	.help_str = "E-tag forwarding enable/disable",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_forwarding,
+		(void *)&cmd_config_e_tag_on_off,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be equal or less than 0x3fff.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_filter_supported(res->port_id,
+					   RTE_ETH_FILTER_L2_TUNNEL);
+	if (ret < 0) {
+		printf("E-tag filter is not supported on port %u.\n",
+		       res->port_id);
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+	entry.pool = res->dst_pool_val;
+
+	ret = rte_eth_dev_filter_ctrl(res->port_id,
+				      RTE_ETH_FILTER_L2_TUNNEL,
+				      RTE_ETH_FILTER_ADD,
+				      &entry);
+	if (ret < 0)
+		printf("E-tag filter programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+	.f = cmd_config_e_tag_filter_add_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter add",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_add,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_dst_pool,
+		(void *)&cmd_config_e_tag_dst_pool_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_config_e_tag_result *res = parsed_result;
+	struct rte_eth_l2_tunnel_conf entry;
+	int ret = 0;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (res->e_tag_id_val > 0x3fff) {
+		printf("e-tag-id must be less than 0x3fff.\n");
+		return;
+	}
+
+	ret = rte_eth_dev_filter_supported(res->port_id,
+					   RTE_ETH_FILTER_L2_TUNNEL);
+	if (ret < 0) {
+		printf("E-tag filter is not supported on port %u.\n",
+		       res->port_id);
+		return;
+	}
+
+	entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+	entry.tunnel_id = res->e_tag_id_val;
+
+	ret = rte_eth_dev_filter_ctrl(res->port_id,
+				      RTE_ETH_FILTER_L2_TUNNEL,
+				      RTE_ETH_FILTER_DELETE,
+				      &entry);
+	if (ret < 0)
+		printf("E-tag filter programming error: (%s)\n",
+		       strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+	.f = cmd_config_e_tag_filter_del_parsed,
+	.data = NULL,
+	.help_str = "E-tag filter delete",
+	.tokens = {
+		(void *)&cmd_config_e_tag_e_tag,
+		(void *)&cmd_config_e_tag_set,
+		(void *)&cmd_config_e_tag_filter,
+		(void *)&cmd_config_e_tag_del,
+		(void *)&cmd_config_e_tag_e_tag_id,
+		(void *)&cmd_config_e_tag_e_tag_id_val,
+		(void *)&cmd_config_e_tag_port,
+		(void *)&cmd_config_e_tag_port_id,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -10049,6 +10467,12 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
 	(cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+	(cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5471ebe..e116d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -917,6 +917,32 @@ Set link down for a port::
 
    testpmd> set link-down port (port id)
 
+E-tag set
+~~~~~~~~~
+
+Enable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion on port-tag-id (value) port (port_id) vf (vf_id)
+
+Disable E-tag insertion for a VF on a port::
+
+   testpmd> E-tag set insertion off port (port_id) vf (vf_id)
+
+Enable/disable E-tag stripping on a port::
+
+   testpmd> E-tag set stripping (on|off) port (port_id)
+
+Enable/disable E-tag based forwarding on a port::
+
+   testpmd> E-tag set forwarding (on|off) port (port_id)
+
+Add an E-tag forwarding filter on a port::
+
+   testpmd> E-tag set filter add e-tag-id (value) dst-pool (pool_id) port (port_id)
+
+Delete an E-tag forwarding filter on a port::
+   testpmd> E-tag set filter del e-tag-id (value) port (port_id)
+
 
 Port Functions
 --------------
-- 
1.9.3

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

* Re: [PATCH v8 0/5] support E-tag offloading and forwarding on X550
  2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
                     ` (4 preceding siblings ...)
  2016-03-11  1:10   ` [PATCH v8 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
@ 2016-03-11 22:27   ` Thomas Monjalon
  5 siblings, 0 replies; 95+ messages in thread
From: Thomas Monjalon @ 2016-03-11 22:27 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev

2016-03-11 09:10, Wenzhuo Lu:
> This patch set adds the support of E-tag offloading and forwarding
> on X550.
> The offloading means E-tag can be inserted and stripped by HW.
> And E-tag packets can be recognized and forwarded to specific pools
> based on GRP and E-CID_base in E-tag.
> 
> E-tag is defined in IEEE802.1br. Please reference
> http://www.ieee802.org/1/pages/802.1br.html.

Applied, thanks

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

end of thread, other threads:[~2016-03-11 22:29 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-29  7:03 [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 1/8] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 2/8] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 3/8] ixgbe: " Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 4/8] app/testpmd: add CLIs for " Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 5/8] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 6/8] ixgbe: support " Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 7/8] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-01-29  7:03 ` [PATCH 8/8] doc: add release note for E-tag Wenzhuo Lu
2016-02-01 16:15   ` Mcnamara, John
2016-01-29  7:16 ` [PATCH 0/8] support E-tag offloading and forwarding on Intel X550 NIC Qiu, Michael
2016-02-01  1:04   ` Lu, Wenzhuo
2016-02-01  1:39     ` Yuanhan Liu
2016-02-01  1:56       ` Lu, Wenzhuo
2016-02-01  2:06         ` Yuanhan Liu
2016-02-01  3:00           ` Lu, Wenzhuo
2016-02-01  8:31       ` Qiu, Michael
2016-02-02  1:24         ` Lu, Wenzhuo
2016-02-02  6:56 ` [PATCH v2 0/7] " Wenzhuo Lu
2016-02-02  6:56   ` [PATCH v2 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-02-02  6:57   ` [PATCH v2 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
2016-02-02 12:03     ` Bruce Richardson
2016-02-03  1:05       ` Lu, Wenzhuo
2016-02-03  3:36     ` Stephen Hemminger
2016-02-03  8:08       ` Lu, Wenzhuo
2016-02-02  6:57   ` [PATCH v2 3/7] ixgbe: " Wenzhuo Lu
2016-02-02  6:57   ` [PATCH v2 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
2016-02-02  6:57   ` [PATCH v2 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
2016-02-02  6:57   ` [PATCH v2 6/7] ixgbe: support " Wenzhuo Lu
2016-02-02  6:57   ` [PATCH v2 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-02-12 13:50   ` [PATCH v2 0/7] support E-tag offloading and forwarding on Intel X550 NIC De Lara Guarch, Pablo
2016-02-15  1:21     ` Lu, Wenzhuo
2016-02-15  9:39       ` De Lara Guarch, Pablo
2016-02-16  8:20 ` [PATCH v3 " Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 3/7] ixgbe: " Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 6/7] ixgbe: support " Wenzhuo Lu
2016-02-16  8:20   ` [PATCH v3 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-02-18  2:46 ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Wenzhuo Lu
2016-02-18  2:46   ` [PATCH v4 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-02-18  2:46   ` [PATCH v4 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
2016-02-18  2:46   ` [PATCH v4 3/7] ixgbe: " Wenzhuo Lu
2016-03-04  1:47     ` He, Shaopeng
2016-03-04  3:17       ` Lu, Wenzhuo
2016-02-18  2:46   ` [PATCH v4 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
2016-02-18  2:46   ` [PATCH v4 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
2016-03-04  1:47     ` He, Shaopeng
2016-03-04  3:31       ` Lu, Wenzhuo
2016-03-07  2:04         ` He, Shaopeng
2016-02-18  2:46   ` [PATCH v4 6/7] ixgbe: support " Wenzhuo Lu
2016-03-04  1:46     ` He, Shaopeng
2016-03-04  3:15       ` Lu, Wenzhuo
2016-02-18  2:46   ` [PATCH v4 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-03-04  1:46     ` He, Shaopeng
2016-03-04  3:11       ` Lu, Wenzhuo
2016-03-04  9:23   ` [PATCH v4 0/7] support E-tag offloading and forwarding on Intel X550 NIC Liu, Yong
2016-03-07  2:42 ` [PATCH v5 0/7] support E-tag offloading and forwarding on X550 Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 1/7] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 2/7] lib/librte_ether: support l2 tunnel config Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 3/7] ixgbe: " Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 4/7] app/testpmd: add CLIs for " Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 5/7] lib/librte_ether: support new l2 tunnel operation Wenzhuo Lu
2016-03-07  3:29     ` Wu, Jingjing
2016-03-07  5:29       ` Lu, Wenzhuo
2016-03-07  2:42   ` [PATCH v5 6/7] ixgbe: support " Wenzhuo Lu
2016-03-07  2:42   ` [PATCH v5 7/7] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-03-08  6:53 ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wenzhuo Lu
2016-03-08  6:53   ` [PATCH v6 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-03-08  6:53   ` [PATCH v6 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
2016-03-09  0:14     ` Thomas Monjalon
2016-03-09  1:15       ` Lu, Wenzhuo
2016-03-09  9:27         ` Thomas Monjalon
2016-03-10  0:54           ` Lu, Wenzhuo
2016-03-08  6:53   ` [PATCH v6 3/5] ixgbe: " Wenzhuo Lu
2016-03-08  6:53   ` [PATCH v6 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
2016-03-08  6:53   ` [PATCH v6 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-03-08  8:08   ` [PATCH v6 0/5] support E-tag offloading and forwarding on X550 Wu, Jingjing
2016-03-09  7:44 ` [PATCH v7 " Wenzhuo Lu
2016-03-09  7:44   ` [PATCH v7 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-03-09  7:44   ` [PATCH v7 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
2016-03-09  7:44   ` [PATCH v7 3/5] ixgbe: " Wenzhuo Lu
2016-03-09  7:44   ` [PATCH v7 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
2016-03-09  7:44   ` [PATCH v7 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-03-09 10:07   ` [PATCH v7 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon
2016-03-10  0:44     ` Lu, Wenzhuo
2016-03-11  1:10 ` [PATCH v8 " Wenzhuo Lu
2016-03-11  1:10   ` [PATCH v8 1/5] ixgbe: select pool by MAC when using double VLAN Wenzhuo Lu
2016-03-11  1:10   ` [PATCH v8 2/5] lib/librte_ether: support l2 tunnel operations Wenzhuo Lu
2016-03-11  1:10   ` [PATCH v8 3/5] ixgbe: " Wenzhuo Lu
2016-03-11  1:10   ` [PATCH v8 4/5] app/testpmd: add CLIs for l2 tunnel config Wenzhuo Lu
2016-03-11  1:10   ` [PATCH v8 5/5] app/testpmd: add CLIs for E-tag operation Wenzhuo Lu
2016-03-11 22:27   ` [PATCH v8 0/5] support E-tag offloading and forwarding on X550 Thomas Monjalon

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.