DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
@ 2014-05-24  1:37 Jingjing Wu
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Jingjing Wu @ 2014-05-24  1:37 UTC (permalink / raw)
  To: dev

--- the v2 patchset changes:
--- add NIC filter support for 82576
--- rework for code rule warning if using git apply to apply patch

A generic filter mechanism for handling special packet is required.
It will allow filters to be set in HW when available so that specific
packet may be filtered by NICs to specific descriptor queues for
processing. Currently only Flow Director for Intel's 10GbE 82599
devices is available. Other types of filter are not support.
NIC filters list below are implemented in this patchset:
  ethertype filter, syn filter, 2tuple filter and flex filter for 82580 and i350
  ethertype filter, syn filter, 5tuple filter for 82576 
  ethertype filter, syn filter and 5tuple filter for 82599


jingjing.wu (4):
  add ethdev APIs for NIC filters of generic filter
  add igb NIC filters of generic filter feature
  add ixgbe NIC filters of generic filter feature
  add commands in testpmd for NIC filters

 app/test-pmd/cmdline.c              | 907 +++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c               | 145 ++++++
 app/test-pmd/testpmd.h              |   6 +
 lib/librte_ether/rte_ethdev.c       | 281 +++++++++++
 lib/librte_ether/rte_ethdev.h       | 421 ++++++++++++++++-
 lib/librte_pmd_e1000/e1000_ethdev.h |  53 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 745 +++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 409 ++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  33 ++
 9 files changed, 2998 insertions(+), 2 deletions(-)

-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of generic filter
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
@ 2014-05-24  1:37 ` Jingjing Wu
  2014-05-27  7:57   ` Ming, LiX
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature Jingjing Wu
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Jingjing Wu @ 2014-05-24  1:37 UTC (permalink / raw)
  To: dev

This patch adds APIs for NIC filters list below:
ethertype filter, syn filter, 2tuple filter, flex filter, 5tuple filter

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 281 ++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 421 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 701 insertions(+), 1 deletion(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a5727dd..afd4fe8 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -41,6 +41,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 
 #include <rte_byteorder.h>
 #include <rte_log.h>
@@ -2335,3 +2336,283 @@ rte_eth_dev_bypass_wd_reset(uint8_t port_id)
 	return 0;
 }
 #endif
+
+int
+rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+			uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 1;
+	filter.hig_pri = high_pri;
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_syn_filter(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 0;
+	filter.hig_pri = 0;
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, 0);
+}
+
+int
+rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_syn_filter)(dev, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->ethertype == ETHER_TYPE_IPv4 ||
+		filter->ethertype == ETHER_TYPE_IPv6){
+		PMD_DEBUG_TRACE("IP and IPv6 are not supported"
+			" in ethertype filter\n");
+		return (-EINVAL);
+	}
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_ethertype_filter)(dev, index,
+					filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_ethertype_filter(uint8_t port_id,  uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_ethertype_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_ethertype_filter)(dev, index,
+						filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
+			" is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_2tuple_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
+			" is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_5tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_5tuple_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_5tuple_filter)(dev, index, filter,
+						rx_queue);
+}
+
+int
+rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_flex_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_flex_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
+						rx_queue);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d5ea46b..21257b2 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -808,6 +808,71 @@ struct rte_eth_dev_callback;
 /** @internal Structure to keep track of registered callbacks */
 TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 
+#define TCP_UGR_FLAG 0x20
+#define TCP_ACK_FLAG 0x10
+#define TCP_PSH_FLAG 0x08
+#define TCP_RST_FLAG 0x04
+#define TCP_SYN_FLAG 0x02
+#define TCP_FIN_FLAG 0x01
+#define TCP_FLAG_ALL 0x3F
+
+/**
+ *  A structure used to define an ethertype filter.
+ */
+struct rte_ethertype_filter {
+	uint16_t ethertype;  /**<little endian*/
+	uint8_t priority_en; /**<compare priority enable*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define an syn filter.
+ */
+struct rte_syn_filter {
+	uint8_t enable;  /**<1 means enable, 0 means disable*/
+	uint8_t hig_pri; /**< 1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower pri*/
+};
+
+/**
+ *  A structure used to define a 2tuple filter.
+ */
+struct rte_2tuple_filter {
+	uint16_t dst_port;  /**<big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**< used when more than one filter matches */
+	uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+		protocol_mask   : 1;
+};
+
+/**
+ *  A structure used to define a flex filter.
+ */
+struct rte_flex_filter {  /** for E1000 filters*/
+	uint16_t len;
+	uint32_t dwords[32];  /**<flex bytes in big endian*/
+	uint8_t mask[16];     /**<if mask bit is 1b, means compare corresponding byte in dwords*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define a 5tuple filter.
+ */
+struct rte_5tuple_filter {
+	uint32_t dst_ip;   /**<destination IP address in big endian*/
+	uint32_t src_ip;   /**<source IP address in big endian*/
+	uint16_t dst_port; /**<destination port in big endian*/
+	uint16_t src_port; /**<source Port big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**<seven evels (001b-111b),  111b is highest, used when more than one filter matches */
+	uint8_t dst_ip_mask   : 1, /**<if mask is 1b, do not compare dst ip*/
+		src_ip_mask   : 1, /**<if mask is 1b, do not compare src ip*/
+		dst_port_mask : 1, /**<if mask is 1b, do not compare dst port*/
+		src_port_mask : 1, /**<if mask is 1b, do not compare src port*/
+		protocol_mask   : 1; /**<if mask is 1b, do not compare protocol*/
+};
+
 /*
  * 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*
@@ -1076,6 +1141,69 @@ typedef int32_t (*bypass_ver_show_t)(struct rte_eth_dev *dev, uint32_t *ver);
 typedef int32_t (*bypass_wd_reset_t)(struct rte_eth_dev *dev);
 #endif
 
+typedef int (*eth_set_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+/**< @internal Set syn filter rule on an Ethernet device */
+
+typedef int (*eth_get_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+/**< @internal Get syn filter rule on an Ethernet device */
+
+typedef int (*eth_add_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_remove_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_get_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_add_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_2tuple_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_2tuple_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_5tuple_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_5tuple_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_flex_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new flex filter rule on an Ethernet device */
+
+typedef int (*eth_remove_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a flex filter rule on an Ethernet device */
+
+typedef int (*eth_get_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_flex_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a flex filter rule on an Ethernet device */
 
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
@@ -1152,7 +1280,20 @@ struct eth_dev_ops {
   bypass_ver_show_t bypass_ver_show;
   bypass_wd_reset_t bypass_wd_reset;
 #endif
-
+	eth_set_syn_filter_t           set_syn_filter;  /**< set syn filter. */
+	eth_get_syn_filter_t           get_syn_filter;  /**< get syn filter. */
+	eth_add_ethertype_filter_t     add_ethertype_filter;  /**< add ethertype filter. */
+	eth_remove_ethertype_filter_t  remove_ethertype_filter;  /**< remove ethertype filter*/
+	eth_get_ethertype_filter_t     get_ethertype_filter;  /**< get ethertype filter*/
+	eth_add_2tuple_filter_t        add_2tuple_filter;  /**<add 2tuple filter */
+	eth_remove_2tuple_filter_t     remove_2tuple_filter;  /**< remove 2tuple filter*/
+	eth_get_2tuple_filter_t        get_2tuple_filter;  /**< get 2tuple filter*/
+	eth_add_5tuple_filter_t        add_5tuple_filter;  /**< add 5tuple filter*/
+	eth_remove_5tuple_filter_t     remove_5tuple_filter;  /**< remove 5tuple filter*/
+	eth_get_5tuple_filter_t        get_5tuple_filter;   /**< get 5tuple filter*/
+	eth_add_flex_filter_t        add_flex_filter;  /**< add flex filter*/
+	eth_remove_flex_filter_t     remove_flex_filter;  /**< remove flex filter*/
+	eth_get_flex_filter_t        get_flex_filter;  /**< get flex filter*/
 };
 
 /**
@@ -2725,6 +2866,284 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
  */
 int rte_eth_dev_bypass_wd_reset(uint8_t port);
 
+/**
+ * add syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param rx_queue
+ *   The index of RX queue where to store RX packets matching the syn filter.
+ * @param high_pri
+ *    1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+				uint8_t rx_queue);
+
+/**
+ * remove syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_remove_syn_filter(uint8_t port_id);
+
+/**
+ * get syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   The pointer to the structure describing the syn filter.
+ * @param rx_queue
+ *   the point of a int type to get the queue of syn filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @param filter
+ *   The pointer to the structure describing the ethertype filter rule.
+ *   The *rte_ethertype_filter* structure includes the values of the different
+ *   fields to match: ethertype and priority in vlan tag.
+ *   priority in vlan tag is not supported for E1000 dev.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+/**
+ * remove an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_ethertype_filter(uint8_t port_id,
+			uint16_t index);
+
+/**
+ * Get an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   A pointer to a structure of type *rte_ethertype_filter* to be filled with
+ *   the information of the Ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+/**
+ * Add a new 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 2tuple filter rule.
+ *   The *rte_2tuple_filter* structure includes the values of the different
+ *   fields to match: protocol, dst_port and
+ *   tcp_flags if the protocol is tcp type.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+
+int rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue);
+/**
+ * remove a 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_2tuple_filter* to be filled with
+ *   the information of the 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 5tuple filter rule.
+ *   The *rte_5tuple_filter* structure includes the values of the different fields
+ *   fields to match: dst src IP, dst src port, protocol and relative masks
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+
+/**
+ * remove a 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_5tuple_filter* to be filled with
+ *   the information of the 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   The pointer to the structure describing the flex filter rule.
+ *   The *rte_flex_filter* structure includes the values of the different fields
+ *   to match: the dwords (first len bytes of packet ) and relative masks.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue);
+/**
+ * remove a flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_flex_filter* to be filled with
+ *   the information of the flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
@ 2014-05-24  1:37 ` Jingjing Wu
  2014-05-27  7:59   ` Ming, LiX
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe " Jingjing Wu
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Jingjing Wu @ 2014-05-24  1:37 UTC (permalink / raw)
  To: dev

This patch adds following igb NIC filters implement:
  syn filter, ethertype filter, 2tuple filter, flex filter for intel NIC 82580 and i350
  syn filter, ethertype filter, 5tuple filter for intel NIC 82576

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_e1000/e1000_ethdev.h |  53 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 745 ++++++++++++++++++++++++++++++++++++
 2 files changed, 798 insertions(+)

diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..239e849 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -52,6 +52,59 @@
 #define E1000_CTRL_EXT_EXTEND_VLAN  (1<<26)    /* EXTENDED VLAN */
 #define IGB_VFTA_SIZE 128
 
+#define IGB_MAX_RX_QUEUE_NUM           8
+#define IGB_MAX_RX_QUEUE_NUM_82576     16
+
+#define E1000_SYN_FILTER_ENABLE        0x00000001 /** syn filter enable field*/
+#define E1000_SYN_FILTER_QUEUE         0x0000000E /** syn filter queue field*/
+#define E1000_SYN_FILTER_QUEUE_SHIFT   1 /** syn filter queue field*/
+#define E1000_RFCTL_SYNQFP             0x00080000 /** SYNQFP in RFCTL register*/
+
+#define E1000_ETQF_ETHERTYPE           0x0000FFFF
+#define E1000_ETQF_QUEUE               0x00070000
+#define E1000_ETQF_QUEUE_SHIFT         16
+#define E1000_MAX_ETQF_FILTERS         8
+
+#define E1000_IMIR_DSTPORT             0x0000FFFF
+#define E1000_IMIR_PRIORITY            0xE0000000
+#define E1000_IMIR_EXT_SIZE_BP         0x00001000
+#define E1000_IMIR_EXT_CTRL_UGR        0x00002000
+#define E1000_IMIR_EXT_CTRL_ACK        0x00004000
+#define E1000_IMIR_EXT_CTRL_PSH        0x00008000
+#define E1000_IMIR_EXT_CTRL_RST        0x00010000
+#define E1000_IMIR_EXT_CTRL_SYN        0x00020000
+#define E1000_IMIR_EXT_CTRL_FIN        0x00040000
+#define E1000_IMIR_EXT_CTRL_BP         0x00080000
+#define E1000_MAX_TTQF_FILTERS         8
+#define E1000_2TUPLE_MAX_PRI           7
+
+#define E1000_MAX_FLEXIBLE_FILTERS       8
+#define E1000_MAX_FHFT                   4
+#define E1000_MAX_FHFT_EXT               4
+#define E1000_MAX_FLEX_FILTER_PRI        7
+#define E1000_MAX_FLEX_FILTER_LEN        128
+#define E1000_FHFT_QUEUEING_LEN          0x0000007F
+#define E1000_FHFT_QUEUEING_QUEUE        0x00000700
+#define E1000_FHFT_QUEUEING_PRIO         0x00070000
+#define E1000_FHFT_QUEUEING_OFFSET       0xFC
+#define E1000_FHFT_QUEUEING_QUEUE_SHIFT  8
+#define E1000_FHFT_QUEUEING_PRIO_SHIFT   16
+#define E1000_WUFC_FLEX_HQ               0x00004000
+
+#define E1000_SPQF_SRCPORT               0x0000FFFF /** src port field */
+
+#define E1000_MAX_FTQF_FILTERS           8
+#define E1000_FTQF_PROTOCOL_MASK         0x000000FF
+#define E1000_FTQF_5TUPLE_MASK_SHIFT     28
+#define E1000_FTQF_PROTOCOL_COMP_MASK    0x10000000
+#define E1000_FTQF_SOURCE_ADDR_MASK      0x20000000
+#define E1000_FTQF_DEST_ADDR_MASK        0x40000000
+#define E1000_FTQF_SOURCE_PORT_MASK      0x80000000
+#define E1000_FTQF_VF_MASK_EN            0x00008000
+#define E1000_FTQF_QUEUE_MASK            0x03ff0000
+#define E1000_FTQF_QUEUE_SHIFT           16
+#define E1000_FTQF_QUEUE_ENABLE          0x00000100
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
 	uint32_t flags;
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 044eac3..1e63a8f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -124,6 +124,43 @@ static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 		struct rte_eth_rss_reta *reta_conf);
 
+static int eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -194,6 +231,20 @@ static struct eth_dev_ops eth_igb_ops = {
 	.mac_addr_remove      = eth_igb_rar_clear,
 	.reta_update          = eth_igb_rss_reta_update,
 	.reta_query           = eth_igb_rss_reta_query,
+	.set_syn_filter       = eth_igb_set_syn_filter,
+	.get_syn_filter          = eth_igb_get_syn_filter,
+	.add_ethertype_filter    = eth_igb_add_ethertype_filter,
+	.remove_ethertype_filter = eth_igb_remove_ethertype_filter,
+	.get_ethertype_filter    = eth_igb_get_ethertype_filter,
+	.add_2tuple_filter       = eth_igb_add_2tuple_filter,
+	.remove_2tuple_filter    = eth_igb_remove_2tuple_filter,
+	.get_2tuple_filter       = eth_igb_get_2tuple_filter,
+	.add_flex_filter         = eth_igb_add_flex_filter,
+	.remove_flex_filter      = eth_igb_remove_flex_filter,
+	.get_flex_filter         = eth_igb_get_flex_filter,
+	.add_5tuple_filter       = eth_igb_add_5tuple_filter,
+	.remove_5tuple_filter    = eth_igb_remove_5tuple_filter,
+	.get_5tuple_filter       = eth_igb_get_5tuple_filter,
 };
 
 /*
@@ -2184,6 +2235,700 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 	return 0;
 }
 
+#define MAC_TYPE_FILTER_SUP(type)    do {\
+	if ((type) != e1000_82580 && (type) != e1000_i350 &&\
+		(type) != e1000_82576)\
+		return -ENOSYS;\
+} while (0)
+
+/*
+ *set the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+
+	if (filter->enable) {
+		if (synqf & E1000_SYN_FILTER_ENABLE)
+			return (-EINVAL);
+		synqf = (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) &
+			E1000_SYN_FILTER_QUEUE) | E1000_SYN_FILTER_ENABLE);
+	} else
+		synqf = 0;
+
+	if (filter->hig_pri)
+		rfctl |= E1000_RFCTL_SYNQFP;
+	else
+		rfctl &= ~E1000_RFCTL_SYNQFP;
+
+	E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+	return 0;
+}
+
+/*
+ *get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	filter->enable = (synqf & E1000_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE) >>
+			E1000_SYN_FILTER_QUEUE_SHIFT);
+	return 0;
+}
+
+/*
+ *add an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+	else
+		etqf = 0;
+
+	etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
+	etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE);
+	etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT;
+
+	if (filter->priority_en) {
+		PMD_INIT_LOG(ERR, "vlan and priority (%d) is not support"
+			" in E1000.\n", filter->priority);
+		return (-EINVAL);
+	}
+
+	E1000_WRITE_REG(hw, E1000_ETQF(index), etqf);
+	return 0;
+}
+
+/*
+ *remove an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	E1000_WRITE_REG(hw, E1000_ETQF(index), 0);
+	return 0;
+}
+
+/*
+ *gets an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE) {
+		filter->ethertype = etqf & E1000_ETQF_ETHERTYPE;
+		filter->priority_en = 0;
+		*rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+#define MAC_TYPE_FILTER_SUP_EXT(type)    do {\
+	if ((type) != e1000_82580 && (type) != e1000_i350)\
+		return -ENOSYS; \
+} while (0)
+
+/*
+ *add a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ttqf, imir = 0;
+	uint32_t imir_ext = 0;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS ||
+		rx_queue >= IGB_MAX_RX_QUEUE_NUM ||
+		filter->priority > E1000_2TUPLE_MAX_PRI)
+		return (-EINVAL);  /**filter index is out of range*/
+	if  (filter->tcp_flags > TCP_FLAG_ALL)
+		return (-EINVAL);  /**flags is invalid*/
+
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+
+	imir = (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+	if (filter->dst_port_mask == 1) /**1b means not compare*/
+		imir |= E1000_IMIR_PORT_BP;
+	else
+		imir &= ~E1000_IMIR_PORT_BP;
+
+	imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+	ttqf = 0;
+	ttqf |= E1000_TTQF_QUEUE_ENABLE;
+	ttqf |= (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT);
+	ttqf |= (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK);
+	if (filter->protocol_mask == 1)
+		ttqf |= E1000_TTQF_MASK_ENABLE;
+	else
+		ttqf &= ~E1000_TTQF_MASK_ENABLE;
+
+	imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+	/*tcp flags bits setting*/
+	if (filter->tcp_flags & TCP_FLAG_ALL) {
+		if (filter->tcp_flags & TCP_UGR_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+		if (filter->tcp_flags & TCP_ACK_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+		if (filter->tcp_flags & TCP_PSH_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+		if (filter->tcp_flags & TCP_RST_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+		if (filter->tcp_flags & TCP_SYN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+		if (filter->tcp_flags & TCP_FIN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+		imir_ext &= ~E1000_IMIR_EXT_CTRL_BP;
+	} else
+		imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+	E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+	E1000_WRITE_REG(hw, E1000_TTQF(index), ttqf);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+	return 0;
+}
+
+/*
+ *remove a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+}
+
+/*
+ *get a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t imir, ttqf, imir_ext;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE) {
+		imir = E1000_READ_REG(hw, E1000_IMIR(index));
+		filter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;
+		filter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;
+		*rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >>
+				E1000_TTQF_QUEUE_SHIFT;
+		filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+		filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+		filter->priority = (imir & E1000_IMIR_PRIORITY) >>
+			E1000_IMIR_PRIORITY_SHIFT;
+
+		imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
+		if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
+			if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
+				filter->tcp_flags |= TCP_UGR_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
+				filter->tcp_flags |= TCP_ACK_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
+				filter->tcp_flags |= TCP_PSH_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
+				filter->tcp_flags |= TCP_RST_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
+				filter->tcp_flags |= TCP_SYN_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
+				filter->tcp_flags |= TCP_FIN_FLAG;
+		} else
+			filter->tcp_flags = 0;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, en_bits = 0;
+	uint32_t queueing = 0;
+	uint32_t reg_off = 0;
+	uint8_t i, j = 0;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN ||
+		filter->len % 8 != 0 ||
+		filter->priority > E1000_MAX_FLEX_FILTER_PRI)
+		return (-EINVAL);
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	en_bits = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+	if ((wufc & en_bits) == en_bits)
+		return (-EINVAL);  /**the filter is  enabled*/
+
+	E1000_WRITE_REG(hw, E1000_WUFC,
+		wufc | E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index));
+
+	j = 0;
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+	for (i = 0; i < 16; i++) {
+		E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+2)*4,
+				(uint32_t)filter->mask[i]);
+		++j;
+	}
+	queueing |= filter->len |
+		(rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) |
+		(filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT);
+	E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing);
+	return 0;
+}
+
+/*
+ *remove a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+				uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, reg_off = 0;
+	uint8_t i;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc & (~(E1000_WUFC_FLX0 << index)));
+
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+	for (i = 0; i < 64; i++)
+		E1000_WRITE_REG(hw, reg_off + i*4, 0);
+	return 0;
+}
+
+/*
+ *get a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: the pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, queueing, wufc_en = 0;
+	uint8_t i, j;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	wufc_en = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+
+	if ((wufc & wufc_en) == wufc_en) {
+		uint32_t reg_off = 0;
+		j = 0;
+		if (index < E1000_MAX_FHFT)
+			reg_off = E1000_FHFT(index);
+		else
+			reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+		for (i = 0; i < 16; i++, j = i * 2) {
+			filter->dwords[j] =
+				E1000_READ_REG(hw, reg_off + i*4*4);
+			filter->dwords[j+1] =
+				E1000_READ_REG(hw, reg_off + (i*4+1)*4);
+			filter->mask[i] =
+				E1000_READ_REG(hw, reg_off + (i*4+2)*4);
+		}
+		queueing = E1000_READ_REG(hw,
+				reg_off + E1000_FHFT_QUEUEING_OFFSET);
+		filter->len = queueing & E1000_FHFT_QUEUEING_LEN;
+		filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >>
+			E1000_FHFT_QUEUEING_PRIO_SHIFT;
+		*rx_queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >>
+			E1000_FHFT_QUEUEING_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, spqf = 0;
+	uint32_t imir = 0;
+	uint32_t imir_ext = 0;
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS ||
+		rx_queue >= IGB_MAX_RX_QUEUE_NUM_82576)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
+	if (ftqf & E1000_FTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+
+	ftqf = 0;
+	ftqf |= filter->protocol & E1000_FTQF_PROTOCOL_MASK;
+	if (filter->src_ip_mask == 1) /** 1b means not compare*/
+		ftqf |= E1000_FTQF_SOURCE_ADDR_MASK;
+	if (filter->dst_ip_mask == 1)
+		ftqf |= E1000_FTQF_DEST_ADDR_MASK;
+	if (filter->src_port_mask == 1)
+		ftqf |= E1000_FTQF_SOURCE_PORT_MASK;
+	if (filter->protocol_mask == 1)
+		ftqf |= E1000_FTQF_PROTOCOL_COMP_MASK;
+	ftqf |= (rx_queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK;
+	ftqf |= E1000_FTQF_VF_MASK_EN;
+	ftqf |= E1000_FTQF_QUEUE_ENABLE;
+	E1000_WRITE_REG(hw, E1000_FTQF(index), ftqf);
+	E1000_WRITE_REG(hw, E1000_DAQF(index), filter->dst_ip);
+	E1000_WRITE_REG(hw, E1000_SAQF(index), filter->src_ip);
+
+	spqf |= filter->src_port & E1000_SPQF_SRCPORT;
+	E1000_WRITE_REG(hw, E1000_SPQF(index), spqf);
+
+	imir |= (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+	if (filter->dst_port_mask == 1) /**1b means not compare*/
+		imir |= E1000_IMIR_PORT_BP;
+	else
+		imir &= ~E1000_IMIR_PORT_BP;
+	imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+	imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+	/*tcp flags bits setting*/
+	if (filter->tcp_flags & TCP_FLAG_ALL) {
+		if (filter->tcp_flags & TCP_UGR_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+		if (filter->tcp_flags & TCP_ACK_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+		if (filter->tcp_flags & TCP_PSH_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+		if (filter->tcp_flags & TCP_RST_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+		if (filter->tcp_flags & TCP_SYN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+		if (filter->tcp_flags & TCP_FIN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+	} else
+		imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+	E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+	return 0;
+}
+
+/*
+ *remove a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
+				uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	E1000_WRITE_REG(hw, E1000_FTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_DAQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_SAQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_SPQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+}
+
+/*
+ *get a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t spqf, ftqf, imir, imir_ext;
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
+	if (ftqf & E1000_FTQF_QUEUE_ENABLE) {
+		filter->src_ip_mask =
+			(ftqf & E1000_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
+		filter->dst_ip_mask =
+			(ftqf & E1000_FTQF_DEST_ADDR_MASK) ? 1 : 0;
+		filter->src_port_mask =
+			(ftqf & E1000_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
+		filter->protocol_mask =
+			(ftqf & E1000_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
+		filter->protocol =
+			(uint8_t)ftqf & E1000_FTQF_PROTOCOL_MASK;
+		*rx_queue = (uint8_t)((ftqf & E1000_FTQF_QUEUE_MASK) >>
+				E1000_FTQF_QUEUE_SHIFT);
+
+		spqf = E1000_READ_REG(hw, E1000_SPQF(index));
+		filter->src_port = spqf & E1000_SPQF_SRCPORT;
+
+		filter->dst_ip = E1000_READ_REG(hw, E1000_DAQF(index));
+		filter->src_ip = E1000_READ_REG(hw, E1000_SAQF(index));
+
+		imir = E1000_READ_REG(hw, E1000_IMIR(index));
+		filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+		filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+		filter->priority = (imir & E1000_IMIR_PRIORITY) >>
+			E1000_IMIR_PRIORITY_SHIFT;
+
+		imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
+		if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
+			if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
+				filter->tcp_flags |= TCP_UGR_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
+				filter->tcp_flags |= TCP_ACK_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
+				filter->tcp_flags |= TCP_PSH_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
+				filter->tcp_flags |= TCP_RST_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
+				filter->tcp_flags |= TCP_SYN_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
+				filter->tcp_flags |= TCP_FIN_FLAG;
+		} else
+			filter->tcp_flags = 0;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
 static struct rte_driver pmd_igb_drv = {
 	.type = PMD_PDEV,
 	.init = rte_igb_pmd_init,
-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe NIC filters of generic filter feature
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature Jingjing Wu
@ 2014-05-24  1:37 ` Jingjing Wu
  2014-05-27  8:00   ` Ming, LiX
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Jingjing Wu @ 2014-05-24  1:37 UTC (permalink / raw)
  To: dev

This patch adds following ixgbe NIC filters implement:
  syn filter, ethertype filter, 5tuple filter for intel NIC 82599

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 409 ++++++++++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  33 +++
 2 files changed, 442 insertions(+)

diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index c9b5fe4..340c7cb 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 #include <rte_byteorder.h>
 #include <rte_common.h>
 #include <rte_cycles.h>
@@ -182,6 +183,23 @@ static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
 		uint8_t	rule_id);
 
+static int ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+static int ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -301,6 +319,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.bypass_ver_show      = ixgbe_bypass_ver_show,
 	.bypass_wd_reset      = ixgbe_bypass_wd_reset,
 #endif /* RTE_NIC_BYPASS */
+	.set_syn_filter	         = ixgbe_set_syn_filter,
+	.get_syn_filter          = ixgbe_get_syn_filter,
+	.add_ethertype_filter    = ixgbe_add_ethertype_filter,
+	.remove_ethertype_filter = ixgbe_remove_ethertype_filter,
+	.get_ethertype_filter    = ixgbe_get_ethertype_filter,
+	.add_5tuple_filter       = ixgbe_add_5tuple_filter,
+	.remove_5tuple_filter    = ixgbe_remove_5tuple_filter,
+	.get_5tuple_filter       = ixgbe_get_5tuple_filter,
 };
 
 /*
@@ -3062,6 +3088,389 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
 	return 0;
 }
 
+/*
+ * set the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+
+	if (filter->enable)
+		synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
+			IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE);
+	else
+		synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
+
+	if (filter->hig_pri)
+		synqf |= IXGBE_SYN_FILTER_SYNQFP;
+	else
+		synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
+	return 0;
+}
+
+/*
+ * get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	filter->enable = (synqf & IXGBE_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1);
+	return 0;
+}
+
+/*
+ * add an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_add_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs = 0;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS ||
+		rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN)
+		return (-EINVAL);  /** filter index is in use*/
+
+	etqf = 0;
+	etqf |= IXGBE_ETQF_FILTER_EN;
+	etqf |= (uint32_t)filter->ethertype;
+
+	if (filter->priority_en) {
+		if (filter->priority > IXGBE_ETQF_MAX_PRI)
+			return (-EINVAL);
+		etqf |= (uint32_t)((filter->priority << IXGBE_ETQF_SHIFT) & IXGBE_ETQF_UP);
+		etqf |= IXGBE_ETQF_UP_EN;
+	}
+	etqs |= (uint32_t)((rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE);
+	etqs |= IXGBE_ETQS_QUEUE_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), etqf);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), etqs);
+	return 0;
+}
+
+/*
+ * remove an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), 0);
+
+	return 0;
+}
+
+/*
+ * gets an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN) {
+		filter->ethertype = etqf & IXGBE_ETQF_ETHERTYPE;
+		filter->priority_en = (etqf & IXGBE_ETQF_UP_EN) ? 1 : 0;
+		if (filter->priority_en)
+			filter->priority = (etqf & IXGBE_ETQF_UP) >> 16;
+		*rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+static inline enum ixgbe_5tuple_protocol
+convert_protocol_type(uint8_t protocol_value)
+{
+	if (protocol_value == IPPROTO_TCP)
+		return IXGBE_FILTER_PROTOCOL_TCP;
+	else if (protocol_value == IPPROTO_UDP)
+		return IXGBE_FILTER_PROTOCOL_UDP;
+	else if (protocol_value == IPPROTO_SCTP)
+		return IXGBE_FILTER_PROTOCOL_SCTP;
+	else
+		return IXGBE_FILTER_PROTOCOL_NONE;
+}
+
+static inline uint8_t
+revert_protocol_type(enum ixgbe_5tuple_protocol protocol)
+{
+	if (protocol == IXGBE_FILTER_PROTOCOL_TCP)
+		return IPPROTO_TCP;
+	else if (protocol == IXGBE_FILTER_PROTOCOL_UDP)
+		return IPPROTO_UDP;
+	else if (protocol == IXGBE_FILTER_PROTOCOL_SCTP)
+		return IPPROTO_SCTP;
+	else
+		return 0;
+}
+
+/*
+ * add a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, sdpqf = 0;
+	uint32_t l34timir = 0;
+	uint8_t mask = 0xff;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS ||
+		rx_queue >= IXGBE_MAX_RX_QUEUE_NUM ||
+		filter->priority > IXGBE_5TUPLE_MAX_PRI ||
+		filter->priority < IXGBE_5TUPLE_MIN_PRI)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	if (filter->tcp_flags) {
+		PMD_INIT_LOG(INFO, "82599EB not tcp flags in 5tuple");
+		return (-EINVAL);
+	}
+
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBE_FTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /** filter index is in use*/
+
+	ftqf = 0;
+	sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDPQF_DSTPORT_SHIFT);
+	sdpqf = sdpqf | (filter->src_port & IXGBE_SDPQF_SRCPORT);
+
+	ftqf |= (uint32_t)(convert_protocol_type(filter->protocol) &
+		IXGBE_FTQF_PROTOCOL_MASK);
+	ftqf |= (uint32_t)((filter->priority & IXGBE_FTQF_PRIORITY_MASK) <<
+		IXGBE_FTQF_PRIORITY_SHIFT);
+	if (filter->src_ip_mask == 0) /** 0 means compare*/
+		mask &= IXGBE_FTQF_SOURCE_ADDR_MASK;
+	if (filter->dst_ip_mask == 0)
+		mask &= IXGBE_FTQF_DEST_ADDR_MASK;
+	if (filter->src_port_mask == 0)
+		mask &= IXGBE_FTQF_SOURCE_PORT_MASK;
+	if (filter->dst_port_mask == 0)
+		mask &= IXGBE_FTQF_DEST_PORT_MASK;
+	if (filter->protocol_mask == 0)
+		mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK;
+	ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT;
+	ftqf |= IXGBE_FTQF_POOL_MASK_EN;
+	ftqf |= IXGBE_FTQF_QUEUE_ENABLE;
+
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf);
+
+	l34timir |= IXGBE_L34T_IMIR_RESERVE;
+	l34timir |= (uint32_t)(rx_queue << IXGBE_L34T_IMIR_QUEUE_SHIFT);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), l34timir);
+	return 0;
+}
+
+/*
+ * remove a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0);
+	return 0;
+}
+
+/*
+ * get a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t sdpqf, ftqf, l34timir;
+	uint8_t mask;
+	enum ixgbe_5tuple_protocol proto;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) {
+		proto = (enum ixgbe_5tuple_protocol)(ftqf & IXGBE_FTQF_PROTOCOL_MASK);
+		filter->protocol = revert_protocol_type(proto);
+		filter->priority = (ftqf >> IXGBE_FTQF_PRIORITY_SHIFT) &
+					IXGBE_FTQF_PRIORITY_MASK;
+		mask = (uint8_t)((ftqf >> IXGBE_FTQF_5TUPLE_MASK_SHIFT) &
+					IXGBE_FTQF_5TUPLE_MASK_MASK);
+		filter->src_ip_mask =
+			(mask & IXGBE_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
+		filter->dst_ip_mask =
+			(mask & IXGBE_FTQF_DEST_ADDR_MASK) ? 1 : 0;
+		filter->src_port_mask =
+			(mask & IXGBE_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
+		filter->dst_port_mask =
+			(mask & IXGBE_FTQF_DEST_PORT_MASK) ? 1 : 0;
+		filter->protocol_mask =
+			(mask & IXGBE_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
+
+		sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index));
+		filter->dst_port = (sdpqf & IXGBE_SDPQF_DSTPORT) >>
+					IXGBE_SDPQF_DSTPORT_SHIFT;
+		filter->src_port = sdpqf & IXGBE_SDPQF_SRCPORT;
+		filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index));
+		filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index));
+
+		l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index));
+		*rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >>
+					IXGBE_L34T_IMIR_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..c5c2845 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -67,6 +67,29 @@
 #define IXGBE_LPBK_82599_NONE		0x0 /* Default value. Loopback is disabled. */
 #define IXGBE_LPBK_82599_TX_RX		0x1 /* Tx->Rx loopback operation is enabled. */
 
+#define IXGBE_SYN_FILTER_ENABLE         0x00000001 /** syn filter enable field*/
+#define IXGBE_SYN_FILTER_QUEUE          0x000000FE /** syn filter queue field*/
+#define IXGBE_SYN_FILTER_QUEUE_SHIFT    1        /** syn filter queue field shift*/
+#define IXGBE_SYN_FILTER_SYNQFP         0x80000000 /**syn filter SYNQFP*/
+
+#define IXGBE_ETQF_UP                   0x00070000 /** ethertype filter priority field*/
+#define IXGBE_ETQF_SHIFT                16
+#define IXGBE_ETQF_UP_EN                0x00080000
+#define IXGBE_ETQF_ETHERTYPE            0x0000FFFF /** ethertype filter ethertype field*/
+#define IXGBE_ETQF_MAX_PRI              7
+
+#define IXGBE_SDPQF_DSTPORT             0xFFFF0000 /** dst port field */
+#define IXGBE_SDPQF_DSTPORT_SHIFT       16 /** dst port field shift*/
+#define IXGBE_SDPQF_SRCPORT             0x0000FFFF /** src port field */
+
+#define IXGBE_L34T_IMIR_SIZE_BP         0x00001000
+#define IXGBE_L34T_IMIR_RESERVE         0x00080000 /** bit 13 to 19 must be set to 1000000b*/
+#define IXGBE_L34T_IMIR_LLI             0x00100000
+#define IXGBE_L34T_IMIR_QUEUE           0x0FE00000
+#define IXGBE_L34T_IMIR_QUEUE_SHIFT     21
+#define IXGBE_5TUPLE_MAX_PRI            7
+#define IXGBE_5TUPLE_MIN_PRI            1
+
 /*
  * Information about the fdir mode.
  */
@@ -150,6 +173,16 @@ struct ixgbe_adapter {
 #endif /* RTE_NIC_BYPASS */
 };
 
+/*
+ *  Possible l4type of 5tuple filters.
+ */
+enum ixgbe_5tuple_protocol {
+	IXGBE_FILTER_PROTOCOL_TCP = 0,
+	IXGBE_FILTER_PROTOCOL_UDP,
+	IXGBE_FILTER_PROTOCOL_SCTP,
+	IXGBE_FILTER_PROTOCOL_NONE,
+};
+
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
 	(&((struct ixgbe_adapter *)adapter)->hw)
 
-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (2 preceding siblings ...)
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe " Jingjing Wu
@ 2014-05-24  1:37 ` Jingjing Wu
  2014-05-27  8:00   ` Ming, LiX
  2014-05-27 23:21 ` [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Thomas Monjalon
  2014-06-04  4:16 ` Cao, Waterman
  5 siblings, 1 reply; 22+ messages in thread
From: Jingjing Wu @ 2014-05-24  1:37 UTC (permalink / raw)
  To: dev

add commands in testpmd for NIC filters:
add_ethertype_filter
remove_ethertype_filter
get_ethertype_filter
add_2tuple_filter
remove_2tuple_filter
get_2tuple_filter
add_5tuple_filter
remove_5tuple_filter
get_5tuple_filter
add_syn_filter
remove_syn_filter
get_syn_filter
add_flex_filter
remove_flex_filter
get_flex_filter

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 app/test-pmd/cmdline.c | 907 ++++++++++++++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c  | 145 ++++++++
 app/test-pmd/testpmd.h |   6 +
 3 files changed, 1057 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b3824f9..6bdfa6b 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -113,6 +113,7 @@ static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
 		"    help ports      : Configuring ports.\n"
 		"    help flowdir    : Flow Director filter help.\n"
 		"    help registers  : Reading and setting port registers.\n"
+		"    help filters    : Filters configuration help.\n"
 		"    help all        : All of the above sections.\n\n"
 	);
 
@@ -543,6 +544,67 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"    Set single bit value of a port register.\n\n"
 		);
 	}
+	if (show_all || !strcmp(res->section, "filters")) {
+
+		cmdline_printf(
+			cl,
+			"\n"
+			"filters:\n"
+			"----------\n\n"
+
+			"add_ethertype_filter (port_id) ethertype (eth_value)"
+			" priority (enable|disable)(pri_value) queue (queue_id) index (idx)\n"
+			"    add an ethertype filter.\n\n"
+
+			"remove_ethertype_filter (port_id) index (idx)\n"
+			"    remove an ethertype filter.\n\n"
+
+			"get_ethertype_filter (port_id) index (idx)\n"
+			"    get info of a ethertype filter.\n\n"
+
+			"add_2tuple_filter (port_id) protocol (pro_value) (pro_mask)"
+			" dst_port (port_value) (port_mask) flags (flg_value) priority (prio_value)"
+			" queue (queue_id) index (idx)\n"
+			"    add a 2tuple filter.\n\n"
+
+			"remove_2tuple_filter (port_id) index (idx)\n"
+			"    remove a 2tuple filter.\n\n"
+
+			"get_2tuple_filter (port_id) index (idx)\n"
+			"    get info of a 2tuple filter.\n\n"
+
+			"add_5tuple_filter (port_id) dst_ip (dst_address) src_ip (src_address)"
+			" dst_port (dst_port_value) src_port (src_port_value) protocol (protocol_value)"
+			" mask (mask_value) flags (flags_value) priority (prio_value)"
+			" queue (queue_id) index (idx)\n"
+			"    add a 5tuple filter.\n\n"
+
+			"remove_5tuple_filter (port_id) index (idx)\n"
+			"    remove a 5tuple filter.\n\n"
+
+			"get_5tuple_filter (port_id) index (idx)\n"
+			"    get info of a 5tuple filter.\n\n"
+
+			"add_syn_filter (port_id) priority (high|low) queue (queue_id)"
+			"    add syn filter.\n\n"
+
+			"remove_syn_filter (port_id)"
+			"    remove syn filter.\n\n"
+
+			"get_syn_filter (port_id) "
+			"    get syn filter info.\n\n"
+
+			"add_flex_filter (port_id) len (len_value) bytes (bytes_string) mask (mask_value)"
+			" priority (prio_value) queue (queue_id) index (idx)\n"
+			"    add a flex filter.\n\n"
+
+			"remove_flex_filter (port_id) index (idx)\n"
+			"    remove a flex filter.\n\n"
+
+			"get_flex_filter (port_id) index (idx)\n"
+			"    get info of a flex filter.\n\n"
+		);
+	}
 }
 
 cmdline_parse_token_string_t cmd_help_long_help =
@@ -551,7 +613,7 @@ cmdline_parse_token_string_t cmd_help_long_help =
 cmdline_parse_token_string_t cmd_help_long_section =
 	TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
 			"all#control#display#config#flowdir#"
-			"ports#registers");
+			"ports#registers#filters");
 
 cmdline_parse_inst_t cmd_help_long = {
 	.f = cmd_help_long_parsed,
@@ -5152,6 +5214,834 @@ cmdline_parse_inst_t cmd_dump_one = {
 	},
 };
 
+/* *** ADD/REMOVE an ethertype FILTER *** */
+struct cmd_ethertype_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t ethertype;
+	uint16_t ethertype_value;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t priority_en;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_ethertype_filter_result *res = parsed_result;
+	struct rte_ethertype_filter filter;
+
+	memset(&filter, 0, sizeof(struct rte_ethertype_filter));
+	filter.ethertype = rte_cpu_to_le_16(res->ethertype_value);
+	filter.priority = res->priority_value;
+
+	if (!strcmp(res->priority_en, "enable"))
+		filter.priority_en = 1;
+	if (!strcmp(res->filter, "add_ethertype_filter"))
+		ret = rte_eth_dev_add_ethertype_filter(res->port_id,
+				res->index_value,
+				&filter, res->queue_id);
+	else if (!strcmp(res->filter, "remove_ethertype_filter"))
+		ret = rte_eth_dev_remove_ethertype_filter(res->port_id,
+				res->index_value);
+	else if (!strcmp(res->filter, "get_ethertype_filter"))
+		get_ethertype_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("ethertype filter setting error: (%s)\n",
+			strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				ethertype, "ethertype");
+cmdline_parse_token_ipaddr_t cmd_ethertype_filter_ethertype_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority, "priority");
+cmdline_parse_token_string_t cmd_ethertype_filter_priority_en =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority_en, "enable#disable");
+cmdline_parse_token_num_t cmd_ethertype_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_ethertype_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				filter, "add_ethertype_filter");
+cmdline_parse_inst_t cmd_add_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "add an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_add_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_ethertype,
+		(void *)&cmd_ethertype_filter_ethertype_value,
+		(void *)&cmd_ethertype_filter_priority,
+		(void *)&cmd_ethertype_filter_priority_en,
+		(void *)&cmd_ethertype_filter_priority_value,
+		(void *)&cmd_ethertype_filter_queue,
+		(void *)&cmd_ethertype_filter_queue_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "remove_ethertype_filter");
+cmdline_parse_inst_t cmd_remove_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "remove an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_remove_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_ethertype_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "get_ethertype_filter");
+cmdline_parse_inst_t cmd_get_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "get an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_get_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** set SYN filter *** */
+struct cmd_set_syn_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t high;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+};
+
+static void
+cmd_set_syn_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_set_syn_filter_result *res = parsed_result;
+	if (!strcmp(res->filter, "add_syn_filter")) {
+		if (!strcmp(res->high, "high"))
+			ret = rte_eth_dev_add_syn_filter(res->port_id,
+				1, res->queue_id);
+		else
+			ret = rte_eth_dev_add_syn_filter(res->port_id,
+				0, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_syn_filter"))
+		ret = rte_eth_dev_remove_syn_filter(res->port_id);
+	else if (!strcmp(res->filter, "get_syn_filter"))
+		get_syn_filter(res->port_id);
+	if (ret < 0)
+		printf("syn filter setting error: (%s)\n", strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_syn_filter_portid =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "add_syn_filter");
+cmdline_parse_token_string_t cmd_syn_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "remove_syn_filter");
+cmdline_parse_inst_t cmd_add_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "add syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_add_filter,
+			(void *)&cmd_syn_filter_portid,
+			(void *)&cmd_syn_filter_priority,
+			(void *)&cmd_syn_filter_high,
+			(void *)&cmd_syn_filter_queue,
+			(void *)&cmd_syn_filter_queue_id,
+			NULL,
+		},
+};
+cmdline_parse_inst_t cmd_remove_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "remove syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_remove_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+cmdline_parse_token_string_t cmd_syn_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "get_syn_filter");
+
+cmdline_parse_inst_t cmd_get_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "get syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_get_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	uint8_t protocol_mask;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	uint16_t dst_port_mask;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_2tuple_filter filter;
+	struct cmd_2tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_2tuple_filter));
+
+	if (!strcmp(res->filter, "add_2tuple_filter")) {
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.protocol = res->protocol_value;
+		filter.dst_port_mask = (res->dst_port_mask) ? 0 : 1;
+		filter.protocol_mask = (res->protocol_mask) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+		ret = rte_eth_dev_add_2tuple_filter(res->port_id,
+			res->index_value, &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_2tuple_filter"))
+		ret = rte_eth_dev_remove_2tuple_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_2tuple_filter"))
+		get_2tuple_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("2tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol, "protocol");
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol_value, UINT8);
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				protocol_mask, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port_value, UINT16);
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port_mask, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				flags, "flags");
+cmdline_parse_token_string_t cmd_2tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_2tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "add_2tuple_filter");
+cmdline_parse_inst_t cmd_add_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_add_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_protocol,
+		(void *)&cmd_2tuple_filter_protocol_value,
+		(void *)&cmd_2tuple_filter_protocol_mask,
+		(void *)&cmd_2tuple_filter_dst_port,
+		(void *)&cmd_2tuple_filter_dst_port_value,
+		(void *)&cmd_2tuple_filter_dst_port_mask,
+		(void *)&cmd_2tuple_filter_flags,
+		(void *)&cmd_2tuple_filter_flags_value,
+		(void *)&cmd_2tuple_filter_priority,
+		(void *)&cmd_2tuple_filter_priority_value,
+		(void *)&cmd_2tuple_filter_queue,
+		(void *)&cmd_2tuple_filter_queue_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_2tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "remove_2tuple_filter");
+cmdline_parse_inst_t cmd_remove_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_remove_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_2tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "get_2tuple_filter");
+cmdline_parse_inst_t cmd_get_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_get_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t dst_ip;
+	cmdline_ipaddr_t dst_ip_value;
+	cmdline_fixed_string_t src_ip;
+	cmdline_ipaddr_t src_ip_value;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	cmdline_fixed_string_t src_port;
+	uint16_t src_port_value;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	cmdline_fixed_string_t mask;
+	uint8_t  mask_value;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_5tuple_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_5tuple_filter filter;
+	struct cmd_5tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_5tuple_filter));
+
+	if (!strcmp(res->filter, "add_5tuple_filter")) {
+		filter.dst_ip_mask = (res->mask_value & 0x10) ? 0 : 1;
+		filter.src_ip_mask = (res->mask_value & 0x08) ? 0 : 1;
+		filter.dst_port_mask = (res->mask_value & 0x04) ? 0 : 1;
+		filter.src_port_mask = (res->mask_value & 0x02) ? 0 : 1;
+		filter.protocol = res->protocol_value;
+		filter.protocol_mask = (res->mask_value & 0x01) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+
+		if (res->dst_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr;
+		else {
+			if (filter.dst_ip_mask == 0) {
+				printf("can not support ipv6 involved compare.\n");
+				return;
+			}
+			filter.dst_ip = 0;
+		}
+
+		if (res->src_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.src_ip = res->src_ip_value.addr.ipv4.s_addr;
+		else {
+			if (filter.src_ip_mask == 0) {
+				printf("can not support ipv6 involved compare.\n");
+				return;
+			}
+			filter.src_ip = 0;
+		}
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.src_port = rte_cpu_to_be_16(res->src_port_value);
+
+		ret = rte_eth_dev_add_5tuple_filter(res->port_id,
+			res->index_value, &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_5tuple_filter"))
+		ret = rte_eth_dev_remove_5tuple_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_5tuple_filter"))
+		get_5tuple_filter(res->port_id, res->index_value);
+	if (ret < 0)
+		printf("5tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+
+cmdline_parse_token_num_t cmd_5tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_ip, "dst_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_ip, "src_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_port, "src_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				protocol, "protocol");
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				mask, "mask");
+cmdline_parse_token_num_t cmd_5tuple_filter_mask_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				mask_value, INT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				flags, "flags");
+cmdline_parse_token_num_t cmd_5tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				flags_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_5tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				index_value, UINT16);
+
+cmdline_parse_token_string_t cmd_5tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "add_5tuple_filter");
+cmdline_parse_inst_t cmd_add_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_add_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_dst_ip,
+		(void *)&cmd_5tuple_filter_dst_ip_value,
+		(void *)&cmd_5tuple_filter_src_ip,
+		(void *)&cmd_5tuple_filter_src_ip_value,
+		(void *)&cmd_5tuple_filter_dst_port,
+		(void *)&cmd_5tuple_filter_dst_port_value,
+		(void *)&cmd_5tuple_filter_src_port,
+		(void *)&cmd_5tuple_filter_src_port_value,
+		(void *)&cmd_5tuple_filter_protocol,
+		(void *)&cmd_5tuple_filter_protocol_value,
+		(void *)&cmd_5tuple_filter_mask,
+		(void *)&cmd_5tuple_filter_mask_value,
+		(void *)&cmd_5tuple_filter_flags,
+		(void *)&cmd_5tuple_filter_flags_value,
+		(void *)&cmd_5tuple_filter_priority,
+		(void *)&cmd_5tuple_filter_priority_value,
+		(void *)&cmd_5tuple_filter_queue,
+		(void *)&cmd_5tuple_filter_queue_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				filter, "remove_5tuple_filter");
+cmdline_parse_inst_t cmd_remove_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_remove_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				filter, "get_5tuple_filter");
+cmdline_parse_inst_t cmd_get_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_get_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t len;
+	uint8_t len_value;
+	cmdline_fixed_string_t bytes;
+	cmdline_fixed_string_t bytes_value;
+	cmdline_fixed_string_t mask;
+	cmdline_fixed_string_t mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static int xdigit2val(unsigned char c)
+{
+	int val;
+	if (isdigit(c))
+		val = c - '0';
+	else if (isupper(c))
+		val = c - 'A' + 10;
+	else
+		val = c - 'a' + 10;
+	return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_flex_filter filter;
+	struct cmd_flex_filter_result *res = parsed_result;
+	char *bytes_ptr, *mask_ptr;
+	uint16_t len, i, j;
+	char c;
+	int val, mod = 0;
+	uint32_t dword = 0;
+	uint8_t byte = 0;
+	uint8_t hex = 0;
+
+	if (!strcmp(res->filter, "add_flex_filter")) {
+		if (res->len_value > 128) {
+			printf("the len exceed the max length 128\n");
+			return;
+		}
+		memset(&filter, 0, sizeof(struct rte_flex_filter));
+		filter.len = res->len_value;
+		filter.priority = res->priority_value;
+		bytes_ptr = res->bytes_value;
+		mask_ptr = res->mask_value;
+
+		j = 0;
+		 /** translate bytes string to uint_32 array*/
+		if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+			(bytes_ptr[1] == 'X')))
+			bytes_ptr += 2;
+		len = strnlen(bytes_ptr, res->len_value * 2);
+		if (len == 0 || (len % 8 != 0)) {
+			printf("please check len and bytes input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = bytes_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			mod = i % 8;
+			if (i % 2) {
+				byte |= val;
+				dword |= byte << (4 * mod - 4);
+				byte = 0;
+			} else
+				byte |= val << 4;
+			if (mod == 7) {
+				filter.dwords[j] = dword;
+				printf("dwords[%d]:%08x ", j, filter.dwords[j]);
+				j++;
+				dword = 0;
+			}
+		}
+		printf("\n");
+		 /** translate mask string to uint8_t array*/
+		j = 0;
+		if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+			(mask_ptr[1] == 'X')))
+			mask_ptr += 2;
+		len = strnlen(mask_ptr, (res->len_value+3)/4);
+		if (len == 0) {
+			printf("invalid input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = mask_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			hex |= (uint8_t)(val & 0x8) >> 3;
+			hex |= (uint8_t)(val & 0x4) >> 1;
+			hex |= (uint8_t)(val & 0x2) << 1;
+			hex |= (uint8_t)(val & 0x1) << 3;
+			if (i % 2) {
+				byte |= hex << 4;
+				filter.mask[j] = byte;
+				printf("mask[%d]:%02x ", j, filter.mask[j]);
+				j++;
+				byte = 0;
+			} else
+				byte |= hex;
+			hex = 0;
+		}
+		printf("\n");
+		printf("call function rte_eth_dev_add_flex_filter: "
+			"index = %d, queue-id = %d, len = %d, priority = %d\n",
+			res->index_value, res->queue_id,
+			filter.len, filter.priority);
+		ret = rte_eth_dev_add_flex_filter(res->port_id, res->index_value,
+				&filter, res->queue_id);
+
+	} else if (!strcmp(res->filter, "remove_flex_filter"))
+		ret = rte_eth_dev_remove_flex_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_flex_filter"))
+		get_flex_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_len =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				len, "len");
+cmdline_parse_token_string_t cmd_flex_filter_len_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_flex_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_flex_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "add_flex_filter");
+cmdline_parse_inst_t cmd_add_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "add a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_add_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_len,
+		(void *)&cmd_flex_filter_len_value,
+		(void *)&cmd_flex_filter_bytes,
+		(void *)&cmd_flex_filter_bytes_value,
+		(void *)&cmd_flex_filter_mask,
+		(void *)&cmd_flex_filter_mask_value,
+		(void *)&cmd_flex_filter_priority,
+		(void *)&cmd_flex_filter_priority_value,
+		(void *)&cmd_flex_filter_queue,
+		(void *)&cmd_flex_filter_queue_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "remove_flex_filter");
+cmdline_parse_inst_t cmd_remove_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_remove_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "get_flex_filter");
+cmdline_parse_inst_t cmd_get_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "get a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_get_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -5235,6 +6125,21 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
 	(cmdline_parse_inst_t *)&cmd_dump,
 	(cmdline_parse_inst_t *)&cmd_dump_one,
+	(cmdline_parse_inst_t *)&cmd_add_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_get_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_add_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_get_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_add_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_get_flex_filter,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 20ad0a8..3c38f14 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1731,3 +1731,148 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 	       "diag=%d\n", port_id, diag);
 }
 
+void
+get_ethertype_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_ethertype_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_ethertype_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get ethertype filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    ethertype:  0x%04x\n",
+			rte_le_to_cpu_32(filter.ethertype));
+		printf("    priority: %s, %d\n",
+			filter.priority_en ? "enable" : "disable",
+			filter.priority);
+		printf("    queue: %d\n", rx_queue);
+	}
+}
+
+void
+get_syn_filter(uint8_t port_id)
+{
+	struct rte_syn_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+
+	if (ret < 0) {
+		printf("get syn filter fails(%s)\n", strerror(-ret));
+		return;
+	}
+	printf("syn filter: %s, priority: %s, queue: %d\n",
+		filter.enable ? "on" : "off",
+		filter.hig_pri ? "high" : "low",
+		rx_queue);
+}
+void
+get_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_2tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_2tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    Destination Port:     0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    protocol:  0x%02x     mask:%d     tcp_flags: 0x%02x\n",
+			filter.protocol, filter.protocol_mask ? 0 : 1,
+			filter.tcp_flags);
+		printf("    priority: %d    queue: %d\n",
+			filter.priority, rx_queue);
+	}
+}
+
+void
+get_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_5tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_5tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 5tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    Destination IP:  0x%08x    mask: %d\n",
+			(unsigned)rte_be_to_cpu_32(filter.dst_ip),
+			filter.dst_ip_mask ? 0 : 1);
+		printf("    Source IP:       0x%08x    mask: %d\n",
+			(unsigned)rte_be_to_cpu_32(filter.src_ip),
+			filter.src_ip_mask ? 0 : 1);
+		printf("    Destination Port:       0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    Source Port:       0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.src_port),
+			filter.src_port_mask ? 0 : 1);
+		printf("    protocol:           0x%02x    mask: %d\n",
+			filter.protocol,
+			filter.protocol_mask ? 0 : 1);
+		printf("    priority: %d    flags: 0x%02x    queue: %d\n",
+			filter.priority, filter.tcp_flags, rx_queue);
+	}
+}
+void
+get_flex_filter(uint8_t port_id, uint16_t index)
+
+{
+	struct rte_flex_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	int i, j;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_flex_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get flex filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]: ", index);
+		printf("\n    length: %d", filter.len);
+		printf("\n    dword[]: 0x");
+		for (i = 0; i < 32; i++)
+			printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i]));
+		printf("\n    mask[]: 0b");
+		for (i = 0; i < 16; i++) {
+			for (j = 0; j < 8; j++)
+				printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0');
+		}
+		printf("\n    priority: %d    queue: %d\n",
+			filter.priority, rx_queue);
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 2bdb1a2..c7998a6 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -528,6 +528,12 @@ void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
 void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, 
 		uint64_t vf_mask, uint8_t on);
 
+void get_syn_filter(uint8_t port_id);
+void get_ethertype_filter(uint8_t port_id, uint16_t index);
+void get_2tuple_filter(uint8_t port_id, uint16_t index);
+void get_5tuple_filter(uint8_t port_id, uint16_t index);
+void get_flex_filter(uint8_t port_id, uint16_t index);
+
 /*
  * Work-around of a compilation error with ICC on invocations of the
  * rte_be_to_cpu_16() function.
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of generic filter
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
@ 2014-05-27  7:57   ` Ming, LiX
  2014-05-27  9:18     ` Thomas Monjalon
  0 siblings, 1 reply; 22+ messages in thread
From: Ming, LiX @ 2014-05-27  7:57 UTC (permalink / raw)
  To: Wu, Jingjing, dev

This patch adds APIs for NIC filters list below:
ethertype filter, syn filter, 2tuple filter, flex filter, 5tuple filter

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 281 ++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 421 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 701 insertions(+), 1 deletion(-)

Test-by: lmingX  lix,ming@intel.com



Compile pass



     >>Compile OS: FC20 x86_64

     >>Kernel version: 3.11.10-301

     >>GCC version: 4.8.2

     >>Server: Crownpass


diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a5727dd..afd4fe8 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -41,6 +41,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 
 #include <rte_byteorder.h>
 #include <rte_log.h>
@@ -2335,3 +2336,283 @@ rte_eth_dev_bypass_wd_reset(uint8_t port_id)
 	return 0;
 }
 #endif
+
+int
+rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+			uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 1;
+	filter.hig_pri = high_pri;
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_syn_filter(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 0;
+	filter.hig_pri = 0;
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, 0);
+}
+
+int
+rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_syn_filter)(dev, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->ethertype == ETHER_TYPE_IPv4 ||
+		filter->ethertype == ETHER_TYPE_IPv6){
+		PMD_DEBUG_TRACE("IP and IPv6 are not supported"
+			" in ethertype filter\n");
+		return (-EINVAL);
+	}
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_ethertype_filter)(dev, index,
+					filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_ethertype_filter(uint8_t port_id,  uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_ethertype_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_ethertype_filter)(dev, index,
+						filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
+			" is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_2tuple_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value"
+			" is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_5tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_5tuple_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_5tuple_filter)(dev, index, filter,
+						rx_queue);
+}
+
+int
+rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_flex_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_flex_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
+						rx_queue);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d5ea46b..21257b2 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -808,6 +808,71 @@ struct rte_eth_dev_callback;
 /** @internal Structure to keep track of registered callbacks */
 TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 
+#define TCP_UGR_FLAG 0x20
+#define TCP_ACK_FLAG 0x10
+#define TCP_PSH_FLAG 0x08
+#define TCP_RST_FLAG 0x04
+#define TCP_SYN_FLAG 0x02
+#define TCP_FIN_FLAG 0x01
+#define TCP_FLAG_ALL 0x3F
+
+/**
+ *  A structure used to define an ethertype filter.
+ */
+struct rte_ethertype_filter {
+	uint16_t ethertype;  /**<little endian*/
+	uint8_t priority_en; /**<compare priority enable*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define an syn filter.
+ */
+struct rte_syn_filter {
+	uint8_t enable;  /**<1 means enable, 0 means disable*/
+	uint8_t hig_pri; /**< 1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower pri*/
+};
+
+/**
+ *  A structure used to define a 2tuple filter.
+ */
+struct rte_2tuple_filter {
+	uint16_t dst_port;  /**<big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**< used when more than one filter matches */
+	uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+		protocol_mask   : 1;
+};
+
+/**
+ *  A structure used to define a flex filter.
+ */
+struct rte_flex_filter {  /** for E1000 filters*/
+	uint16_t len;
+	uint32_t dwords[32];  /**<flex bytes in big endian*/
+	uint8_t mask[16];     /**<if mask bit is 1b, means compare corresponding byte in dwords*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define a 5tuple filter.
+ */
+struct rte_5tuple_filter {
+	uint32_t dst_ip;   /**<destination IP address in big endian*/
+	uint32_t src_ip;   /**<source IP address in big endian*/
+	uint16_t dst_port; /**<destination port in big endian*/
+	uint16_t src_port; /**<source Port big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**<seven evels (001b-111b),  111b is highest, used when more than one filter matches */
+	uint8_t dst_ip_mask   : 1, /**<if mask is 1b, do not compare dst ip*/
+		src_ip_mask   : 1, /**<if mask is 1b, do not compare src ip*/
+		dst_port_mask : 1, /**<if mask is 1b, do not compare dst port*/
+		src_port_mask : 1, /**<if mask is 1b, do not compare src port*/
+		protocol_mask   : 1; /**<if mask is 1b, do not compare protocol*/
+};
+
 /*
  * 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*
@@ -1076,6 +1141,69 @@ typedef int32_t (*bypass_ver_show_t)(struct rte_eth_dev *dev, uint32_t *ver);
 typedef int32_t (*bypass_wd_reset_t)(struct rte_eth_dev *dev);
 #endif
 
+typedef int (*eth_set_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+/**< @internal Set syn filter rule on an Ethernet device */
+
+typedef int (*eth_get_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+/**< @internal Get syn filter rule on an Ethernet device */
+
+typedef int (*eth_add_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_remove_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_get_ethertype_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_add_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_2tuple_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_2tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_2tuple_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_5tuple_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_5tuple_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_5tuple_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_flex_filter *filter,
+			uint8_t rx_queue);
+/**< @internal Setup a new flex filter rule on an Ethernet device */
+
+typedef int (*eth_remove_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index);
+/**< @internal Remove a flex filter rule on an Ethernet device */
+
+typedef int (*eth_get_flex_filter_t)(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_flex_filter *filter,
+			uint8_t *rx_queue);
+/**< @internal Get a flex filter rule on an Ethernet device */
 
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
@@ -1152,7 +1280,20 @@ struct eth_dev_ops {
   bypass_ver_show_t bypass_ver_show;
   bypass_wd_reset_t bypass_wd_reset;
 #endif
-
+	eth_set_syn_filter_t           set_syn_filter;  /**< set syn filter. */
+	eth_get_syn_filter_t           get_syn_filter;  /**< get syn filter. */
+	eth_add_ethertype_filter_t     add_ethertype_filter;  /**< add ethertype filter. */
+	eth_remove_ethertype_filter_t  remove_ethertype_filter;  /**< remove ethertype filter*/
+	eth_get_ethertype_filter_t     get_ethertype_filter;  /**< get ethertype filter*/
+	eth_add_2tuple_filter_t        add_2tuple_filter;  /**<add 2tuple filter */
+	eth_remove_2tuple_filter_t     remove_2tuple_filter;  /**< remove 2tuple filter*/
+	eth_get_2tuple_filter_t        get_2tuple_filter;  /**< get 2tuple filter*/
+	eth_add_5tuple_filter_t        add_5tuple_filter;  /**< add 5tuple filter*/
+	eth_remove_5tuple_filter_t     remove_5tuple_filter;  /**< remove 5tuple filter*/
+	eth_get_5tuple_filter_t        get_5tuple_filter;   /**< get 5tuple filter*/
+	eth_add_flex_filter_t        add_flex_filter;  /**< add flex filter*/
+	eth_remove_flex_filter_t     remove_flex_filter;  /**< remove flex filter*/
+	eth_get_flex_filter_t        get_flex_filter;  /**< get flex filter*/
 };
 
 /**
@@ -2725,6 +2866,284 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
  */
 int rte_eth_dev_bypass_wd_reset(uint8_t port);
 
+/**
+ * add syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param rx_queue
+ *   The index of RX queue where to store RX packets matching the syn filter.
+ * @param high_pri
+ *    1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+				uint8_t rx_queue);
+
+/**
+ * remove syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_remove_syn_filter(uint8_t port_id);
+
+/**
+ * get syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   The pointer to the structure describing the syn filter.
+ * @param rx_queue
+ *   the point of a int type to get the queue of syn filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @param filter
+ *   The pointer to the structure describing the ethertype filter rule.
+ *   The *rte_ethertype_filter* structure includes the values of the different
+ *   fields to match: ethertype and priority in vlan tag.
+ *   priority in vlan tag is not supported for E1000 dev.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+/**
+ * remove an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_ethertype_filter(uint8_t port_id,
+			uint16_t index);
+
+/**
+ * Get an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   A pointer to a structure of type *rte_ethertype_filter* to be filled with
+ *   the information of the Ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+/**
+ * Add a new 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 2tuple filter rule.
+ *   The *rte_2tuple_filter* structure includes the values of the different
+ *   fields to match: protocol, dst_port and
+ *   tcp_flags if the protocol is tcp type.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+
+int rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue);
+/**
+ * remove a 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_2tuple_filter* to be filled with
+ *   the information of the 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 5tuple filter rule.
+ *   The *rte_5tuple_filter* structure includes the values of the different fields
+ *   fields to match: dst src IP, dst src port, protocol and relative masks
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+
+/**
+ * remove a 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_5tuple_filter* to be filled with
+ *   the information of the 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   The pointer to the structure describing the flex filter rule.
+ *   The *rte_flex_filter* structure includes the values of the different fields
+ *   to match: the dwords (first len bytes of packet ) and relative masks.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue);
+/**
+ * remove a flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_flex_filter* to be filled with
+ *   the information of the flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature Jingjing Wu
@ 2014-05-27  7:59   ` Ming, LiX
  0 siblings, 0 replies; 22+ messages in thread
From: Ming, LiX @ 2014-05-27  7:59 UTC (permalink / raw)
  To: Wu, Jingjing, dev


This patch adds following igb NIC filters implement:
  syn filter, ethertype filter, 2tuple filter, flex filter for intel NIC 82580 and i350
  syn filter, ethertype filter, 5tuple filter for intel NIC 82576

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_e1000/e1000_ethdev.h |  53 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 745 ++++++++++++++++++++++++++++++++++++
 2 files changed, 798 insertions(+)

Test-by: lmingX  lix,ming@intel.com



Compile pass



     >>Compile OS: FC20 x86_64

     >>Kernel version: 3.11.10-301

     >>GCC version: 4.8.2

     >>Server: Crownpass

diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..239e849 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -52,6 +52,59 @@
 #define E1000_CTRL_EXT_EXTEND_VLAN  (1<<26)    /* EXTENDED VLAN */
 #define IGB_VFTA_SIZE 128
 
+#define IGB_MAX_RX_QUEUE_NUM           8
+#define IGB_MAX_RX_QUEUE_NUM_82576     16
+
+#define E1000_SYN_FILTER_ENABLE        0x00000001 /** syn filter enable field*/
+#define E1000_SYN_FILTER_QUEUE         0x0000000E /** syn filter queue field*/
+#define E1000_SYN_FILTER_QUEUE_SHIFT   1 /** syn filter queue field*/
+#define E1000_RFCTL_SYNQFP             0x00080000 /** SYNQFP in RFCTL register*/
+
+#define E1000_ETQF_ETHERTYPE           0x0000FFFF
+#define E1000_ETQF_QUEUE               0x00070000
+#define E1000_ETQF_QUEUE_SHIFT         16
+#define E1000_MAX_ETQF_FILTERS         8
+
+#define E1000_IMIR_DSTPORT             0x0000FFFF
+#define E1000_IMIR_PRIORITY            0xE0000000
+#define E1000_IMIR_EXT_SIZE_BP         0x00001000
+#define E1000_IMIR_EXT_CTRL_UGR        0x00002000
+#define E1000_IMIR_EXT_CTRL_ACK        0x00004000
+#define E1000_IMIR_EXT_CTRL_PSH        0x00008000
+#define E1000_IMIR_EXT_CTRL_RST        0x00010000
+#define E1000_IMIR_EXT_CTRL_SYN        0x00020000
+#define E1000_IMIR_EXT_CTRL_FIN        0x00040000
+#define E1000_IMIR_EXT_CTRL_BP         0x00080000
+#define E1000_MAX_TTQF_FILTERS         8
+#define E1000_2TUPLE_MAX_PRI           7
+
+#define E1000_MAX_FLEXIBLE_FILTERS       8
+#define E1000_MAX_FHFT                   4
+#define E1000_MAX_FHFT_EXT               4
+#define E1000_MAX_FLEX_FILTER_PRI        7
+#define E1000_MAX_FLEX_FILTER_LEN        128
+#define E1000_FHFT_QUEUEING_LEN          0x0000007F
+#define E1000_FHFT_QUEUEING_QUEUE        0x00000700
+#define E1000_FHFT_QUEUEING_PRIO         0x00070000
+#define E1000_FHFT_QUEUEING_OFFSET       0xFC
+#define E1000_FHFT_QUEUEING_QUEUE_SHIFT  8
+#define E1000_FHFT_QUEUEING_PRIO_SHIFT   16
+#define E1000_WUFC_FLEX_HQ               0x00004000
+
+#define E1000_SPQF_SRCPORT               0x0000FFFF /** src port field */
+
+#define E1000_MAX_FTQF_FILTERS           8
+#define E1000_FTQF_PROTOCOL_MASK         0x000000FF
+#define E1000_FTQF_5TUPLE_MASK_SHIFT     28
+#define E1000_FTQF_PROTOCOL_COMP_MASK    0x10000000
+#define E1000_FTQF_SOURCE_ADDR_MASK      0x20000000
+#define E1000_FTQF_DEST_ADDR_MASK        0x40000000
+#define E1000_FTQF_SOURCE_PORT_MASK      0x80000000
+#define E1000_FTQF_VF_MASK_EN            0x00008000
+#define E1000_FTQF_QUEUE_MASK            0x03ff0000
+#define E1000_FTQF_QUEUE_SHIFT           16
+#define E1000_FTQF_QUEUE_ENABLE          0x00000100
+
 /* structure for interrupt relative data */
 struct e1000_interrupt {
 	uint32_t flags;
diff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c
index 044eac3..1e63a8f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -124,6 +124,43 @@ static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 		struct rte_eth_rss_reta *reta_conf);
 
+static int eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -194,6 +231,20 @@ static struct eth_dev_ops eth_igb_ops = {
 	.mac_addr_remove      = eth_igb_rar_clear,
 	.reta_update          = eth_igb_rss_reta_update,
 	.reta_query           = eth_igb_rss_reta_query,
+	.set_syn_filter       = eth_igb_set_syn_filter,
+	.get_syn_filter          = eth_igb_get_syn_filter,
+	.add_ethertype_filter    = eth_igb_add_ethertype_filter,
+	.remove_ethertype_filter = eth_igb_remove_ethertype_filter,
+	.get_ethertype_filter    = eth_igb_get_ethertype_filter,
+	.add_2tuple_filter       = eth_igb_add_2tuple_filter,
+	.remove_2tuple_filter    = eth_igb_remove_2tuple_filter,
+	.get_2tuple_filter       = eth_igb_get_2tuple_filter,
+	.add_flex_filter         = eth_igb_add_flex_filter,
+	.remove_flex_filter      = eth_igb_remove_flex_filter,
+	.get_flex_filter         = eth_igb_get_flex_filter,
+	.add_5tuple_filter       = eth_igb_add_5tuple_filter,
+	.remove_5tuple_filter    = eth_igb_remove_5tuple_filter,
+	.get_5tuple_filter       = eth_igb_get_5tuple_filter,
 };
 
 /*
@@ -2184,6 +2235,700 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 	return 0;
 }
 
+#define MAC_TYPE_FILTER_SUP(type)    do {\
+	if ((type) != e1000_82580 && (type) != e1000_i350 &&\
+		(type) != e1000_82576)\
+		return -ENOSYS;\
+} while (0)
+
+/*
+ *set the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+
+	if (filter->enable) {
+		if (synqf & E1000_SYN_FILTER_ENABLE)
+			return (-EINVAL);
+		synqf = (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) &
+			E1000_SYN_FILTER_QUEUE) | E1000_SYN_FILTER_ENABLE);
+	} else
+		synqf = 0;
+
+	if (filter->hig_pri)
+		rfctl |= E1000_RFCTL_SYNQFP;
+	else
+		rfctl &= ~E1000_RFCTL_SYNQFP;
+
+	E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+	return 0;
+}
+
+/*
+ *get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	filter->enable = (synqf & E1000_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE) >>
+			E1000_SYN_FILTER_QUEUE_SHIFT);
+	return 0;
+}
+
+/*
+ *add an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+	else
+		etqf = 0;
+
+	etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
+	etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE);
+	etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT;
+
+	if (filter->priority_en) {
+		PMD_INIT_LOG(ERR, "vlan and priority (%d) is not support"
+			" in E1000.\n", filter->priority);
+		return (-EINVAL);
+	}
+
+	E1000_WRITE_REG(hw, E1000_ETQF(index), etqf);
+	return 0;
+}
+
+/*
+ *remove an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	E1000_WRITE_REG(hw, E1000_ETQF(index), 0);
+	return 0;
+}
+
+/*
+ *gets an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE) {
+		filter->ethertype = etqf & E1000_ETQF_ETHERTYPE;
+		filter->priority_en = 0;
+		*rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+#define MAC_TYPE_FILTER_SUP_EXT(type)    do {\
+	if ((type) != e1000_82580 && (type) != e1000_i350)\
+		return -ENOSYS; \
+} while (0)
+
+/*
+ *add a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ttqf, imir = 0;
+	uint32_t imir_ext = 0;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS ||
+		rx_queue >= IGB_MAX_RX_QUEUE_NUM ||
+		filter->priority > E1000_2TUPLE_MAX_PRI)
+		return (-EINVAL);  /**filter index is out of range*/
+	if  (filter->tcp_flags > TCP_FLAG_ALL)
+		return (-EINVAL);  /**flags is invalid*/
+
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+
+	imir = (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+	if (filter->dst_port_mask == 1) /**1b means not compare*/
+		imir |= E1000_IMIR_PORT_BP;
+	else
+		imir &= ~E1000_IMIR_PORT_BP;
+
+	imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+	ttqf = 0;
+	ttqf |= E1000_TTQF_QUEUE_ENABLE;
+	ttqf |= (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT);
+	ttqf |= (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK);
+	if (filter->protocol_mask == 1)
+		ttqf |= E1000_TTQF_MASK_ENABLE;
+	else
+		ttqf &= ~E1000_TTQF_MASK_ENABLE;
+
+	imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+	/*tcp flags bits setting*/
+	if (filter->tcp_flags & TCP_FLAG_ALL) {
+		if (filter->tcp_flags & TCP_UGR_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+		if (filter->tcp_flags & TCP_ACK_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+		if (filter->tcp_flags & TCP_PSH_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+		if (filter->tcp_flags & TCP_RST_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+		if (filter->tcp_flags & TCP_SYN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+		if (filter->tcp_flags & TCP_FIN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+		imir_ext &= ~E1000_IMIR_EXT_CTRL_BP;
+	} else
+		imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+	E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+	E1000_WRITE_REG(hw, E1000_TTQF(index), ttqf);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+	return 0;
+}
+
+/*
+ *remove a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+}
+
+/*
+ *get a 2tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t imir, ttqf, imir_ext;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
+	if (ttqf & E1000_TTQF_QUEUE_ENABLE) {
+		imir = E1000_READ_REG(hw, E1000_IMIR(index));
+		filter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;
+		filter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;
+		*rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >>
+				E1000_TTQF_QUEUE_SHIFT;
+		filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+		filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+		filter->priority = (imir & E1000_IMIR_PRIORITY) >>
+			E1000_IMIR_PRIORITY_SHIFT;
+
+		imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
+		if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
+			if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
+				filter->tcp_flags |= TCP_UGR_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
+				filter->tcp_flags |= TCP_ACK_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
+				filter->tcp_flags |= TCP_PSH_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
+				filter->tcp_flags |= TCP_RST_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
+				filter->tcp_flags |= TCP_SYN_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
+				filter->tcp_flags |= TCP_FIN_FLAG;
+		} else
+			filter->tcp_flags = 0;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *     - On failure, a negative value.
+ */
+static int
+eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, en_bits = 0;
+	uint32_t queueing = 0;
+	uint32_t reg_off = 0;
+	uint8_t i, j = 0;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN ||
+		filter->len % 8 != 0 ||
+		filter->priority > E1000_MAX_FLEX_FILTER_PRI)
+		return (-EINVAL);
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	en_bits = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+	if ((wufc & en_bits) == en_bits)
+		return (-EINVAL);  /**the filter is  enabled*/
+
+	E1000_WRITE_REG(hw, E1000_WUFC,
+		wufc | E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index));
+
+	j = 0;
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+	for (i = 0; i < 16; i++) {
+		E1000_WRITE_REG(hw, reg_off + i*4*4, filter->dwords[j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+1)*4, filter->dwords[++j]);
+		E1000_WRITE_REG(hw, reg_off + (i*4+2)*4,
+				(uint32_t)filter->mask[i]);
+		++j;
+	}
+	queueing |= filter->len |
+		(rx_queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) |
+		(filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT);
+	E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing);
+	return 0;
+}
+
+/*
+ *remove a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+				uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, reg_off = 0;
+	uint8_t i;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc & (~(E1000_WUFC_FLX0 << index)));
+
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+	for (i = 0; i < 64; i++)
+		E1000_WRITE_REG(hw, reg_off + i*4, 0);
+	return 0;
+}
+
+/*
+ *get a flex filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: the pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, queueing, wufc_en = 0;
+	uint8_t i, j;
+
+	MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	wufc_en = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+
+	if ((wufc & wufc_en) == wufc_en) {
+		uint32_t reg_off = 0;
+		j = 0;
+		if (index < E1000_MAX_FHFT)
+			reg_off = E1000_FHFT(index);
+		else
+			reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+
+		for (i = 0; i < 16; i++, j = i * 2) {
+			filter->dwords[j] =
+				E1000_READ_REG(hw, reg_off + i*4*4);
+			filter->dwords[j+1] =
+				E1000_READ_REG(hw, reg_off + (i*4+1)*4);
+			filter->mask[i] =
+				E1000_READ_REG(hw, reg_off + (i*4+2)*4);
+		}
+		queueing = E1000_READ_REG(hw,
+				reg_off + E1000_FHFT_QUEUEING_OFFSET);
+		filter->len = queueing & E1000_FHFT_QUEUEING_LEN;
+		filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >>
+			E1000_FHFT_QUEUEING_PRIO_SHIFT;
+		*rx_queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >>
+			E1000_FHFT_QUEUEING_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, spqf = 0;
+	uint32_t imir = 0;
+	uint32_t imir_ext = 0;
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS ||
+		rx_queue >= IGB_MAX_RX_QUEUE_NUM_82576)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
+	if (ftqf & E1000_FTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /**filter index is in use*/
+
+	ftqf = 0;
+	ftqf |= filter->protocol & E1000_FTQF_PROTOCOL_MASK;
+	if (filter->src_ip_mask == 1) /** 1b means not compare*/
+		ftqf |= E1000_FTQF_SOURCE_ADDR_MASK;
+	if (filter->dst_ip_mask == 1)
+		ftqf |= E1000_FTQF_DEST_ADDR_MASK;
+	if (filter->src_port_mask == 1)
+		ftqf |= E1000_FTQF_SOURCE_PORT_MASK;
+	if (filter->protocol_mask == 1)
+		ftqf |= E1000_FTQF_PROTOCOL_COMP_MASK;
+	ftqf |= (rx_queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK;
+	ftqf |= E1000_FTQF_VF_MASK_EN;
+	ftqf |= E1000_FTQF_QUEUE_ENABLE;
+	E1000_WRITE_REG(hw, E1000_FTQF(index), ftqf);
+	E1000_WRITE_REG(hw, E1000_DAQF(index), filter->dst_ip);
+	E1000_WRITE_REG(hw, E1000_SAQF(index), filter->src_ip);
+
+	spqf |= filter->src_port & E1000_SPQF_SRCPORT;
+	E1000_WRITE_REG(hw, E1000_SPQF(index), spqf);
+
+	imir |= (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
+	if (filter->dst_port_mask == 1) /**1b means not compare*/
+		imir |= E1000_IMIR_PORT_BP;
+	else
+		imir &= ~E1000_IMIR_PORT_BP;
+	imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+
+	imir_ext |= E1000_IMIR_EXT_SIZE_BP;
+	/*tcp flags bits setting*/
+	if (filter->tcp_flags & TCP_FLAG_ALL) {
+		if (filter->tcp_flags & TCP_UGR_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
+		if (filter->tcp_flags & TCP_ACK_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
+		if (filter->tcp_flags & TCP_PSH_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
+		if (filter->tcp_flags & TCP_RST_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_RST;
+		if (filter->tcp_flags & TCP_SYN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
+		if (filter->tcp_flags & TCP_FIN_FLAG)
+			imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
+	} else
+		imir_ext |= E1000_IMIR_EXT_CTRL_BP;
+	E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
+	return 0;
+}
+
+/*
+ *remove a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
+				uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	E1000_WRITE_REG(hw, E1000_FTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_DAQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_SAQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_SPQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+}
+
+/*
+ *get a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t spqf, ftqf, imir, imir_ext;
+
+	if (hw->mac.type != e1000_82576)
+		return (-ENOSYS);
+
+	if (index >= E1000_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+
+	ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
+	if (ftqf & E1000_FTQF_QUEUE_ENABLE) {
+		filter->src_ip_mask =
+			(ftqf & E1000_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
+		filter->dst_ip_mask =
+			(ftqf & E1000_FTQF_DEST_ADDR_MASK) ? 1 : 0;
+		filter->src_port_mask =
+			(ftqf & E1000_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
+		filter->protocol_mask =
+			(ftqf & E1000_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
+		filter->protocol =
+			(uint8_t)ftqf & E1000_FTQF_PROTOCOL_MASK;
+		*rx_queue = (uint8_t)((ftqf & E1000_FTQF_QUEUE_MASK) >>
+				E1000_FTQF_QUEUE_SHIFT);
+
+		spqf = E1000_READ_REG(hw, E1000_SPQF(index));
+		filter->src_port = spqf & E1000_SPQF_SRCPORT;
+
+		filter->dst_ip = E1000_READ_REG(hw, E1000_DAQF(index));
+		filter->src_ip = E1000_READ_REG(hw, E1000_SAQF(index));
+
+		imir = E1000_READ_REG(hw, E1000_IMIR(index));
+		filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
+		filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
+		filter->priority = (imir & E1000_IMIR_PRIORITY) >>
+			E1000_IMIR_PRIORITY_SHIFT;
+
+		imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
+		if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
+			if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
+				filter->tcp_flags |= TCP_UGR_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
+				filter->tcp_flags |= TCP_ACK_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
+				filter->tcp_flags |= TCP_PSH_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
+				filter->tcp_flags |= TCP_RST_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
+				filter->tcp_flags |= TCP_SYN_FLAG;
+			if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
+				filter->tcp_flags |= TCP_FIN_FLAG;
+		} else
+			filter->tcp_flags = 0;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
 static struct rte_driver pmd_igb_drv = {
 	.type = PMD_PDEV,
 	.init = rte_igb_pmd_init,
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe NIC filters of generic filter feature
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe " Jingjing Wu
@ 2014-05-27  8:00   ` Ming, LiX
  0 siblings, 0 replies; 22+ messages in thread
From: Ming, LiX @ 2014-05-27  8:00 UTC (permalink / raw)
  To: Wu, Jingjing, dev

This patch adds following ixgbe NIC filters implement:
  syn filter, ethertype filter, 5tuple filter for intel NIC 82599

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 409 ++++++++++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  33 +++
 2 files changed, 442 insertions(+)
Test-by: lmingX  lix,ming@intel.com



Compile pass



     >>Compile OS: FC20 x86_64

     >>Kernel version: 3.11.10-301

     >>GCC version: 4.8.2

     >>Server: Crownpass
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index c9b5fe4..340c7cb 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 #include <rte_byteorder.h>
 #include <rte_common.h>
 #include <rte_cycles.h>
@@ -182,6 +183,23 @@ static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
 		uint8_t	rule_id);
 
+static int ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue);
+static int ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index);
+static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -301,6 +319,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.bypass_ver_show      = ixgbe_bypass_ver_show,
 	.bypass_wd_reset      = ixgbe_bypass_wd_reset,
 #endif /* RTE_NIC_BYPASS */
+	.set_syn_filter	         = ixgbe_set_syn_filter,
+	.get_syn_filter          = ixgbe_get_syn_filter,
+	.add_ethertype_filter    = ixgbe_add_ethertype_filter,
+	.remove_ethertype_filter = ixgbe_remove_ethertype_filter,
+	.get_ethertype_filter    = ixgbe_get_ethertype_filter,
+	.add_5tuple_filter       = ixgbe_add_5tuple_filter,
+	.remove_5tuple_filter    = ixgbe_remove_5tuple_filter,
+	.get_5tuple_filter       = ixgbe_get_5tuple_filter,
 };
 
 /*
@@ -3062,6 +3088,389 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
 	return 0;
 }
 
+/*
+ * set the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+
+	if (filter->enable)
+		synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
+			IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE);
+	else
+		synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
+
+	if (filter->hig_pri)
+		synqf |= IXGBE_SYN_FILTER_SYNQFP;
+	else
+		synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
+	return 0;
+}
+
+/*
+ * get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	filter->enable = (synqf & IXGBE_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1);
+	return 0;
+}
+
+/*
+ * add an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_add_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs = 0;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS ||
+		rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN)
+		return (-EINVAL);  /** filter index is in use*/
+
+	etqf = 0;
+	etqf |= IXGBE_ETQF_FILTER_EN;
+	etqf |= (uint32_t)filter->ethertype;
+
+	if (filter->priority_en) {
+		if (filter->priority > IXGBE_ETQF_MAX_PRI)
+			return (-EINVAL);
+		etqf |= (uint32_t)((filter->priority << IXGBE_ETQF_SHIFT) & IXGBE_ETQF_UP);
+		etqf |= IXGBE_ETQF_UP_EN;
+	}
+	etqs |= (uint32_t)((rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE);
+	etqs |= IXGBE_ETQS_QUEUE_EN;
+
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), etqf);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), etqs);
+	return 0;
+}
+
+/*
+ * remove an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), 0);
+
+	return 0;
+}
+
+/*
+ * gets an ethertype filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index, struct rte_ethertype_filter *filter,
+			uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN) {
+		filter->ethertype = etqf & IXGBE_ETQF_ETHERTYPE;
+		filter->priority_en = (etqf & IXGBE_ETQF_UP_EN) ? 1 : 0;
+		if (filter->priority_en)
+			filter->priority = (etqf & IXGBE_ETQF_UP) >> 16;
+		*rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+static inline enum ixgbe_5tuple_protocol
+convert_protocol_type(uint8_t protocol_value)
+{
+	if (protocol_value == IPPROTO_TCP)
+		return IXGBE_FILTER_PROTOCOL_TCP;
+	else if (protocol_value == IPPROTO_UDP)
+		return IXGBE_FILTER_PROTOCOL_UDP;
+	else if (protocol_value == IPPROTO_SCTP)
+		return IXGBE_FILTER_PROTOCOL_SCTP;
+	else
+		return IXGBE_FILTER_PROTOCOL_NONE;
+}
+
+static inline uint8_t
+revert_protocol_type(enum ixgbe_5tuple_protocol protocol)
+{
+	if (protocol == IXGBE_FILTER_PROTOCOL_TCP)
+		return IPPROTO_TCP;
+	else if (protocol == IXGBE_FILTER_PROTOCOL_UDP)
+		return IPPROTO_UDP;
+	else if (protocol == IXGBE_FILTER_PROTOCOL_SCTP)
+		return IPPROTO_SCTP;
+	else
+		return 0;
+}
+
+/*
+ * add a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, sdpqf = 0;
+	uint32_t l34timir = 0;
+	uint8_t mask = 0xff;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS ||
+		rx_queue >= IXGBE_MAX_RX_QUEUE_NUM ||
+		filter->priority > IXGBE_5TUPLE_MAX_PRI ||
+		filter->priority < IXGBE_5TUPLE_MIN_PRI)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	if (filter->tcp_flags) {
+		PMD_INIT_LOG(INFO, "82599EB not tcp flags in 5tuple");
+		return (-EINVAL);
+	}
+
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBE_FTQF_QUEUE_ENABLE)
+		return (-EINVAL);  /** filter index is in use*/
+
+	ftqf = 0;
+	sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDPQF_DSTPORT_SHIFT);
+	sdpqf = sdpqf | (filter->src_port & IXGBE_SDPQF_SRCPORT);
+
+	ftqf |= (uint32_t)(convert_protocol_type(filter->protocol) &
+		IXGBE_FTQF_PROTOCOL_MASK);
+	ftqf |= (uint32_t)((filter->priority & IXGBE_FTQF_PRIORITY_MASK) <<
+		IXGBE_FTQF_PRIORITY_SHIFT);
+	if (filter->src_ip_mask == 0) /** 0 means compare*/
+		mask &= IXGBE_FTQF_SOURCE_ADDR_MASK;
+	if (filter->dst_ip_mask == 0)
+		mask &= IXGBE_FTQF_DEST_ADDR_MASK;
+	if (filter->src_port_mask == 0)
+		mask &= IXGBE_FTQF_SOURCE_PORT_MASK;
+	if (filter->dst_port_mask == 0)
+		mask &= IXGBE_FTQF_DEST_PORT_MASK;
+	if (filter->protocol_mask == 0)
+		mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK;
+	ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT;
+	ftqf |= IXGBE_FTQF_POOL_MASK_EN;
+	ftqf |= IXGBE_FTQF_QUEUE_ENABLE;
+
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf);
+
+	l34timir |= IXGBE_L34T_IMIR_RESERVE;
+	l34timir |= (uint32_t)(rx_queue << IXGBE_L34T_IMIR_QUEUE_SHIFT);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), l34timir);
+	return 0;
+}
+
+/*
+ * remove a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0);
+	return 0;
+}
+
+/*
+ * get a 5tuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t sdpqf, ftqf, l34timir;
+	uint8_t mask;
+	enum ixgbe_5tuple_protocol proto;
+
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (index >= IXGBE_MAX_FTQF_FILTERS)
+		return (-EINVAL);  /** filter index is out of range*/
+
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) {
+		proto = (enum ixgbe_5tuple_protocol)(ftqf & IXGBE_FTQF_PROTOCOL_MASK);
+		filter->protocol = revert_protocol_type(proto);
+		filter->priority = (ftqf >> IXGBE_FTQF_PRIORITY_SHIFT) &
+					IXGBE_FTQF_PRIORITY_MASK;
+		mask = (uint8_t)((ftqf >> IXGBE_FTQF_5TUPLE_MASK_SHIFT) &
+					IXGBE_FTQF_5TUPLE_MASK_MASK);
+		filter->src_ip_mask =
+			(mask & IXGBE_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
+		filter->dst_ip_mask =
+			(mask & IXGBE_FTQF_DEST_ADDR_MASK) ? 1 : 0;
+		filter->src_port_mask =
+			(mask & IXGBE_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
+		filter->dst_port_mask =
+			(mask & IXGBE_FTQF_DEST_PORT_MASK) ? 1 : 0;
+		filter->protocol_mask =
+			(mask & IXGBE_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
+
+		sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index));
+		filter->dst_port = (sdpqf & IXGBE_SDPQF_DSTPORT) >>
+					IXGBE_SDPQF_DSTPORT_SHIFT;
+		filter->src_port = sdpqf & IXGBE_SDPQF_SRCPORT;
+		filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index));
+		filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index));
+
+		l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index));
+		*rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >>
+					IXGBE_L34T_IMIR_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
 static struct rte_driver rte_ixgbe_driver = {
 	.type = PMD_PDEV,
 	.init = rte_ixgbe_pmd_init,
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..c5c2845 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -67,6 +67,29 @@
 #define IXGBE_LPBK_82599_NONE		0x0 /* Default value. Loopback is disabled. */
 #define IXGBE_LPBK_82599_TX_RX		0x1 /* Tx->Rx loopback operation is enabled. */
 
+#define IXGBE_SYN_FILTER_ENABLE         0x00000001 /** syn filter enable field*/
+#define IXGBE_SYN_FILTER_QUEUE          0x000000FE /** syn filter queue field*/
+#define IXGBE_SYN_FILTER_QUEUE_SHIFT    1        /** syn filter queue field shift*/
+#define IXGBE_SYN_FILTER_SYNQFP         0x80000000 /**syn filter SYNQFP*/
+
+#define IXGBE_ETQF_UP                   0x00070000 /** ethertype filter priority field*/
+#define IXGBE_ETQF_SHIFT                16
+#define IXGBE_ETQF_UP_EN                0x00080000
+#define IXGBE_ETQF_ETHERTYPE            0x0000FFFF /** ethertype filter ethertype field*/
+#define IXGBE_ETQF_MAX_PRI              7
+
+#define IXGBE_SDPQF_DSTPORT             0xFFFF0000 /** dst port field */
+#define IXGBE_SDPQF_DSTPORT_SHIFT       16 /** dst port field shift*/
+#define IXGBE_SDPQF_SRCPORT             0x0000FFFF /** src port field */
+
+#define IXGBE_L34T_IMIR_SIZE_BP         0x00001000
+#define IXGBE_L34T_IMIR_RESERVE         0x00080000 /** bit 13 to 19 must be set to 1000000b*/
+#define IXGBE_L34T_IMIR_LLI             0x00100000
+#define IXGBE_L34T_IMIR_QUEUE           0x0FE00000
+#define IXGBE_L34T_IMIR_QUEUE_SHIFT     21
+#define IXGBE_5TUPLE_MAX_PRI            7
+#define IXGBE_5TUPLE_MIN_PRI            1
+
 /*
  * Information about the fdir mode.
  */
@@ -150,6 +173,16 @@ struct ixgbe_adapter {
 #endif /* RTE_NIC_BYPASS */
 };
 
+/*
+ *  Possible l4type of 5tuple filters.
+ */
+enum ixgbe_5tuple_protocol {
+	IXGBE_FILTER_PROTOCOL_TCP = 0,
+	IXGBE_FILTER_PROTOCOL_UDP,
+	IXGBE_FILTER_PROTOCOL_SCTP,
+	IXGBE_FILTER_PROTOCOL_NONE,
+};
+
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
 	(&((struct ixgbe_adapter *)adapter)->hw)
 
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
@ 2014-05-27  8:00   ` Ming, LiX
  0 siblings, 0 replies; 22+ messages in thread
From: Ming, LiX @ 2014-05-27  8:00 UTC (permalink / raw)
  To: Wu, Jingjing, dev


add commands in testpmd for NIC filters:
add_ethertype_filter
remove_ethertype_filter
get_ethertype_filter
add_2tuple_filter
remove_2tuple_filter
get_2tuple_filter
add_5tuple_filter
remove_5tuple_filter
get_5tuple_filter
add_syn_filter
remove_syn_filter
get_syn_filter
add_flex_filter
remove_flex_filter
get_flex_filter

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 app/test-pmd/cmdline.c | 907 ++++++++++++++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c  | 145 ++++++++
 app/test-pmd/testpmd.h |   6 +
 3 files changed, 1057 insertions(+), 1 deletion(-)

Test-by: lmingX  lix,ming@intel.com



Compile pass



     >>Compile OS: FC20 x86_64

     >>Kernel version: 3.11.10-301

     >>GCC version: 4.8.2

     >>Server: Crownpass

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b3824f9..6bdfa6b 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -113,6 +113,7 @@ static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
 		"    help ports      : Configuring ports.\n"
 		"    help flowdir    : Flow Director filter help.\n"
 		"    help registers  : Reading and setting port registers.\n"
+		"    help filters    : Filters configuration help.\n"
 		"    help all        : All of the above sections.\n\n"
 	);
 
@@ -543,6 +544,67 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"    Set single bit value of a port register.\n\n"
 		);
 	}
+	if (show_all || !strcmp(res->section, "filters")) {
+
+		cmdline_printf(
+			cl,
+			"\n"
+			"filters:\n"
+			"----------\n\n"
+
+			"add_ethertype_filter (port_id) ethertype (eth_value)"
+			" priority (enable|disable)(pri_value) queue (queue_id) index (idx)\n"
+			"    add an ethertype filter.\n\n"
+
+			"remove_ethertype_filter (port_id) index (idx)\n"
+			"    remove an ethertype filter.\n\n"
+
+			"get_ethertype_filter (port_id) index (idx)\n"
+			"    get info of a ethertype filter.\n\n"
+
+			"add_2tuple_filter (port_id) protocol (pro_value) (pro_mask)"
+			" dst_port (port_value) (port_mask) flags (flg_value) priority (prio_value)"
+			" queue (queue_id) index (idx)\n"
+			"    add a 2tuple filter.\n\n"
+
+			"remove_2tuple_filter (port_id) index (idx)\n"
+			"    remove a 2tuple filter.\n\n"
+
+			"get_2tuple_filter (port_id) index (idx)\n"
+			"    get info of a 2tuple filter.\n\n"
+
+			"add_5tuple_filter (port_id) dst_ip (dst_address) src_ip (src_address)"
+			" dst_port (dst_port_value) src_port (src_port_value) protocol (protocol_value)"
+			" mask (mask_value) flags (flags_value) priority (prio_value)"
+			" queue (queue_id) index (idx)\n"
+			"    add a 5tuple filter.\n\n"
+
+			"remove_5tuple_filter (port_id) index (idx)\n"
+			"    remove a 5tuple filter.\n\n"
+
+			"get_5tuple_filter (port_id) index (idx)\n"
+			"    get info of a 5tuple filter.\n\n"
+
+			"add_syn_filter (port_id) priority (high|low) queue (queue_id)"
+			"    add syn filter.\n\n"
+
+			"remove_syn_filter (port_id)"
+			"    remove syn filter.\n\n"
+
+			"get_syn_filter (port_id) "
+			"    get syn filter info.\n\n"
+
+			"add_flex_filter (port_id) len (len_value) bytes (bytes_string) mask (mask_value)"
+			" priority (prio_value) queue (queue_id) index (idx)\n"
+			"    add a flex filter.\n\n"
+
+			"remove_flex_filter (port_id) index (idx)\n"
+			"    remove a flex filter.\n\n"
+
+			"get_flex_filter (port_id) index (idx)\n"
+			"    get info of a flex filter.\n\n"
+		);
+	}
 }
 
 cmdline_parse_token_string_t cmd_help_long_help =
@@ -551,7 +613,7 @@ cmdline_parse_token_string_t cmd_help_long_help =
 cmdline_parse_token_string_t cmd_help_long_section =
 	TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
 			"all#control#display#config#flowdir#"
-			"ports#registers");
+			"ports#registers#filters");
 
 cmdline_parse_inst_t cmd_help_long = {
 	.f = cmd_help_long_parsed,
@@ -5152,6 +5214,834 @@ cmdline_parse_inst_t cmd_dump_one = {
 	},
 };
 
+/* *** ADD/REMOVE an ethertype FILTER *** */
+struct cmd_ethertype_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t ethertype;
+	uint16_t ethertype_value;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t priority_en;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_ethertype_filter_result *res = parsed_result;
+	struct rte_ethertype_filter filter;
+
+	memset(&filter, 0, sizeof(struct rte_ethertype_filter));
+	filter.ethertype = rte_cpu_to_le_16(res->ethertype_value);
+	filter.priority = res->priority_value;
+
+	if (!strcmp(res->priority_en, "enable"))
+		filter.priority_en = 1;
+	if (!strcmp(res->filter, "add_ethertype_filter"))
+		ret = rte_eth_dev_add_ethertype_filter(res->port_id,
+				res->index_value,
+				&filter, res->queue_id);
+	else if (!strcmp(res->filter, "remove_ethertype_filter"))
+		ret = rte_eth_dev_remove_ethertype_filter(res->port_id,
+				res->index_value);
+	else if (!strcmp(res->filter, "get_ethertype_filter"))
+		get_ethertype_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("ethertype filter setting error: (%s)\n",
+			strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				ethertype, "ethertype");
+cmdline_parse_token_ipaddr_t cmd_ethertype_filter_ethertype_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority, "priority");
+cmdline_parse_token_string_t cmd_ethertype_filter_priority_en =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority_en, "enable#disable");
+cmdline_parse_token_num_t cmd_ethertype_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_ethertype_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				filter, "add_ethertype_filter");
+cmdline_parse_inst_t cmd_add_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "add an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_add_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_ethertype,
+		(void *)&cmd_ethertype_filter_ethertype_value,
+		(void *)&cmd_ethertype_filter_priority,
+		(void *)&cmd_ethertype_filter_priority_en,
+		(void *)&cmd_ethertype_filter_priority_value,
+		(void *)&cmd_ethertype_filter_queue,
+		(void *)&cmd_ethertype_filter_queue_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "remove_ethertype_filter");
+cmdline_parse_inst_t cmd_remove_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "remove an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_remove_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_ethertype_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "get_ethertype_filter");
+cmdline_parse_inst_t cmd_get_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "get an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_get_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** set SYN filter *** */
+struct cmd_set_syn_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t high;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+};
+
+static void
+cmd_set_syn_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_set_syn_filter_result *res = parsed_result;
+	if (!strcmp(res->filter, "add_syn_filter")) {
+		if (!strcmp(res->high, "high"))
+			ret = rte_eth_dev_add_syn_filter(res->port_id,
+				1, res->queue_id);
+		else
+			ret = rte_eth_dev_add_syn_filter(res->port_id,
+				0, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_syn_filter"))
+		ret = rte_eth_dev_remove_syn_filter(res->port_id);
+	else if (!strcmp(res->filter, "get_syn_filter"))
+		get_syn_filter(res->port_id);
+	if (ret < 0)
+		printf("syn filter setting error: (%s)\n", strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_syn_filter_portid =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "add_syn_filter");
+cmdline_parse_token_string_t cmd_syn_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "remove_syn_filter");
+cmdline_parse_inst_t cmd_add_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "add syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_add_filter,
+			(void *)&cmd_syn_filter_portid,
+			(void *)&cmd_syn_filter_priority,
+			(void *)&cmd_syn_filter_high,
+			(void *)&cmd_syn_filter_queue,
+			(void *)&cmd_syn_filter_queue_id,
+			NULL,
+		},
+};
+cmdline_parse_inst_t cmd_remove_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "remove syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_remove_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+cmdline_parse_token_string_t cmd_syn_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "get_syn_filter");
+
+cmdline_parse_inst_t cmd_get_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "get syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_get_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	uint8_t protocol_mask;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	uint16_t dst_port_mask;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_2tuple_filter filter;
+	struct cmd_2tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_2tuple_filter));
+
+	if (!strcmp(res->filter, "add_2tuple_filter")) {
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.protocol = res->protocol_value;
+		filter.dst_port_mask = (res->dst_port_mask) ? 0 : 1;
+		filter.protocol_mask = (res->protocol_mask) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+		ret = rte_eth_dev_add_2tuple_filter(res->port_id,
+			res->index_value, &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_2tuple_filter"))
+		ret = rte_eth_dev_remove_2tuple_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_2tuple_filter"))
+		get_2tuple_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("2tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol, "protocol");
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol_value, UINT8);
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				protocol_mask, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port_value, UINT16);
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				dst_port_mask, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				flags, "flags");
+cmdline_parse_token_string_t cmd_2tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_2tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "add_2tuple_filter");
+cmdline_parse_inst_t cmd_add_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_add_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_protocol,
+		(void *)&cmd_2tuple_filter_protocol_value,
+		(void *)&cmd_2tuple_filter_protocol_mask,
+		(void *)&cmd_2tuple_filter_dst_port,
+		(void *)&cmd_2tuple_filter_dst_port_value,
+		(void *)&cmd_2tuple_filter_dst_port_mask,
+		(void *)&cmd_2tuple_filter_flags,
+		(void *)&cmd_2tuple_filter_flags_value,
+		(void *)&cmd_2tuple_filter_priority,
+		(void *)&cmd_2tuple_filter_priority_value,
+		(void *)&cmd_2tuple_filter_queue,
+		(void *)&cmd_2tuple_filter_queue_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_2tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "remove_2tuple_filter");
+cmdline_parse_inst_t cmd_remove_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_remove_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_2tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				filter, "get_2tuple_filter");
+cmdline_parse_inst_t cmd_get_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_get_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t dst_ip;
+	cmdline_ipaddr_t dst_ip_value;
+	cmdline_fixed_string_t src_ip;
+	cmdline_ipaddr_t src_ip_value;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	cmdline_fixed_string_t src_port;
+	uint16_t src_port_value;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	cmdline_fixed_string_t mask;
+	uint8_t  mask_value;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_5tuple_filter_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_5tuple_filter filter;
+	struct cmd_5tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_5tuple_filter));
+
+	if (!strcmp(res->filter, "add_5tuple_filter")) {
+		filter.dst_ip_mask = (res->mask_value & 0x10) ? 0 : 1;
+		filter.src_ip_mask = (res->mask_value & 0x08) ? 0 : 1;
+		filter.dst_port_mask = (res->mask_value & 0x04) ? 0 : 1;
+		filter.src_port_mask = (res->mask_value & 0x02) ? 0 : 1;
+		filter.protocol = res->protocol_value;
+		filter.protocol_mask = (res->mask_value & 0x01) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+
+		if (res->dst_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr;
+		else {
+			if (filter.dst_ip_mask == 0) {
+				printf("can not support ipv6 involved compare.\n");
+				return;
+			}
+			filter.dst_ip = 0;
+		}
+
+		if (res->src_ip_value.family == AF_INET)
+			/** no need to convert, already big endian*/
+			filter.src_ip = res->src_ip_value.addr.ipv4.s_addr;
+		else {
+			if (filter.src_ip_mask == 0) {
+				printf("can not support ipv6 involved compare.\n");
+				return;
+			}
+			filter.src_ip = 0;
+		}
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.src_port = rte_cpu_to_be_16(res->src_port_value);
+
+		ret = rte_eth_dev_add_5tuple_filter(res->port_id,
+			res->index_value, &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_5tuple_filter"))
+		ret = rte_eth_dev_remove_5tuple_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_5tuple_filter"))
+		get_5tuple_filter(res->port_id, res->index_value);
+	if (ret < 0)
+		printf("5tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+
+cmdline_parse_token_num_t cmd_5tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_ip, "dst_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_ip =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_ip, "src_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_port, "src_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				src_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				protocol, "protocol");
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				mask, "mask");
+cmdline_parse_token_num_t cmd_5tuple_filter_mask_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				mask_value, INT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				flags, "flags");
+cmdline_parse_token_num_t cmd_5tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				flags_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_5tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+				index_value, UINT16);
+
+cmdline_parse_token_string_t cmd_5tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "add_5tuple_filter");
+cmdline_parse_inst_t cmd_add_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_add_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_dst_ip,
+		(void *)&cmd_5tuple_filter_dst_ip_value,
+		(void *)&cmd_5tuple_filter_src_ip,
+		(void *)&cmd_5tuple_filter_src_ip_value,
+		(void *)&cmd_5tuple_filter_dst_port,
+		(void *)&cmd_5tuple_filter_dst_port_value,
+		(void *)&cmd_5tuple_filter_src_port,
+		(void *)&cmd_5tuple_filter_src_port_value,
+		(void *)&cmd_5tuple_filter_protocol,
+		(void *)&cmd_5tuple_filter_protocol_value,
+		(void *)&cmd_5tuple_filter_mask,
+		(void *)&cmd_5tuple_filter_mask_value,
+		(void *)&cmd_5tuple_filter_flags,
+		(void *)&cmd_5tuple_filter_flags_value,
+		(void *)&cmd_5tuple_filter_priority,
+		(void *)&cmd_5tuple_filter_priority_value,
+		(void *)&cmd_5tuple_filter_queue,
+		(void *)&cmd_5tuple_filter_queue_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				filter, "remove_5tuple_filter");
+cmdline_parse_inst_t cmd_remove_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_remove_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				filter, "get_5tuple_filter");
+cmdline_parse_inst_t cmd_get_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_get_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t len;
+	uint8_t len_value;
+	cmdline_fixed_string_t bytes;
+	cmdline_fixed_string_t bytes_value;
+	cmdline_fixed_string_t mask;
+	cmdline_fixed_string_t mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t index_value;
+};
+
+static int xdigit2val(unsigned char c)
+{
+	int val;
+	if (isdigit(c))
+		val = c - '0';
+	else if (isupper(c))
+		val = c - 'A' + 10;
+	else
+		val = c - 'a' + 10;
+	return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_flex_filter filter;
+	struct cmd_flex_filter_result *res = parsed_result;
+	char *bytes_ptr, *mask_ptr;
+	uint16_t len, i, j;
+	char c;
+	int val, mod = 0;
+	uint32_t dword = 0;
+	uint8_t byte = 0;
+	uint8_t hex = 0;
+
+	if (!strcmp(res->filter, "add_flex_filter")) {
+		if (res->len_value > 128) {
+			printf("the len exceed the max length 128\n");
+			return;
+		}
+		memset(&filter, 0, sizeof(struct rte_flex_filter));
+		filter.len = res->len_value;
+		filter.priority = res->priority_value;
+		bytes_ptr = res->bytes_value;
+		mask_ptr = res->mask_value;
+
+		j = 0;
+		 /** translate bytes string to uint_32 array*/
+		if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+			(bytes_ptr[1] == 'X')))
+			bytes_ptr += 2;
+		len = strnlen(bytes_ptr, res->len_value * 2);
+		if (len == 0 || (len % 8 != 0)) {
+			printf("please check len and bytes input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = bytes_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			mod = i % 8;
+			if (i % 2) {
+				byte |= val;
+				dword |= byte << (4 * mod - 4);
+				byte = 0;
+			} else
+				byte |= val << 4;
+			if (mod == 7) {
+				filter.dwords[j] = dword;
+				printf("dwords[%d]:%08x ", j, filter.dwords[j]);
+				j++;
+				dword = 0;
+			}
+		}
+		printf("\n");
+		 /** translate mask string to uint8_t array*/
+		j = 0;
+		if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+			(mask_ptr[1] == 'X')))
+			mask_ptr += 2;
+		len = strnlen(mask_ptr, (res->len_value+3)/4);
+		if (len == 0) {
+			printf("invalid input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = mask_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			hex |= (uint8_t)(val & 0x8) >> 3;
+			hex |= (uint8_t)(val & 0x4) >> 1;
+			hex |= (uint8_t)(val & 0x2) << 1;
+			hex |= (uint8_t)(val & 0x1) << 3;
+			if (i % 2) {
+				byte |= hex << 4;
+				filter.mask[j] = byte;
+				printf("mask[%d]:%02x ", j, filter.mask[j]);
+				j++;
+				byte = 0;
+			} else
+				byte |= hex;
+			hex = 0;
+		}
+		printf("\n");
+		printf("call function rte_eth_dev_add_flex_filter: "
+			"index = %d, queue-id = %d, len = %d, priority = %d\n",
+			res->index_value, res->queue_id,
+			filter.len, filter.priority);
+		ret = rte_eth_dev_add_flex_filter(res->port_id, res->index_value,
+				&filter, res->queue_id);
+
+	} else if (!strcmp(res->filter, "remove_flex_filter"))
+		ret = rte_eth_dev_remove_flex_filter(res->port_id,
+			res->index_value);
+	else if (!strcmp(res->filter, "get_flex_filter"))
+		get_flex_filter(res->port_id, res->index_value);
+
+	if (ret < 0)
+		printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_len =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				len, "len");
+cmdline_parse_token_string_t cmd_flex_filter_len_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				index, "index");
+cmdline_parse_token_num_t cmd_flex_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				index_value, UINT16);
+cmdline_parse_token_string_t cmd_flex_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "add_flex_filter");
+cmdline_parse_inst_t cmd_add_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "add a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_add_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_len,
+		(void *)&cmd_flex_filter_len_value,
+		(void *)&cmd_flex_filter_bytes,
+		(void *)&cmd_flex_filter_bytes_value,
+		(void *)&cmd_flex_filter_mask,
+		(void *)&cmd_flex_filter_mask_value,
+		(void *)&cmd_flex_filter_priority,
+		(void *)&cmd_flex_filter_priority_value,
+		(void *)&cmd_flex_filter_queue,
+		(void *)&cmd_flex_filter_queue_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "remove_flex_filter");
+cmdline_parse_inst_t cmd_remove_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_remove_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				filter, "get_flex_filter");
+cmdline_parse_inst_t cmd_get_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "get a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_get_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -5235,6 +6125,21 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
 	(cmdline_parse_inst_t *)&cmd_dump,
 	(cmdline_parse_inst_t *)&cmd_dump_one,
+	(cmdline_parse_inst_t *)&cmd_add_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_get_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_add_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_get_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_add_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_get_flex_filter,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 20ad0a8..3c38f14 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1731,3 +1731,148 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 	       "diag=%d\n", port_id, diag);
 }
 
+void
+get_ethertype_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_ethertype_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_ethertype_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get ethertype filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    ethertype:  0x%04x\n",
+			rte_le_to_cpu_32(filter.ethertype));
+		printf("    priority: %s, %d\n",
+			filter.priority_en ? "enable" : "disable",
+			filter.priority);
+		printf("    queue: %d\n", rx_queue);
+	}
+}
+
+void
+get_syn_filter(uint8_t port_id)
+{
+	struct rte_syn_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+
+	if (ret < 0) {
+		printf("get syn filter fails(%s)\n", strerror(-ret));
+		return;
+	}
+	printf("syn filter: %s, priority: %s, queue: %d\n",
+		filter.enable ? "on" : "off",
+		filter.hig_pri ? "high" : "low",
+		rx_queue);
+}
+void
+get_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_2tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_2tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    Destination Port:     0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    protocol:  0x%02x     mask:%d     tcp_flags: 0x%02x\n",
+			filter.protocol, filter.protocol_mask ? 0 : 1,
+			filter.tcp_flags);
+		printf("    priority: %d    queue: %d\n",
+			filter.priority, rx_queue);
+	}
+}
+
+void
+get_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_5tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_5tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 5tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]:\n", index);
+		printf("    Destination IP:  0x%08x    mask: %d\n",
+			(unsigned)rte_be_to_cpu_32(filter.dst_ip),
+			filter.dst_ip_mask ? 0 : 1);
+		printf("    Source IP:       0x%08x    mask: %d\n",
+			(unsigned)rte_be_to_cpu_32(filter.src_ip),
+			filter.src_ip_mask ? 0 : 1);
+		printf("    Destination Port:       0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    Source Port:       0x%04x    mask: %d\n",
+			rte_be_to_cpu_16(filter.src_port),
+			filter.src_port_mask ? 0 : 1);
+		printf("    protocol:           0x%02x    mask: %d\n",
+			filter.protocol,
+			filter.protocol_mask ? 0 : 1);
+		printf("    priority: %d    flags: 0x%02x    queue: %d\n",
+			filter.priority, filter.tcp_flags, rx_queue);
+	}
+}
+void
+get_flex_filter(uint8_t port_id, uint16_t index)
+
+{
+	struct rte_flex_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	int i, j;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_flex_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get flex filter fails(%s)\n", strerror(-ret));
+		return;
+	} else {
+		printf("filter[%d]: ", index);
+		printf("\n    length: %d", filter.len);
+		printf("\n    dword[]: 0x");
+		for (i = 0; i < 32; i++)
+			printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i]));
+		printf("\n    mask[]: 0b");
+		for (i = 0; i < 16; i++) {
+			for (j = 0; j < 8; j++)
+				printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0');
+		}
+		printf("\n    priority: %d    queue: %d\n",
+			filter.priority, rx_queue);
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 2bdb1a2..c7998a6 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -528,6 +528,12 @@ void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
 void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, 
 		uint64_t vf_mask, uint8_t on);
 
+void get_syn_filter(uint8_t port_id);
+void get_ethertype_filter(uint8_t port_id, uint16_t index);
+void get_2tuple_filter(uint8_t port_id, uint16_t index);
+void get_5tuple_filter(uint8_t port_id, uint16_t index);
+void get_flex_filter(uint8_t port_id, uint16_t index);
+
 /*
  * Work-around of a compilation error with ICC on invocations of the
  * rte_be_to_cpu_16() function.
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of generic filter
  2014-05-27  7:57   ` Ming, LiX
@ 2014-05-27  9:18     ` Thomas Monjalon
  0 siblings, 0 replies; 22+ messages in thread
From: Thomas Monjalon @ 2014-05-27  9:18 UTC (permalink / raw)
  To: Ming, LiX; +Cc: dev

Hi LiX,

Thanks for testing patches.

In order to be more efficient next times, I have same comments as for 
HuilongX.

2014-05-27 07:57, Ming, LiX:
> This patch adds APIs for NIC filters list below:
> ethertype filter, syn filter, 2tuple filter, flex filter, 5tuple filter

1) When replying to an email, there should be "> " in front of lines you have 
not written. Here, it's not easy to see what you are replying.

> Test-by: lmingX  lix,ming@intel.com

2) If you do some tests (other than compiling), please explain what are 
the tests (command lines and environment).

> Compile pass

3) No need to notify that compilation is working. It's implicit (and 
mandatory) when sending a patch.

> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index a5727dd..afd4fe8 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c

4) Please do not copy all the patch if you have nothing specific to say about 
it.

Thanks for your help
-- 
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (3 preceding siblings ...)
  2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
@ 2014-05-27 23:21 ` Thomas Monjalon
  2014-05-28  0:53   ` Wu, Jingjing
  2014-06-04  4:16 ` Cao, Waterman
  5 siblings, 1 reply; 22+ messages in thread
From: Thomas Monjalon @ 2014-05-27 23:21 UTC (permalink / raw)
  To: Jingjing Wu; +Cc: dev

Hi Jingjing,

2014-05-24 09:37, Jingjing Wu:
> A generic filter mechanism for handling special packet is required.
> It will allow filters to be set in HW when available so that specific
> packet may be filtered by NICs to specific descriptor queues for
> processing. Currently only Flow Director for Intel's 10GbE 82599
> devices is available. Other types of filter are not support.
> NIC filters list below are implemented in this patchset:
>   ethertype filter, syn filter, 2tuple filter and flex filter for 82580 and
> i350 ethertype filter, syn filter, 5tuple filter for 82576
>   ethertype filter, syn filter and 5tuple filter for 82599

I'd like we have a discussion about how this API is generic enough.
I think many people would like to integrate drivers for other NICs in DPDK and 
I'd hate to see a global rework of this API because we haven't tried to think 
about it before.

First, is there someone in the mailing list who knows other hardware which 
could fit in this filtering feature?

Thanks
-- 
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-05-27 23:21 ` [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Thomas Monjalon
@ 2014-05-28  0:53   ` Wu, Jingjing
  2014-05-28  1:12     ` Wu, Jingjing
  0 siblings, 1 reply; 22+ messages in thread
From: Wu, Jingjing @ 2014-05-28  0:53 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi, Thomas

This patch is mainly about multiple NIC filters implement. It has close relationship with NICs.
As the patch says:
NIC filters list below are implemented in this patchset:
	ethertype filter, syn filter, 2tuple filter and flex filter for 82580 and i350 
	ethertype filter, syn filter, 5tuple filter for 82576
	ethertype filter, syn filter and 5tuple filter for 82599

The same type filter uses the same API for the NICs list above.
About the generic filter feature, how to define the "generic" is still in discussing, and not included in this patch. 
These NIC filters implemented in this patch are first step. Even without generic, it also provides a way to configure these NIC filters to hardware in DPDK PMD.


-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] 
Sent: Wednesday, May 28, 2014 7:22 AM
To: Wu, Jingjing
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi Jingjing,

2014-05-24 09:37, Jingjing Wu:
> A generic filter mechanism for handling special packet is required.
> It will allow filters to be set in HW when available so that specific 
> packet may be filtered by NICs to specific descriptor queues for 
> processing. Currently only Flow Director for Intel's 10GbE 82599 
> devices is available. Other types of filter are not support.
> NIC filters list below are implemented in this patchset:
>   ethertype filter, syn filter, 2tuple filter and flex filter for 
> 82580 and
> i350 ethertype filter, syn filter, 5tuple filter for 82576
>   ethertype filter, syn filter and 5tuple filter for 82599

I'd like we have a discussion about how this API is generic enough.
I think many people would like to integrate drivers for other NICs in DPDK and I'd hate to see a global rework of this API because we haven't tried to think about it before.

First, is there someone in the mailing list who knows other hardware which could fit in this filtering feature?

Thanks
--
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-05-28  0:53   ` Wu, Jingjing
@ 2014-05-28  1:12     ` Wu, Jingjing
  2014-06-11 15:45       ` Thomas Monjalon
  0 siblings, 1 reply; 22+ messages in thread
From: Wu, Jingjing @ 2014-05-28  1:12 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi, Thomas

The generic you said may be different from I mentioned in last mail. You are discussing whether the APIs provide for NIC filters is generic or not. About that we can use same API for a type of filter. For example, if we want to configure ethertype filter, we can use the same API, no matter the NIC is 82580, i350, 82576 or 82599. We think these NICs may be most common used.

-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wu, Jingjing
Sent: Wednesday, May 28, 2014 8:53 AM
To: Thomas Monjalon
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi, Thomas

This patch is mainly about multiple NIC filters implement. It has close relationship with NICs.
As the patch says:
NIC filters list below are implemented in this patchset:
	ethertype filter, syn filter, 2tuple filter and flex filter for 82580 and i350 
	ethertype filter, syn filter, 5tuple filter for 82576
	ethertype filter, syn filter and 5tuple filter for 82599

The same type filter uses the same API for the NICs list above.
About the generic filter feature, how to define the "generic" is still in discussing, and not included in this patch. 
These NIC filters implemented in this patch are first step. Even without generic, it also provides a way to configure these NIC filters to hardware in DPDK PMD.


-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Wednesday, May 28, 2014 7:22 AM
To: Wu, Jingjing
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi Jingjing,

2014-05-24 09:37, Jingjing Wu:
> A generic filter mechanism for handling special packet is required.
> It will allow filters to be set in HW when available so that specific 
> packet may be filtered by NICs to specific descriptor queues for 
> processing. Currently only Flow Director for Intel's 10GbE 82599 
> devices is available. Other types of filter are not support.
> NIC filters list below are implemented in this patchset:
>   ethertype filter, syn filter, 2tuple filter and flex filter for
> 82580 and
> i350 ethertype filter, syn filter, 5tuple filter for 82576
>   ethertype filter, syn filter and 5tuple filter for 82599

I'd like we have a discussion about how this API is generic enough.
I think many people would like to integrate drivers for other NICs in DPDK and I'd hate to see a global rework of this API because we haven't tried to think about it before.

First, is there someone in the mailing list who knows other hardware which could fit in this filtering feature?

Thanks
--
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (4 preceding siblings ...)
  2014-05-27 23:21 ` [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Thomas Monjalon
@ 2014-06-04  4:16 ` Cao, Waterman
  5 siblings, 0 replies; 22+ messages in thread
From: Cao, Waterman @ 2014-06-04  4:16 UTC (permalink / raw)
  To: dev

Tested-by: Waterman Cao <waterman.cao@intel.com>

This patch includes 4 files, and has been tested by Intel.
Please see information as the following:
 Fedora 20 x86_64, Linux Kernel 3.11.10-301, GCC 4.8.2
 Intel Xeon CPU E5-2680 v2 @ 2.80GHz
 NIC: Intel Niantic 82599, Intel i350, Intel 82580 and Intel 82576
 We verified ethertype filter, 2-tuple filter, 5-tuple filter, 
 flex filter and SYN filter with different NICs.
 
 Total cases        Passed               Failed   
     18               16                   2

 Failure only related to priority of filter, no impact on functionality.
 Example: Show how to distribute specific packet to assigned queue 
 Please launch testpmd firstly, then run the following command:
  ---add syn filter ---
  testpmd> add_syn_filter (port_id) priority (high|low) queue (queue_id)
  ---get syn filter info ---
  testpmd> get_syn_filter (port_id)
  ---remove syn filter ---
  testpmd> remove_syn_filter (port_id)

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-05-28  1:12     ` Wu, Jingjing
@ 2014-06-11 15:45       ` Thomas Monjalon
  2014-06-12  8:08         ` Wu, Jingjing
  0 siblings, 1 reply; 22+ messages in thread
From: Thomas Monjalon @ 2014-06-11 15:45 UTC (permalink / raw)
  To: Wu, Jingjing; +Cc: dev

Hi Jingjing,

Please reply below the question.

2014-05-28 01:12, Wu, Jingjing:
> You are discussing whether the APIs provide for NIC filters is generic
> or not. About that we can use same API for a type of filter. For example,
> if we want to configure ethertype filter, we can use the same API, no
> matter the NIC is 82580, i350, 82576 or 82599. We think these NICs may be
> most common used.

I was wondering if this API can apply to non-Intel devices. But nobody talked 
about it. So let's forget it.

My main concern is that Vladimir Medvedkin suggested another API and I'd like 
you give your opinion about it:
	http://dpdk.org/ml/archives/dev/2014-June/003053.html
It offers pool number in configuration of the filters.

Last comment: patches would be more pleasant to read with right alignment and 
spaces in comments. This is an extract to illustrate what I'm talking about:
+       uint16_t priority; /**< used when more than one filter matches */
+       uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+               protocol_mask   : 1;

Thanks
-- 
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-11 15:45       ` Thomas Monjalon
@ 2014-06-12  8:08         ` Wu, Jingjing
  2014-06-12 15:36           ` Thomas Monjalon
  0 siblings, 1 reply; 22+ messages in thread
From: Wu, Jingjing @ 2014-06-12  8:08 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi, Thomas

Thanks for your reply.

About your first concern:
The pool field is used in virtualization scenario. It is acting as one of input set during filter matching in ixgbe. 
My patch didn't consider the virtualization scenario in generic filter feature. Because in 82599 datasheet, it is recommended to assign rx queues not used by DCB/RSS, that is virtualization without RSS and DCB mode. For this mode, current DPDK version makes the number of queue to 1 by default in IOV mode. So in this case it makes no sense make pool as a input set and the rx queue also need to be set to in this pool, so just keep the consistent with flow director who also ignore it in previous version. 
And further E1000/Niantic/Fortville have different definitions for VF, we need to think how to define it more generic.
And even just need offer pool number in configuration of the filters as what Vladimir did, it also need to verify the interworking with Virtualization for different kinds of NICs, and the interworking with DCB and RSS which is not recommended in 82599's datasheet.
So I think it will be a good choice to implement generic filter interworking with virtualization in future patch. If there is any volunteer to send patch for support this concern later, it will be also cool.

About your second concern:
I will send out a new version for that soon.


-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] 
Sent: Wednesday, June 11, 2014 11:45 PM
To: Wu, Jingjing
Cc: dev@dpdk.org; Vladimir Medvedkin
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi Jingjing,

Please reply below the question.

2014-05-28 01:12, Wu, Jingjing:
> You are discussing whether the APIs provide for NIC filters is generic 
> or not. About that we can use same API for a type of filter. For 
> example, if we want to configure ethertype filter, we can use the same 
> API, no matter the NIC is 82580, i350, 82576 or 82599. We think these 
> NICs may be most common used.

I was wondering if this API can apply to non-Intel devices. But nobody talked about it. So let's forget it.

My main concern is that Vladimir Medvedkin suggested another API and I'd like you give your opinion about it:
	http://dpdk.org/ml/archives/dev/2014-June/003053.html
It offers pool number in configuration of the filters.

Last comment: patches would be more pleasant to read with right alignment and spaces in comments. This is an extract to illustrate what I'm talking about:
+       uint16_t priority; /**< used when more than one filter matches */
+       uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+               protocol_mask   : 1;

Thanks
--
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-12  8:08         ` Wu, Jingjing
@ 2014-06-12 15:36           ` Thomas Monjalon
  2014-06-13 11:51             ` Vladimir Medvedkin
  0 siblings, 1 reply; 22+ messages in thread
From: Thomas Monjalon @ 2014-06-12 15:36 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

> 2014-06-11 17:45, Thomas Monjalon:
> > My main concern is that Vladimir Medvedkin suggested another API and I'd
> > like you give your opinion about it:
> > 		http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > It offers pool number in configuration of the filters.

2014-06-12 08:08, Wu, Jingjing:
> The pool field is used in virtualization scenario. It is acting as one of
> input set during filter matching in ixgbe. 
> My patch didn't consider the virtualization scenario in generic filter
> feature. Because in 82599 datasheet, it is recommended to assign rx queues
> not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> this mode, current DPDK version makes the number of queue to 1 by default in
> IOV mode. So in this case it makes no sense make pool as a input set and the
> rx queue also need to be set to in this pool, so just keep the consistent
> with flow director who also ignore it in previous version. 
> And further E1000/Niantic/Fortville have different definitions for VF, we
> need to think how to define it more generic.
> And even just need offer pool number in configuration of the filters as what
> Vladimir did, it also need to verify the interworking with Virtualization
> for different kinds of NICs, and the interworking with DCB and RSS which is
> not recommended in 82599's datasheet.
> So I think it will be a good choice to implement generic filter interworking
> with virtualization in future patch. If there is any volunteer to send patch
> for support this concern later, it will be also cool.

Vladimir, do you agree with this analysis?
As you suggested another implementation, I need you acknowledgment for this 
patchset to be integrated.

Thanks
-- 
Thomas

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-12 15:36           ` Thomas Monjalon
@ 2014-06-13 11:51             ` Vladimir Medvedkin
  2014-06-13 14:12               ` Wu, Jingjing
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir Medvedkin @ 2014-06-13 11:51 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

Hi all,

The 82599 datasheet (p. 284 and p.287) has only recommendations and only
when possible about assign rx queue not used by RSS/DCB. I do not see any
serious restrictions do not assign the rx queue used by RSS/DCB.
For cases with only 1 queue if I understand correctly this patch
http://dpdk.org/ml/archives/dev/2014-May/002589.html we can init second
queue in pool and assign it by filter. In *ETH_MQ_RX_VMDQ_ONLY*  mode init
all possible queues (even if hardware route packets to zero queue in pools)
so there no problem. Moreover, it is not necesary for rx queue to be set in
the same pool.

About genericity. I agree with Jingjing, different controllers have
different definitions for pools or VFs. And it is only Intel controllers!
It is very hard to predict hardware implementation. For example for
Fortville I can not find 5-tuple filters at all.

API. I have several remarks.
1. You use rx_queue as separate arg. For example:
rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, struct
rte_ethertype_filter *filter, uint8_t rx_queue)
rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, struct
rte_ethertype_filter *filter, uint8_t *rx_queue)
you can move uint8_t rx_queue into struct rte_ethertype_filter *filter.
2. In SYN filter:
rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri, uint8_t
rx_queue)
rte_eth_dev_get_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
uint8_t *rx_queue)
In first ADD func you alloc struct rte_syn_filter inside func, but in GET
func you have to alloc struct rte_syn_filter in your app. May be better to
do
rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
uint8_t *rx_queue) ?

So, Jingjing made a lot of work, much more then I (igb filters, testpmd
commands). It works the same as mine (not counting pools logic), so let's
integrate it (it's will be great if jingjing change api according to my
remarks).

Regards,
Vladimir


2014-06-12 19:36 GMT+04:00 Thomas Monjalon <thomas.monjalon@6wind.com>:

> > 2014-06-11 17:45, Thomas Monjalon:
> > > My main concern is that Vladimir Medvedkin suggested another API and
> I'd
> > > like you give your opinion about it:
> > >             http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > > It offers pool number in configuration of the filters.
>
> 2014-06-12 08:08, Wu, Jingjing:
> > The pool field is used in virtualization scenario. It is acting as one of
> > input set during filter matching in ixgbe.
> > My patch didn't consider the virtualization scenario in generic filter
> > feature. Because in 82599 datasheet, it is recommended to assign rx
> queues
> > not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> > this mode, current DPDK version makes the number of queue to 1 by
> default in
> > IOV mode. So in this case it makes no sense make pool as a input set and
> the
> > rx queue also need to be set to in this pool, so just keep the consistent
> > with flow director who also ignore it in previous version.
> > And further E1000/Niantic/Fortville have different definitions for VF, we
> > need to think how to define it more generic.
> > And even just need offer pool number in configuration of the filters as
> what
> > Vladimir did, it also need to verify the interworking with Virtualization
> > for different kinds of NICs, and the interworking with DCB and RSS which
> is
> > not recommended in 82599's datasheet.
> > So I think it will be a good choice to implement generic filter
> interworking
> > with virtualization in future patch. If there is any volunteer to send
> patch
> > for support this concern later, it will be also cool.
>
> Vladimir, do you agree with this analysis?
> As you suggested another implementation, I need you acknowledgment for this
> patchset to be integrated.
>
> Thanks
> --
> Thomas
>

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-13 11:51             ` Vladimir Medvedkin
@ 2014-06-13 14:12               ` Wu, Jingjing
  2014-06-13 16:19                 ` Vladimir Medvedkin
  0 siblings, 1 reply; 22+ messages in thread
From: Wu, Jingjing @ 2014-06-13 14:12 UTC (permalink / raw)
  To: Vladimir Medvedkin, Thomas Monjalon; +Cc: dev

Hi, Vladimir

Thanks a lot for your remarks.

Yes, your understanding is correct, in non-IOV mode, we can use 64pool, per pool can has 2 queues when ETH_MQ_RX_VMDQ_ONLY.  While in IOV mode, current DPDK version makes the number of queue to 1 by default. The pools logic makes sense, but I didn’t consider it globally with the thinking we can do it in future. I will be great if you can generate a new patch based on mine. Or we can discuss it further? Due to it is close to the feature deliver time now and much verification work for it, it may not possible to add it in this patch.

In API
About your first remark, the reason why I didn’t put the queue in the filter structure is that the filter contains the fields used for comparison and the queue is acted as result, and another concern is to keep consistent with flow director’s implementation.
About your second remark, I will accept it and integrate the change to patch in new version.

Do your  agree my proposal?


From: Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
Sent: Friday, June 13, 2014 7:52 PM
To: Thomas Monjalon
Cc: Wu, Jingjing; dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi all,
The 82599 datasheet (p. 284 and p.287) has only recommendations and only when possible about assign rx queue not used by RSS/DCB. I do not see any serious restrictions do not assign the rx queue used by RSS/DCB.
For cases with only 1 queue if I understand correctly this patch http://dpdk.org/ml/archives/dev/2014-May/002589.html we can init second queue in pool and assign it by filter. In ETH_MQ_RX_VMDQ_ONLY  mode init all possible queues (even if hardware route packets to zero queue in pools) so there no problem. Moreover, it is not necesary for rx queue to be set in the same pool.

About genericity. I agree with Jingjing, different controllers have different definitions for pools or VFs. And it is only Intel controllers! It is very hard to predict hardware implementation. For example for Fortville I can not find 5-tuple filters at all.

API. I have several remarks.
1. You use rx_queue as separate arg. For example:
rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, struct rte_ethertype_filter *filter, uint8_t rx_queue)
rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, struct rte_ethertype_filter *filter, uint8_t *rx_queue)
you can move uint8_t rx_queue into struct rte_ethertype_filter *filter.
2. In SYN filter:
rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri, uint8_t rx_queue)
rte_eth_dev_get_syn_filter(uint8_t port_id, struct rte_syn_filter *filter, uint8_t *rx_queue)
In first ADD func you alloc struct rte_syn_filter inside func, but in GET func you have to alloc struct rte_syn_filter in your app. May be better to do
rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter, uint8_t *rx_queue) ?

So, Jingjing made a lot of work, much more then I (igb filters, testpmd commands). It works the same as mine (not counting pools logic), so let's integrate it (it's will be great if jingjing change api according to my remarks).

Regards,
Vladimir

2014-06-12 19:36 GMT+04:00 Thomas Monjalon <thomas.monjalon@6wind.com<mailto:thomas.monjalon@6wind.com>>:
> 2014-06-11 17:45, Thomas Monjalon:
> > My main concern is that Vladimir Medvedkin suggested another API and I'd
> > like you give your opinion about it:
> >             http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > It offers pool number in configuration of the filters.
2014-06-12 08:08, Wu, Jingjing:
> The pool field is used in virtualization scenario. It is acting as one of
> input set during filter matching in ixgbe.
> My patch didn't consider the virtualization scenario in generic filter
> feature. Because in 82599 datasheet, it is recommended to assign rx queues
> not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> this mode, current DPDK version makes the number of queue to 1 by default in
> IOV mode. So in this case it makes no sense make pool as a input set and the
> rx queue also need to be set to in this pool, so just keep the consistent
> with flow director who also ignore it in previous version.
> And further E1000/Niantic/Fortville have different definitions for VF, we
> need to think how to define it more generic.
> And even just need offer pool number in configuration of the filters as what
> Vladimir did, it also need to verify the interworking with Virtualization
> for different kinds of NICs, and the interworking with DCB and RSS which is
> not recommended in 82599's datasheet.
> So I think it will be a good choice to implement generic filter interworking
> with virtualization in future patch. If there is any volunteer to send patch
> for support this concern later, it will be also cool.
Vladimir, do you agree with this analysis?
As you suggested another implementation, I need you acknowledgment for this
patchset to be integrated.

Thanks
--
Thomas


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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-13 14:12               ` Wu, Jingjing
@ 2014-06-13 16:19                 ` Vladimir Medvedkin
  2014-06-14  1:00                   ` Wu, Jingjing
  0 siblings, 1 reply; 22+ messages in thread
From: Vladimir Medvedkin @ 2014-06-13 16:19 UTC (permalink / raw)
  To: Wu, Jingjing; +Cc: dev

Hi Jingjing,

Yes, I agree.
I have one more remark. It is about type of rx_queue arg. Now it is
uint8_t. I think we have to change it to uint16_t because for Fortville NIC
it is not enough. Quote fro the datasheet:
A PF VSI (Virtual Station Interfaces aka virtual NICs) can allocate and use
up to 1536 LQPs (LAN queue pairs).

Regards,
Vladimir


2014-06-13 18:12 GMT+04:00 Wu, Jingjing <jingjing.wu@intel.com>:

>  Hi, Vladimir
>
>
>
> Thanks a lot for your remarks.
>
>
>
> Yes, your understanding is correct, in non-IOV mode, we can use 64pool,
> per pool can has 2 queues when ETH_MQ_RX_VMDQ_ONLY.  While in IOV mode,
> current DPDK version makes the number of queue to 1 by default. The pools
> logic makes sense, but I didn’t consider it globally with the thinking we
> can do it in future. I will be great if you can generate a new patch based
> on mine. Or we can discuss it further? Due to it is close to the feature
> deliver time now and much verification work for it, it may not possible to
> add it in this patch.
>
>
>
> In API
>
> About your first remark, the reason why I didn’t put the queue in the
> filter structure is that the filter contains the fields used for comparison
> and the queue is acted as result, and another concern is to keep consistent
> with flow director’s implementation.
>
> About your second remark, I will accept it and integrate the change to
> patch in new version.
>
>
>
> Do your  agree my proposal?
>
>
>
>
>
> *From:* Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
> *Sent:* Friday, June 13, 2014 7:52 PM
> *To:* Thomas Monjalon
> *Cc:* Wu, Jingjing; dev@dpdk.org
>
> *Subject:* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic
> filter
>
>
>
> Hi all,
>
> The 82599 datasheet (p. 284 and p.287) has only recommendations and only
> when possible about assign rx queue not used by RSS/DCB. I do not see any
> serious restrictions do not assign the rx queue used by RSS/DCB.
>
> For cases with only 1 queue if I understand correctly this patch
> http://dpdk.org/ml/archives/dev/2014-May/002589.html we can init second
> queue in pool and assign it by filter. In *ETH_MQ_RX_VMDQ_ONLY*  mode
> init all possible queues (even if hardware route packets to zero queue in
> pools) so there no problem. Moreover, it is not necesary for rx queue to be
> set in the same pool.
>
>
> About genericity. I agree with Jingjing, different controllers have
> different definitions for pools or VFs. And it is only Intel controllers!
> It is very hard to predict hardware implementation. For example for
> Fortville I can not find 5-tuple filters at all.
>
>
>
> API. I have several remarks.
>
> 1. You use rx_queue as separate arg. For example:
>
> rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, struct
> rte_ethertype_filter *filter, uint8_t rx_queue)
> rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, struct
> rte_ethertype_filter *filter, uint8_t *rx_queue)
>
> you can move uint8_t rx_queue into struct rte_ethertype_filter *filter.
>
> 2. In SYN filter:
> rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri, uint8_t
> rx_queue)
> rte_eth_dev_get_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
> uint8_t *rx_queue)
>
> In first ADD func you alloc struct rte_syn_filter inside func, but in GET
> func you have to alloc struct rte_syn_filter in your app. May be better to
> do
> rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
> uint8_t *rx_queue) ?
>
>
>
> So, Jingjing made a lot of work, much more then I (igb filters, testpmd
> commands). It works the same as mine (not counting pools logic), so let's
> integrate it (it's will be great if jingjing change api according to my
> remarks).
>
>
>
> Regards,
>
> Vladimir
>
>
>
> 2014-06-12 19:36 GMT+04:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
>
> > 2014-06-11 17:45, Thomas Monjalon:
>
> > > My main concern is that Vladimir Medvedkin suggested another API and
> I'd
> > > like you give your opinion about it:
> > >             http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > > It offers pool number in configuration of the filters.
>
> 2014-06-12 08:08, Wu, Jingjing:
>
> > The pool field is used in virtualization scenario. It is acting as one of
> > input set during filter matching in ixgbe.
> > My patch didn't consider the virtualization scenario in generic filter
> > feature. Because in 82599 datasheet, it is recommended to assign rx
> queues
> > not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> > this mode, current DPDK version makes the number of queue to 1 by
> default in
> > IOV mode. So in this case it makes no sense make pool as a input set and
> the
> > rx queue also need to be set to in this pool, so just keep the consistent
> > with flow director who also ignore it in previous version.
> > And further E1000/Niantic/Fortville have different definitions for VF, we
> > need to think how to define it more generic.
> > And even just need offer pool number in configuration of the filters as
> what
> > Vladimir did, it also need to verify the interworking with Virtualization
> > for different kinds of NICs, and the interworking with DCB and RSS which
> is
> > not recommended in 82599's datasheet.
> > So I think it will be a good choice to implement generic filter
> interworking
> > with virtualization in future patch. If there is any volunteer to send
> patch
> > for support this concern later, it will be also cool.
>
> Vladimir, do you agree with this analysis?
> As you suggested another implementation, I need you acknowledgment for this
> patchset to be integrated.
>
> Thanks
> --
> Thomas
>
>
>

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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-13 16:19                 ` Vladimir Medvedkin
@ 2014-06-14  1:00                   ` Wu, Jingjing
  2014-06-14  9:00                     ` Vladimir Medvedkin
  0 siblings, 1 reply; 22+ messages in thread
From: Wu, Jingjing @ 2014-06-14  1:00 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

Hi, Vladimir

Yes, for Fortville, uint8_t is not enough, it was also the concern is to keep consistent with flow director’s implementation. But I agree that we need to change.

Let make an agreement like:

I will make change for the remarks from you. One is the change the type of rx_queue to uint16_t. The other is change API like “rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter, uint16_t rx_queue)”.

And about the pool and virtualization case, maybe you will send a new patch about it, maybe me. Whatever, just leave it in future, not  include in this patch.

Thank you!
Jingjing

From: Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
Sent: Saturday, June 14, 2014 12:19 AM
To: Wu, Jingjing
Cc: Thomas Monjalon; dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi Jingjing,
Yes, I agree.
I have one more remark. It is about type of rx_queue arg. Now it is uint8_t. I think we have to change it to uint16_t because for Fortville NIC it is not enough. Quote fro the datasheet:
A PF VSI (Virtual Station Interfaces aka virtual NICs) can allocate and use up to 1536 LQPs (LAN queue pairs).
Regards,
Vladimir

2014-06-13 18:12 GMT+04:00 Wu, Jingjing <jingjing.wu@intel.com<mailto:jingjing.wu@intel.com>>:
Hi, Vladimir

Thanks a lot for your remarks.

Yes, your understanding is correct, in non-IOV mode, we can use 64pool, per pool can has 2 queues when ETH_MQ_RX_VMDQ_ONLY.  While in IOV mode, current DPDK version makes the number of queue to 1 by default. The pools logic makes sense, but I didn’t consider it globally with the thinking we can do it in future. I will be great if you can generate a new patch based on mine. Or we can discuss it further? Due to it is close to the feature deliver time now and much verification work for it, it may not possible to add it in this patch.

In API
About your first remark, the reason why I didn’t put the queue in the filter structure is that the filter contains the fields used for comparison and the queue is acted as result, and another concern is to keep consistent with flow director’s implementation.
About your second remark, I will accept it and integrate the change to patch in new version.

Do your  agree my proposal?


From: Vladimir Medvedkin [mailto:medvedkinv@gmail.com<mailto:medvedkinv@gmail.com>]
Sent: Friday, June 13, 2014 7:52 PM
To: Thomas Monjalon
Cc: Wu, Jingjing; dev@dpdk.org<mailto:dev@dpdk.org>

Subject: Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter

Hi all,
The 82599 datasheet (p. 284 and p.287) has only recommendations and only when possible about assign rx queue not used by RSS/DCB. I do not see any serious restrictions do not assign the rx queue used by RSS/DCB.
For cases with only 1 queue if I understand correctly this patch http://dpdk.org/ml/archives/dev/2014-May/002589.html we can init second queue in pool and assign it by filter. In ETH_MQ_RX_VMDQ_ONLY  mode init all possible queues (even if hardware route packets to zero queue in pools) so there no problem. Moreover, it is not necesary for rx queue to be set in the same pool.

About genericity. I agree with Jingjing, different controllers have different definitions for pools or VFs. And it is only Intel controllers! It is very hard to predict hardware implementation. For example for Fortville I can not find 5-tuple filters at all.

API. I have several remarks.
1. You use rx_queue as separate arg. For example:
rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, struct rte_ethertype_filter *filter, uint8_t rx_queue)
rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, struct rte_ethertype_filter *filter, uint8_t *rx_queue)
you can move uint8_t rx_queue into struct rte_ethertype_filter *filter.
2. In SYN filter:
rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri, uint8_t rx_queue)
rte_eth_dev_get_syn_filter(uint8_t port_id, struct rte_syn_filter *filter, uint8_t *rx_queue)
In first ADD func you alloc struct rte_syn_filter inside func, but in GET func you have to alloc struct rte_syn_filter in your app. May be better to do
rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter, uint8_t *rx_queue) ?

So, Jingjing made a lot of work, much more then I (igb filters, testpmd commands). It works the same as mine (not counting pools logic), so let's integrate it (it's will be great if jingjing change api according to my remarks).

Regards,
Vladimir

2014-06-12 19:36 GMT+04:00 Thomas Monjalon <thomas.monjalon@6wind.com<mailto:thomas.monjalon@6wind.com>>:
> 2014-06-11 17:45, Thomas Monjalon:
> > My main concern is that Vladimir Medvedkin suggested another API and I'd
> > like you give your opinion about it:
> >             http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > It offers pool number in configuration of the filters.
2014-06-12 08:08, Wu, Jingjing:
> The pool field is used in virtualization scenario. It is acting as one of
> input set during filter matching in ixgbe.
> My patch didn't consider the virtualization scenario in generic filter
> feature. Because in 82599 datasheet, it is recommended to assign rx queues
> not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> this mode, current DPDK version makes the number of queue to 1 by default in
> IOV mode. So in this case it makes no sense make pool as a input set and the
> rx queue also need to be set to in this pool, so just keep the consistent
> with flow director who also ignore it in previous version.
> And further E1000/Niantic/Fortville have different definitions for VF, we
> need to think how to define it more generic.
> And even just need offer pool number in configuration of the filters as what
> Vladimir did, it also need to verify the interworking with Virtualization
> for different kinds of NICs, and the interworking with DCB and RSS which is
> not recommended in 82599's datasheet.
> So I think it will be a good choice to implement generic filter interworking
> with virtualization in future patch. If there is any volunteer to send patch
> for support this concern later, it will be also cool.
Vladimir, do you agree with this analysis?
As you suggested another implementation, I need you acknowledgment for this
patchset to be integrated.

Thanks
--
Thomas



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

* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter
  2014-06-14  1:00                   ` Wu, Jingjing
@ 2014-06-14  9:00                     ` Vladimir Medvedkin
  0 siblings, 0 replies; 22+ messages in thread
From: Vladimir Medvedkin @ 2014-06-14  9:00 UTC (permalink / raw)
  To: Wu, Jingjing; +Cc: dev

Hi Jingjing,

Ok!
Let's get back to this patch after 1.7 release.

Thanks!

Regards,
Vladimir


2014-06-14 5:00 GMT+04:00 Wu, Jingjing <jingjing.wu@intel.com>:

>  Hi, Vladimir
>
>
>
> Yes, for Fortville, uint8_t is not enough, it was also the concern is to
> keep consistent with flow director’s implementation. But I agree that we
> need to change.
>
>
>
> Let make an agreement like:
>
>
>
> I will make change for the remarks from you. One is the change the type of
> rx_queue to uint16_t. The other is change API like
> “rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
> uint16_t rx_queue)”.
>
>
>
> And about the pool and virtualization case, maybe you will send a new
> patch about it, maybe me. Whatever, just leave it in future, not  include
> in this patch.
>
>
>
> Thank you!
>
> Jingjing
>
>
>
> *From:* Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
> *Sent:* Saturday, June 14, 2014 12:19 AM
> *To:* Wu, Jingjing
> *Cc:* Thomas Monjalon; dev@dpdk.org
>
> *Subject:* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic
> filter
>
>
>
> Hi Jingjing,
>
> Yes, I agree.
> I have one more remark. It is about type of rx_queue arg. Now it is
> uint8_t. I think we have to change it to uint16_t because for Fortville NIC
> it is not enough. Quote fro the datasheet:
> A PF VSI (Virtual Station Interfaces aka virtual NICs) can allocate and
> use up to 1536 LQPs (LAN queue pairs).
>
> Regards,
>
> Vladimir
>
>
>
> 2014-06-13 18:12 GMT+04:00 Wu, Jingjing <jingjing.wu@intel.com>:
>
>  Hi, Vladimir
>
>
>
> Thanks a lot for your remarks.
>
>
>
> Yes, your understanding is correct, in non-IOV mode, we can use 64pool,
> per pool can has 2 queues when ETH_MQ_RX_VMDQ_ONLY.  While in IOV mode,
> current DPDK version makes the number of queue to 1 by default. The pools
> logic makes sense, but I didn’t consider it globally with the thinking we
> can do it in future. I will be great if you can generate a new patch based
> on mine. Or we can discuss it further? Due to it is close to the feature
> deliver time now and much verification work for it, it may not possible to
> add it in this patch.
>
>
>
> In API
>
> About your first remark, the reason why I didn’t put the queue in the
> filter structure is that the filter contains the fields used for comparison
> and the queue is acted as result, and another concern is to keep consistent
> with flow director’s implementation.
>
> About your second remark, I will accept it and integrate the change to
> patch in new version.
>
>
>
> Do your  agree my proposal?
>
>
>
>
>
> *From:* Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
> *Sent:* Friday, June 13, 2014 7:52 PM
> *To:* Thomas Monjalon
> *Cc:* Wu, Jingjing; dev@dpdk.org
>
>
> *Subject:* Re: [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic
> filter
>
>
>
> Hi all,
>
> The 82599 datasheet (p. 284 and p.287) has only recommendations and only
> when possible about assign rx queue not used by RSS/DCB. I do not see any
> serious restrictions do not assign the rx queue used by RSS/DCB.
>
> For cases with only 1 queue if I understand correctly this patch
> http://dpdk.org/ml/archives/dev/2014-May/002589.html we can init second
> queue in pool and assign it by filter. In *ETH_MQ_RX_VMDQ_ONLY*  mode
> init all possible queues (even if hardware route packets to zero queue in
> pools) so there no problem. Moreover, it is not necesary for rx queue to be
> set in the same pool.
>
>
> About genericity. I agree with Jingjing, different controllers have
> different definitions for pools or VFs. And it is only Intel controllers!
> It is very hard to predict hardware implementation. For example for
> Fortville I can not find 5-tuple filters at all.
>
>
>
> API. I have several remarks.
>
> 1. You use rx_queue as separate arg. For example:
>
> rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, struct
> rte_ethertype_filter *filter, uint8_t rx_queue)
> rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, struct
> rte_ethertype_filter *filter, uint8_t *rx_queue)
>
> you can move uint8_t rx_queue into struct rte_ethertype_filter *filter.
>
> 2. In SYN filter:
> rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri, uint8_t
> rx_queue)
> rte_eth_dev_get_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
> uint8_t *rx_queue)
>
> In first ADD func you alloc struct rte_syn_filter inside func, but in GET
> func you have to alloc struct rte_syn_filter in your app. May be better to
> do
> rte_eth_dev_add_syn_filter(uint8_t port_id, struct rte_syn_filter *filter,
> uint8_t *rx_queue) ?
>
>
>
> So, Jingjing made a lot of work, much more then I (igb filters, testpmd
> commands). It works the same as mine (not counting pools logic), so let's
> integrate it (it's will be great if jingjing change api according to my
> remarks).
>
>
>
> Regards,
>
> Vladimir
>
>
>
> 2014-06-12 19:36 GMT+04:00 Thomas Monjalon <thomas.monjalon@6wind.com>:
>
> > 2014-06-11 17:45, Thomas Monjalon:
>
> > > My main concern is that Vladimir Medvedkin suggested another API and
> I'd
> > > like you give your opinion about it:
> > >             http://dpdk.org/ml/archives/dev/2014-June/003053.html
> > > It offers pool number in configuration of the filters.
>
> 2014-06-12 08:08, Wu, Jingjing:
>
> > The pool field is used in virtualization scenario. It is acting as one of
> > input set during filter matching in ixgbe.
> > My patch didn't consider the virtualization scenario in generic filter
> > feature. Because in 82599 datasheet, it is recommended to assign rx
> queues
> > not used by DCB/RSS, that is virtualization without RSS and DCB mode. For
> > this mode, current DPDK version makes the number of queue to 1 by
> default in
> > IOV mode. So in this case it makes no sense make pool as a input set and
> the
> > rx queue also need to be set to in this pool, so just keep the consistent
> > with flow director who also ignore it in previous version.
> > And further E1000/Niantic/Fortville have different definitions for VF, we
> > need to think how to define it more generic.
> > And even just need offer pool number in configuration of the filters as
> what
> > Vladimir did, it also need to verify the interworking with Virtualization
> > for different kinds of NICs, and the interworking with DCB and RSS which
> is
> > not recommended in 82599's datasheet.
> > So I think it will be a good choice to implement generic filter
> interworking
> > with virtualization in future patch. If there is any volunteer to send
> patch
> > for support this concern later, it will be also cool.
>
> Vladimir, do you agree with this analysis?
> As you suggested another implementation, I need you acknowledgment for this
> patchset to be integrated.
>
> Thanks
> --
> Thomas
>
>
>
>
>

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

end of thread, other threads:[~2014-06-14  9:00 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-24  1:37 [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Jingjing Wu
2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 1/4]ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
2014-05-27  7:57   ` Ming, LiX
2014-05-27  9:18     ` Thomas Monjalon
2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 2/4]e1000: add igb NIC filters of generic filter feature Jingjing Wu
2014-05-27  7:59   ` Ming, LiX
2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 3/4]ixgbe: add ixgbe " Jingjing Wu
2014-05-27  8:00   ` Ming, LiX
2014-05-24  1:37 ` [dpdk-dev] [PATCH v2 4/4]app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
2014-05-27  8:00   ` Ming, LiX
2014-05-27 23:21 ` [dpdk-dev] [PATCH v2 0/4] NIC filters support for generic filter Thomas Monjalon
2014-05-28  0:53   ` Wu, Jingjing
2014-05-28  1:12     ` Wu, Jingjing
2014-06-11 15:45       ` Thomas Monjalon
2014-06-12  8:08         ` Wu, Jingjing
2014-06-12 15:36           ` Thomas Monjalon
2014-06-13 11:51             ` Vladimir Medvedkin
2014-06-13 14:12               ` Wu, Jingjing
2014-06-13 16:19                 ` Vladimir Medvedkin
2014-06-14  1:00                   ` Wu, Jingjing
2014-06-14  9:00                     ` Vladimir Medvedkin
2014-06-04  4:16 ` Cao, Waterman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).