[dpdk-dev,v6,2/5] lib/librte_ether: support l2 tunnel operations

Message ID 1457420017-15345-3-git-send-email-wenzhuo.lu@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Commit Message

Wenzhuo Lu March 8, 2016, 6:53 a.m. UTC
  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(+)
  

Comments

Thomas Monjalon March 9, 2016, 12:14 a.m. UTC | #1
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.
  
Wenzhuo Lu March 9, 2016, 1:15 a.m. UTC | #2
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.
  
Thomas Monjalon March 9, 2016, 9:27 a.m. UTC | #3
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.
  
Wenzhuo Lu March 10, 2016, 12:54 a.m. UTC | #4
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 :)
  

Patch

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: *;
 };