[dpdk-dev,v2,3/7] rte_ether:add API of VxLAN packet filter in librte_ether

Message ID 1409038294-21693-4-git-send-email-jijiang.liu@intel.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

Jijiang Liu Aug. 26, 2014, 7:31 a.m. UTC
  VxLAN packet filters, which use MAC and VLAN to point
   to a queue. The filter types supported are listed below:
   1. Inner MAC and Inner VLAN ID
   2. Inner MAC address, inner VLAN ID and tenant ID.
   3. Inner MAC and tenant ID
   4. Inner MAC address
   5. Outer MAC address, tenant ID and inner MAC

Signed-off-by: jijiangl <jijiang.liu@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Acked-by: Jing Chen <jing.d.chen@intel.com>

---
 lib/librte_ether/rte_ethdev.c |   50 ++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h |   72 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+), 0 deletions(-)
  

Comments

Thomas Monjalon Aug. 27, 2014, 3:12 p.m. UTC | #1
2014-08-26 15:31, Jijiang Liu:
> +enum rte_tunnel_filter_type {
> +	RTE_TUNNEL_FILTER_TYPE_NONE = 0,
> +	RTE_TUNNEL_FILTER_IMAC_IVLAN, /**< Filter by inner MAC and VLAN ID. */
> +	RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID,
> +	/**< Filter by inner MAC address and VLAN ID, tenned ID. */
> +	RTE_TUNNEL_FILTER_IMAC_TENID, /**< Filter by inner MAC and tenant ID. */
> +	RTE_TUNNEL_FILTER_IMAC, /**< Filter by inner MAC address */
> +	RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,
> +	/**< Filter by outer MAC address, tenant ID and Inner MAC */
> +	RTE_TUNNEL_FILTER_TYPE_MAX,
> +};
[...]
>  /**
> + * Tunnel Packet filter configuration.
> + */
> +struct rte_eth_tunnel_filter_conf {
> +	struct ether_addr *outer_mac;  /**< Outer MAC address fiter. */
> +	struct ether_addr *inner_mac;  /**< Inner MAC address fiter. */
> +	uint16_t inner_vlan;           /**< Inner VLAN fiter. */
> +	enum rte_tunnel_iptype ip_type; /**< IP address type. */
> +	union {
> +		uint32_t ipv4_addr;    /**< IPv4 source address to match. */
> +		uint32_t ipv6_addr[4]; /**< IPv6 source address to match. */
> +	} ip_addr; /**< IPv4/IPv6 source address to match (union of above). */
> +
> +	uint8_t filter_type;           /**< Filter type. */
> +	uint8_t to_queue;              /**< Use MAC and VLAN to point to a queue. */
> +	enum rte_eth_tunnel_type tunnel_type; /**< Tunnel Type. */
> +	uint32_t tenant_id;            /** < Tenant number. */
> +	uint16_t queue_id;             /** < queue number. */
> +};
[...]
> +typedef int (*eth_tunnel_filter_set_t)(struct rte_eth_dev *dev,
> +				      struct rte_eth_tunnel_filter_conf *tunnel_filter,
> +				      uint8_t filter_count, uint8_t add);
> +/**< @internal Set tunnel filter */
[...]
> + /**
> + * Add tunnel filter configuration of Ethernet device
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param tunnel_filter
> + *   Where to store the current Tunneling UDP configuration
> + *   of the Ethernet device.
> + * @param filter_count
> + *   How many filters are going to added.
> + * @param add
> + *   0: remove tunnel filter
> + *   1: add tunnel filter
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if port identifier is invalid.
> + *   - (-EINVAL) if bad parameter.
> + *   - (-ENOTSUP) if hardware doesn't support tunnel type.
> + */
> +int
> +rte_eth_dev_tunnel_filter_set(uint8_t port_id,
> +			struct rte_eth_tunnel_filter_conf *tunnel_filter,
> +			uint8_t filter_count, uint8_t add);

I wonder if we could use a common function to set all kind of filters?

Thoughts are welcome.
  
Jijiang Liu Aug. 28, 2014, 12:55 a.m. UTC | #2
> -----Original Message-----

> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]

> Sent: Wednesday, August 27, 2014 11:12 PM

> To: Liu, Jijiang

> Cc: dev@dpdk.org

> Subject: Re: [dpdk-dev] [PATCH v2 3/7]rte_ether:add API of VxLAN packet filter

> in librte_ether

> 

> 2014-08-26 15:31, Jijiang Liu:

> > +enum rte_tunnel_filter_type {

> > +	RTE_TUNNEL_FILTER_TYPE_NONE = 0,

> > +	RTE_TUNNEL_FILTER_IMAC_IVLAN, /**< Filter by inner MAC and VLAN ID.

> */

> > +	RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID,

> > +	/**< Filter by inner MAC address and VLAN ID, tenned ID. */

> > +	RTE_TUNNEL_FILTER_IMAC_TENID, /**< Filter by inner MAC and tenant

> ID. */

> > +	RTE_TUNNEL_FILTER_IMAC, /**< Filter by inner MAC address */

> > +	RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,

> > +	/**< Filter by outer MAC address, tenant ID and Inner MAC */

> > +	RTE_TUNNEL_FILTER_TYPE_MAX,

> > +};

> [...]

> >  /**

> > + * Tunnel Packet filter configuration.

> > + */

> > +struct rte_eth_tunnel_filter_conf {

> > +	struct ether_addr *outer_mac;  /**< Outer MAC address fiter. */

> > +	struct ether_addr *inner_mac;  /**< Inner MAC address fiter. */

> > +	uint16_t inner_vlan;           /**< Inner VLAN fiter. */

> > +	enum rte_tunnel_iptype ip_type; /**< IP address type. */

> > +	union {

> > +		uint32_t ipv4_addr;    /**< IPv4 source address to match. */

> > +		uint32_t ipv6_addr[4]; /**< IPv6 source address to match. */

> > +	} ip_addr; /**< IPv4/IPv6 source address to match (union of above).

> > +*/

> > +

> > +	uint8_t filter_type;           /**< Filter type. */

> > +	uint8_t to_queue;              /**< Use MAC and VLAN to point to a

> queue. */

> > +	enum rte_eth_tunnel_type tunnel_type; /**< Tunnel Type. */

> > +	uint32_t tenant_id;            /** < Tenant number. */

> > +	uint16_t queue_id;             /** < queue number. */

> > +};

> [...]

> > +typedef int (*eth_tunnel_filter_set_t)(struct rte_eth_dev *dev,

> > +				      struct rte_eth_tunnel_filter_conf *tunnel_filter,

> > +				      uint8_t filter_count, uint8_t add); /**< @internal

> Set

> > +tunnel filter */

> [...]

> > + /**

> > + * Add tunnel filter configuration of Ethernet device

> > + *

> > + * @param port_id

> > + *   The port identifier of the Ethernet device.

> > + * @param tunnel_filter

> > + *   Where to store the current Tunneling UDP configuration

> > + *   of the Ethernet device.

> > + * @param filter_count

> > + *   How many filters are going to added.

> > + * @param add

> > + *   0: remove tunnel filter

> > + *   1: add tunnel filter

> > + *

> > + * @return

> > + *   - (0) if successful.

> > + *   - (-ENODEV) if port identifier is invalid.

> > + *   - (-EINVAL) if bad parameter.

> > + *   - (-ENOTSUP) if hardware doesn't support tunnel type.

> > + */

> > +int

> > +rte_eth_dev_tunnel_filter_set(uint8_t port_id,

> > +			struct rte_eth_tunnel_filter_conf *tunnel_filter,

> > +			uint8_t filter_count, uint8_t add);

> 

> I wonder if we could use a common function to set all kind of filters?

> 

> Thoughts are welcome.

> 

> --

> Thomas


The rte_eth_dev_tunnel_filter_set() is a common filter function for tunneling packet, which can set all kind of filters.
But now I just implemented and tested VxLAN tunneling packet in this function, another tunneling packets support will be here later.
Look at the structure definition, which support another tunneling types. 
struct rte_eth_tunnel_filter_conf {
    ...
    enum rte_eth_tunnel_type tunnel_type; /**< Tunnel Type. */
    ...
}
--
Jijiang Liu
  
Thomas Monjalon Aug. 28, 2014, 8:36 a.m. UTC | #3
2014-08-28 00:55, Liu, Jijiang:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > I wonder if we could use a common function to set all kind of filters?
> > 
> > Thoughts are welcome.
> 
> The rte_eth_dev_tunnel_filter_set() is a common filter function for
> tunneling packet, which can set all kind of filters.

I understand that. But my question was: could we have common functions for
tunnel filters and (existing) generic filters?
  
Jijiang Liu Aug. 28, 2014, 11:02 a.m. UTC | #4
Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, August 28, 2014 4:37 PM
> To: Liu, Jijiang
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 3/7]rte_ether:add API of VxLAN packet filter
> in librte_ether
> 
> 2014-08-28 00:55, Liu, Jijiang:
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > I wonder if we could use a common function to set all kind of filters?
> > >
> > > Thoughts are welcome.
> >
> > The rte_eth_dev_tunnel_filter_set() is a common filter function for
> > tunneling packet, which can set all kind of filters.
> 
> I understand that. But my question was: could we have common functions for
> tunnel filters and (existing) generic filters?
> 
> --
> Thomas
Tunneling packet is encapsulated format, in order to extend another tunneling type support and distinguish between tunneling and non-tunneling packet,
we had better provide independent common filter API. 
The existing generic filter function is related to normal L2 packet filter(non-tunneling packet). If there are two kind of filter APIs, one is for normal L2 packet, 
other is for tunneling packet, which will make user more clear when and how to use them.  

Thanks
Jijiang Liu
  
Thomas Monjalon Aug. 28, 2014, 12:31 p.m. UTC | #5
2014-08-28 11:02, Liu, Jijiang:
> From: Thomas Monjalon
> > 2014-08-28 00:55, Liu, Jijiang:
> > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > > I wonder if we could use a common function to set all kind of filters?
> > > >
> > > > Thoughts are welcome.
> > >
> > > The rte_eth_dev_tunnel_filter_set() is a common filter function for
> > > tunneling packet, which can set all kind of filters.
> > 
> > I understand that. But my question was: could we have common functions for
> > tunnel filters and (existing) generic filters?
> 
> Tunneling packet is encapsulated format, in order to extend another
> tunneling type support and distinguish between tunneling and non-tunneling
> packet, we had better provide independent common filter API. 
> The existing generic filter function is related to normal L2 packet
> filter(non-tunneling packet). If there are two kind of filter APIs, one is
> for normal L2 packet, other is for tunneling packet, which will make user
> more clear when and how to use them.

So I ask wether it is possible to merge 2 functions and you answer they are
different functions. I know they are different.
I don't see why you can merge all different tunnels filtering in one function
and not merge them with other L2 filters type?

Should we wait that someone suggest a new API for HTTP filtering (for a new
shiny NIC) to think about how all filters could be configured through a common
API?
We already have flow director, syn filter, ethertype filter, 2-tuple filter,
5-tuple filter, flex filter and you want to add tunnel filter.
Last time, filters was called "generic filter" and I asked to think about how
it was generic:
	http://dpdk.org/ml/archives/dev/2014-May/002859.html
As I suspected, same story restart.

I want these new i40e features as much as you. But it's not responsible to
let API becoming a mess like that.
All these filters must be reworked (including flow director).
  

Patch

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 325edb1..d941d86 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1955,6 +1955,56 @@  rte_eth_dev_udp_tunnel_delete(uint8_t port_id,
 }
 
 int
+rte_eth_dev_tunnel_filter_set(uint8_t port_id,
+			 struct rte_eth_tunnel_filter_conf *tunnel_filter,
+			 uint8_t filter_count, uint8_t add)
+{
+	uint8_t i;
+	struct rte_eth_dev *dev;
+	struct rte_eth_tunnel_filter_conf *pfilter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return -ENODEV;
+	}
+
+	if (tunnel_filter == NULL) {
+		PMD_DEBUG_TRACE("Invalid oud_filter parameter\n");
+		return -EINVAL;
+	}
+	pfilter = tunnel_filter;
+
+	dev = &rte_eth_devices[port_id];
+	for (i = 0; i < filter_count; i++, pfilter++) {
+		if (pfilter->queue_id >= dev->data->nb_rx_queues) {
+			PMD_DEBUG_TRACE("Invalid queue number\n");
+			return -EINVAL;
+		}
+
+		if (pfilter->inner_vlan > ETHER_MAX_VLAN_ID) {
+			PMD_DEBUG_TRACE("Invalid inner VLAN ID\n");
+			return -EINVAL;
+		}
+
+		if (is_zero_ether_addr(pfilter->outer_mac)) {
+			PMD_DEBUG_TRACE("port %d: Cannot add NULL outer MAC address\n",
+				port_id);
+			return -EINVAL;
+		}
+
+		if (is_zero_ether_addr(pfilter->inner_mac)) {
+			PMD_DEBUG_TRACE("port %d: Cannot add NULL inner MAC address\n",
+				port_id);
+			return -EINVAL;
+		}
+	}
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tunnel_filter_set, -ENOTSUP);
+	return (*dev->dev_ops->tunnel_filter_set)(dev, tunnel_filter,
+						filter_count, add);
+}
+
+int
 rte_eth_led_on(uint8_t port_id)
 {
 	struct rte_eth_dev *dev;
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d24907f..47d50da 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -707,6 +707,28 @@  struct rte_fdir_conf {
 	uint8_t drop_queue;
 };
 
+enum rte_tunnel_filter_type {
+	RTE_TUNNEL_FILTER_TYPE_NONE = 0,
+	RTE_TUNNEL_FILTER_IMAC_IVLAN, /**< Filter by inner MAC and VLAN ID. */
+	RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID,
+	/**< Filter by inner MAC address and VLAN ID, tenned ID. */
+	RTE_TUNNEL_FILTER_IMAC_TENID, /**< Filter by inner MAC and tenant ID. */
+	RTE_TUNNEL_FILTER_IMAC, /**< Filter by inner MAC address */
+	RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,
+	/**< Filter by outer MAC address, tenant ID and Inner MAC */
+	RTE_TUNNEL_FILTER_TYPE_MAX,
+};
+
+#define RTE_TUNNEL_FLAGS_TO_QUEUE               1
+
+/**
+ *  Select IPv4 or IPv6 tunnel filters.
+ */
+enum rte_tunnel_iptype {
+	RTE_TUNNEL_IPTYPE_IPV4 = 0, /**< IPv4. */
+	RTE_TUNNEL_IPTYPE_IPV6,     /**< IPv6. */
+};
+
 /**
  * Tunneled type.
  */
@@ -720,6 +742,26 @@  enum rte_eth_tunnel_type {
 };
 
 /**
+ * Tunnel Packet filter configuration.
+ */
+struct rte_eth_tunnel_filter_conf {
+	struct ether_addr *outer_mac;  /**< Outer MAC address fiter. */
+	struct ether_addr *inner_mac;  /**< Inner MAC address fiter. */
+	uint16_t inner_vlan;           /**< Inner VLAN fiter. */
+	enum rte_tunnel_iptype ip_type; /**< IP address type. */
+	union {
+		uint32_t ipv4_addr;    /**< IPv4 source address to match. */
+		uint32_t ipv6_addr[4]; /**< IPv6 source address to match. */
+	} ip_addr; /**< IPv4/IPv6 source address to match (union of above). */
+
+	uint8_t filter_type;           /**< Filter type. */
+	uint8_t to_queue;              /**< Use MAC and VLAN to point to a queue. */
+	enum rte_eth_tunnel_type tunnel_type; /**< Tunnel Type. */
+	uint32_t tenant_id;            /** < Tenant number. */
+	uint16_t queue_id;             /** < queue number. */
+};
+
+/**
  * UDP tunneling configuration.
  */
 struct rte_eth_udp_tunnel {
@@ -1251,6 +1293,11 @@  typedef int (*eth_set_vf_rate_limit_t)(struct rte_eth_dev *dev,
 				uint64_t q_msk);
 /**< @internal Set VF TX rate */
 
+typedef int (*eth_tunnel_filter_set_t)(struct rte_eth_dev *dev,
+				      struct rte_eth_tunnel_filter_conf *tunnel_filter,
+				      uint8_t filter_count, uint8_t add);
+/**< @internal Set tunnel filter */
+
 typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev,
 				  struct rte_eth_vmdq_mirror_conf *mirror_conf,
 				  uint8_t rule_id,
@@ -1446,6 +1493,7 @@  struct eth_dev_ops {
 	eth_set_vf_vlan_filter_t   set_vf_vlan_filter;  /**< Set VF VLAN filter */
 	eth_udp_tunnel_add_t       udp_tunnel_add;
 	eth_udp_tunnel_del_t       udp_tunnel_del;
+	eth_tunnel_filter_set_t     tunnel_filter_set;
 	eth_set_queue_rate_limit_t set_queue_rate_limit;   /**< Set queue rate limit */
 	eth_set_vf_rate_limit_t    set_vf_rate_limit;   /**< Set VF rate limit */
 
@@ -3344,6 +3392,30 @@  rte_eth_dev_udp_tunnel_delete(uint8_t port_id,
 			struct rte_eth_udp_tunnel *tunnel_udp,
 			uint8_t count);
 
+ /**
+ * Add tunnel filter configuration of Ethernet device
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param tunnel_filter
+ *   Where to store the current Tunneling UDP configuration
+ *   of the Ethernet device.
+ * @param filter_count
+ *   How many filters are going to added.
+ * @param add
+ *   0: remove tunnel filter
+ *   1: add tunnel filter
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if port identifier is invalid.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-ENOTSUP) if hardware doesn't support tunnel type.
+ */
+int
+rte_eth_dev_tunnel_filter_set(uint8_t port_id,
+			struct rte_eth_tunnel_filter_conf *tunnel_filter,
+			uint8_t filter_count, uint8_t add);
 /**
  * add syn filter
  *