[dpdk-dev,3/6] i40e:Add VxLAN Cloud filter API

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

Commit Message

Jijiang Liu Aug. 12, 2014, 3:12 a.m. UTC
Support VxLAN cloud filters,which is used to use MAC, VLAN to point
   to a queue. The filter types supported include below:
   1. Inner MAC and Inner VLAN ID
   2. Inner MAC address and inner VLAN ID, tenned 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 ++++++++++++++++++++++++
 lib/librte_pmd_i40e/i40e_ethdev.c |  112 +++++++++++++++++++++++++++++++++++++
 3 files changed, 234 insertions(+), 0 deletions(-)
  

Comments

Thomas Monjalon Aug. 12, 2014, 10:40 a.m. UTC | #1
Hi Jijiang,

2014-08-12 11:12, Jijiang Liu:
> Support VxLAN cloud filters,which is used to use MAC, VLAN to point
>    to a queue. The filter types supported include below:
>    1. Inner MAC and Inner VLAN ID
>    2. Inner MAC address and inner VLAN ID, tenned 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 ++++++++++++++++++++++++
>  lib/librte_pmd_i40e/i40e_ethdev.c |  112 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 234 insertions(+), 0 deletions(-)

I prefer to have a separated commit for API (ethdev) and another one for
implementation (i40e).

About API, why name it cloud filter instead of VxLAN?

Thanks
  
Jijiang Liu Aug. 13, 2014, 8:23 a.m. UTC | #2
Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Tuesday, August 12, 2014 6:40 PM
> To: Liu, Jijiang
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 3/6]i40e:Add VxLAN Cloud filter API
> 
> Hi Jijiang,
> 
> 2014-08-12 11:12, Jijiang Liu:
> > Support VxLAN cloud filters,which is used to use MAC, VLAN to point
> >    to a queue. The filter types supported include below:
> >    1. Inner MAC and Inner VLAN ID
> >    2. Inner MAC address and inner VLAN ID, tenned 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 ++++++++++++++++++++++++
> >  lib/librte_pmd_i40e/i40e_ethdev.c |  112
> > +++++++++++++++++++++++++++++++++++++
> >  3 files changed, 234 insertions(+), 0 deletions(-)
> 
> I prefer to have a separated commit for API (ethdev) and another one for
> implementation (i40e).
> 
> About API, why name it cloud filter instead of VxLAN?
> 
Ok, I can separate the commit into two patches.

VxLAN is just a kind tunnel type, there are another tunnel types based on protocol type, they are below.
Tunnel Type:
* 0x0: VXLAN
* 0x1: NVGRE or other MAC in GRE
* 0x2: Geneve
  0x3: IP in GRE
Currently, I just implemented VxLAN tunnel type, and we will support another tunnel types in cloud filter API later.
  
Thomas Monjalon Aug. 13, 2014, 1:50 p.m. UTC | #3
2014-08-13 08:23, Liu, Jijiang:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > About API, why name it cloud filter instead of VxLAN?
> 
> VxLAN is just a kind tunnel type, there are another tunnel types based
> on protocol type, they are below.
> Tunnel Type:
> * 0x0: VXLAN
> * 0x1: NVGRE or other MAC in GRE
> * 0x2: Geneve
>   0x3: IP in GRE
> Currently, I just implemented VxLAN tunnel type, and we will support
> another tunnel types in cloud filter API later.

OK, I understand. But cloud filter is just a marketing name.
Please let's stick to technical and precise names.
It seems these tunnels are L2 over IP, right?
  
Alex Markuze Aug. 13, 2014, 2:17 p.m. UTC | #4
All are L2 over L3(UDP) -  General name  - Network Overlay.


On Wed, Aug 13, 2014 at 4:50 PM, Thomas Monjalon
<thomas.monjalon@6wind.com> wrote:
> 2014-08-13 08:23, Liu, Jijiang:
>> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
>> > About API, why name it cloud filter instead of VxLAN?
>>
>> VxLAN is just a kind tunnel type, there are another tunnel types based
>> on protocol type, they are below.
>> Tunnel Type:
>> * 0x0: VXLAN
>> * 0x1: NVGRE or other MAC in GRE
>> * 0x2: Geneve
>>   0x3: IP in GRE
>> Currently, I just implemented VxLAN tunnel type, and we will support
>> another tunnel types in cloud filter API later.
>
> OK, I understand. But cloud filter is just a marketing name.
> Please let's stick to technical and precise names.
> It seems these tunnels are L2 over IP, right?
>
> --
> Thomas
  
Jijiang Liu Aug. 18, 2014, 1:44 a.m. UTC | #5
Hi Thomas,

> -----Original Message-----

> From: Alex Markuze [mailto:alex@weka.io]

> Sent: Wednesday, August 13, 2014 10:18 PM

> To: Thomas Monjalon

> Cc: Liu, Jijiang; dev@dpdk.org

> Subject: Re: [dpdk-dev] [PATCH 3/6]i40e:Add VxLAN Cloud filter API

> 

> All are L2 over L3(UDP) -  General name  - Network Overlay.

> 

> 

> On Wed, Aug 13, 2014 at 4:50 PM, Thomas Monjalon

> <thomas.monjalon@6wind.com> wrote:

> > 2014-08-13 08:23, Liu, Jijiang:

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

> >> > About API, why name it cloud filter instead of VxLAN?

> >>

> >> VxLAN is just a kind tunnel type, there are another tunnel types

> >> based on protocol type, they are below.

> >> Tunnel Type:

> >> * 0x0: VXLAN

> >> * 0x1: NVGRE or other MAC in GRE

> >> * 0x2: Geneve

> >>   0x3: IP in GRE

> >> Currently, I just implemented VxLAN tunnel type, and we will support

> >> another tunnel types in cloud filter API later.

> >

> > OK, I understand. But cloud filter is just a marketing name.

> > Please let's stick to technical and precise names.

> > It seems these tunnels are L2 over IP, right?

> >

> > --

> > Thomas


I agree. I will change the API name as rte_eth_dev_tunnel_filter_set(), which means the API supports tunneled packet filtering.
Any comments?

Thanks
Jijiang Liu
  

Patch

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 325edb1..0e5b16d 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_cloud_filter_set(uint8_t port_id,
+			 struct rte_eth_cloud_filter_conf *cloud_filter,
+			 uint8_t filter_count, uint8_t add)
+{
+	uint8_t i;
+	struct rte_eth_dev *dev;
+	struct rte_eth_cloud_filter_conf *pfilter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return -ENODEV;
+	}
+
+	if (cloud_filter == NULL) {
+		PMD_DEBUG_TRACE("Invalid oud_filter parameter\n");
+		return -EINVAL;
+	}
+	pfilter = cloud_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->cloud_filter_set, -ENOTSUP);
+	return (*dev->dev_ops->cloud_filter_set)(dev, cloud_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..c95bab5 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_cloud_filter_type {
+	RTE_CLOUD_FILTER_TYPE_NONE = 0,
+	RTE_CLOUD_FILTER_IMAC_IVLAN, /**< Filter by inner MAC and VLAN ID. */
+	RTE_CLOUD_FILTER_IMAC_IVLAN_TENID,
+	/**< Filter by inner MAC address and VLAN ID, tenned ID. */
+	RTE_CLOUD_FILTER_IMAC_TENID, /**< Filter by inner MAC and tenant ID. */
+	RTE_CLOUD_FILTER_IMAC, /**< Filter by inner MAC address */
+	RTE_CLOUD_FILTER_OMAC_TENID_IMAC,
+	/**< Filter by outer MAC address, tenant ID and Inner MAC */
+	RTE_CLOUD_FILTER_TYPE_MAX,
+};
+
+#define RTE_CLOUD_FLAGS_TO_QUEUE               1
+
+/**
+ *  Select IPv4 or IPv6 Cloud filters.
+ */
+enum rte_cloud_iptype {
+	RTE_CLOUD_IPTYPE_IPV4 = 0, /**< IPv4. */
+	RTE_CLOUD_IPTYPE_IPV6,     /**< IPv6. */
+};
+
 /**
  * Tunneled type.
  */
@@ -720,6 +742,26 @@  enum rte_eth_tunnel_type {
 };
 
 /**
+ * Cloud filter configuration.
+ */
+struct rte_eth_cloud_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_cloud_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_cloud_filter_set_t)(struct rte_eth_dev *dev,
+				      struct rte_eth_cloud_filter_conf *cloud_filter,
+				      uint8_t filter_count, uint8_t add);
+/**< @internal Set cloud 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_cloud_filter_set_t     cloud_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 Cloud filter configuration of Ethernet device
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param cloud_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 cloud filter
+ *   1: add cloud 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_cloud_filter_set(uint8_t port_id,
+			struct rte_eth_cloud_filter_conf *cloud_filter,
+			uint8_t filter_count, uint8_t add);
 /**
  * add syn filter
  *
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index bb3d39a..29bb931 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -209,6 +209,9 @@  static int i40e_dev_udp_tunnel_add(struct rte_eth_dev *dev,
 static int i40e_dev_udp_tunnel_del(struct rte_eth_dev *dev,
 				   struct rte_eth_udp_tunnel *udp_tunnel,
 				   uint8_t count);
+static int i40e_dev_cloud_filter_set(struct rte_eth_dev *dev,
+			     struct rte_eth_cloud_filter_conf *cloud_filter,
+			     uint8_t filter_count, uint8_t add);
 static int i40e_pf_config_vxlan(struct i40e_pf *pf);
 
 /* Default hash key buffer for RSS */
@@ -257,6 +260,7 @@  static struct eth_dev_ops i40e_eth_dev_ops = {
 	.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,
 	.udp_tunnel_add               = i40e_dev_udp_tunnel_add,
 	.udp_tunnel_del               = i40e_dev_udp_tunnel_del,
+	.cloud_filter_set             = i40e_dev_cloud_filter_set,
 };
 
 static struct eth_driver rte_i40e_pmd = {
@@ -3948,6 +3952,114 @@  i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 }
 
 static int
+i40e_dev_get_filter_type(enum rte_cloud_filter_type filter_type, uint16_t *flag)
+{
+	switch (filter_type) {
+	case RTE_CLOUD_FILTER_IMAC_IVLAN:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN;
+		break;
+	case RTE_CLOUD_FILTER_IMAC_IVLAN_TENID:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID;
+		break;
+	case RTE_CLOUD_FILTER_IMAC_TENID:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID;
+		break;
+	case RTE_CLOUD_FILTER_OMAC_TENID_IMAC:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC;
+		break;
+	case RTE_CLOUD_FILTER_IMAC:
+		*flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC;
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "invalid cloud filter type\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+i40e_dev_cloud_filter_set(struct rte_eth_dev *dev,
+			struct rte_eth_cloud_filter_conf *cloud_filter,
+			uint8_t filter_count, uint8_t add)
+{
+	uint16_t ip_type;
+	uint8_t i, tun_type = 0;
+	enum i40e_status_code ret;
+	int val;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_vsi *vsi = pf->main_vsi;
+	struct i40e_aqc_add_remove_cloud_filters_element_data  *cld_filter;
+	struct i40e_aqc_add_remove_cloud_filters_element_data  *pfilter;
+
+	cld_filter = rte_zmalloc("cloud_filter", filter_count *
+		sizeof(struct i40e_aqc_add_remove_cloud_filters_element_data),
+		0);
+
+	if (NULL == cld_filter) {
+		PMD_DRV_LOG(ERR, "Failed to alloc memory.\n");
+		return -EINVAL;
+	}
+	pfilter = cld_filter;
+
+	for (i = 0; i < filter_count; i++, cloud_filter++, pfilter++) {
+
+		(void)rte_memcpy(&pfilter->outer_mac, cloud_filter->outer_mac,
+				sizeof(struct ether_addr));
+		(void)rte_memcpy(&pfilter->inner_mac, cloud_filter->inner_mac,
+				sizeof(struct ether_addr));
+
+		pfilter->inner_vlan = cloud_filter->inner_vlan;
+		if (cloud_filter->ip_type == RTE_CLOUD_IPTYPE_IPV4) {
+			ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4;
+			(void)rte_memcpy(&pfilter->ipaddr.v4.data,
+					&cloud_filter->ip_addr,
+					sizeof(pfilter->ipaddr.v4.data));
+		} else {
+			ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6;
+			(void)rte_memcpy(&pfilter->ipaddr.v6.data,
+					&cloud_filter->ip_addr,
+					sizeof(pfilter->ipaddr.v6.data));
+		}
+
+		/* check tunnel type */
+		switch (cloud_filter->tunnel_type) {
+		case RTE_TUNNEL_TYPE_VXLAN:
+			tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN;
+			break;
+		default:
+			/* Other tunnel types is not supported. */
+			PMD_DRV_LOG(ERR, "tunnel type is not supported.\n");
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
+
+		val = i40e_dev_get_filter_type(cloud_filter->filter_type,
+						&pfilter->flags);
+		if (val < 0) {
+			rte_free(cld_filter);
+			return -EINVAL;
+		}
+
+		pfilter->flags |= I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE | ip_type |
+			(tun_type << I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT);
+		pfilter->tenant_id = cloud_filter->tenant_id;
+		pfilter->queue_number = cloud_filter->queue_id;
+	}
+
+	if (add)
+		ret = i40e_aq_add_cloud_filters(hw, vsi->seid, cld_filter,
+						filter_count);
+	else
+		ret = i40e_aq_remove_cloud_filters(hw, vsi->seid, cld_filter,
+						filter_count);
+	rte_free(cld_filter);
+
+	return ret;
+}
+
+static int
 i40e_get_vxlan_port_idx(struct i40e_pf *pf, uint16_t port)
 {
 	uint8_t i;