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

--- the v4 patchset changes:
--- change the type of rx_queue to uint16_t
--- change the parameter of rte_eth_dev_add_syn_filter API

--- the v3 patchset changes:
--- comments alignment

--- the v2 patchset changes:
--- add NIC filter support for 82576
--- rework for the whitespace and tab 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):
  ethdev: add ethdev APIs for NIC filters of generic filter
  e1000: add igb NIC filters of generic filter feature
  ixgbe: add ixgbe NIC filters of generic filter feature
  app/test-pmd: add commands in testpmd for NIC filters

 app/test-pmd/cmdline.c              | 909 +++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c               | 147 ++++++
 app/test-pmd/testpmd.h              |   5 +
 lib/librte_ether/rte_ethdev.c       | 275 +++++++++++
 lib/librte_ether/rte_ethdev.h       | 428 +++++++++++++++++
 lib/librte_pmd_e1000/e1000_ethdev.h |  53 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 768 ++++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 440 +++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  34 ++
 9 files changed, 3058 insertions(+), 1 deletion(-)

-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v4 1/4] ethdev: add ethdev APIs for NIC filters of generic filter
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
@ 2014-06-16  7:31 ` Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 2/4] e1000: add igb NIC filters of generic filter feature Jingjing Wu
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jingjing Wu @ 2014-06-16  7:31 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 | 275 +++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 428 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 703 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 8011b8b..42333ee 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>
@@ -2606,3 +2607,277 @@ rte_eth_dev_bypass_wd_reset(uint8_t port_id)
 	return 0;
 }
 #endif
+
+int
+rte_eth_dev_add_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint16_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_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_syn_filter)(dev, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_syn_filter(uint8_t port_id)
+{
+	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_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_syn_filter)(dev);
+}
+
+int
+rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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 67eda50..38ae0b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -813,6 +813,73 @@ 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 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 {
+	uint16_t len;
+	uint32_t dwords[32];  /**< flex bytes in big endian. */
+	uint8_t mask[16];     /**< if mask bit is 1b, do not 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;        /**< l4 protocol. */
+	uint8_t tcp_flags;       /**< 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*
@@ -1114,6 +1181,72 @@ 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_add_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_t rx_queue);
+/**< @internal add syn filter rule on an Ethernet device */
+
+typedef int (*eth_remove_syn_filter_t)(struct rte_eth_dev *dev);
+/**< @internal remove syn filter rule on an Ethernet device */
+
+typedef int (*eth_get_syn_filter_t)(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_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,
+			uint16_t *rx_queue);
+/**< @internal Get a flex filter rule on an Ethernet device */
 
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
@@ -1203,6 +1336,21 @@ struct eth_dev_ops {
 	rss_hash_update_t rss_hash_update;
 	/** Get current RSS hash configuration. */
 	rss_hash_conf_get_t rss_hash_conf_get;
+	eth_add_syn_filter_t           add_syn_filter;       /**< add syn filter. */
+	eth_remove_syn_filter_t        remove_syn_filter;    /**< remove 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. */
 };
 
 /**
@@ -2937,6 +3085,286 @@ int
 rte_eth_dev_rss_hash_conf_get(uint8_t port_id,
 			      struct rte_eth_rss_conf *rss_conf);
 
+/**
+ * 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 filter
+ *   The pointer to the structure describing the syn filter rule.
+ * @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,
+			struct rte_syn_filter *filter, uint16_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, uint16_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, uint16_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 index
+ *   The identifier of ethertype filter.
+ * @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, uint16_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, uint16_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, uint16_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 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, uint16_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, uint16_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, uint16_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, uint16_t *rx_queue);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.8.1.4

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

* [dpdk-dev] [PATCH v4 2/4] e1000: add igb NIC filters of generic filter feature
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 1/4] ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
@ 2014-06-16  7:31 ` Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 3/4] ixgbe: add ixgbe " Jingjing Wu
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jingjing Wu @ 2014-06-16  7:31 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   | 768 ++++++++++++++++++++++++++++++++++++
 2 files changed, 821 insertions(+)

diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index a287f40..71eb5fb 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
+
+#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 6e835c3..343a78c 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -124,6 +124,44 @@ 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_add_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_t rx_queue);
+static int eth_igb_remove_syn_filter(struct rte_eth_dev *dev);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_ethertype_filter *filter, uint16_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, uint16_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_2tuple_filter *filter, uint16_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, uint16_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_flex_filter *filter, uint16_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, uint16_t *rx_queue);
+static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev,
+			uint16_t index,
+			struct rte_5tuple_filter *filter, uint16_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, uint16_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -196,6 +234,21 @@ static struct eth_dev_ops eth_igb_ops = {
 	.reta_query           = eth_igb_rss_reta_query,
 	.rss_hash_update      = eth_igb_rss_hash_update,
 	.rss_hash_conf_get    = eth_igb_rss_hash_conf_get,
+	.add_syn_filter          = eth_igb_add_syn_filter,
+	.remove_syn_filter       = eth_igb_remove_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,
 };
 
 /*
@@ -2186,6 +2239,721 @@ 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)
+
+/*
+ * add the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * 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_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_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));
+	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);
+
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	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;
+}
+
+/*
+ * remove the syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+eth_igb_remove_syn_filter(struct rte_eth_dev *dev)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	E1000_WRITE_REG(hw, E1000_SYNQF(0), 0);
+	return 0;
+}
+
+
+/*
+ * get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * filter: ponter to the filter that returns.
+ * *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, uint16_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));
+	if (synqf & E1000_SYN_FILTER_ENABLE) {
+		rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+		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;
+	}
+	return -ENOENT;
+}
+
+/*
+ * 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, uint16_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, uint16_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, uint16_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, uint16_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, uint16_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 in use. */
+
+	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, uint16_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, uint16_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, uint16_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 = (uint16_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] 7+ messages in thread

* [dpdk-dev] [PATCH v4 3/4] ixgbe: add ixgbe NIC filters of generic filter feature
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 1/4] ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 2/4] e1000: add igb NIC filters of generic filter feature Jingjing Wu
@ 2014-06-16  7:31 ` Jingjing Wu
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 4/4] app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jingjing Wu @ 2014-06-16  7:31 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 | 440 ++++++++++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  34 +++
 2 files changed, 474 insertions(+)

diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 10e5633..ed34386 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>
@@ -196,6 +197,23 @@ static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev,
 				 struct ether_addr *mac_addr,
 				 uint32_t index, uint32_t pool);
 static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index);
+static int ixgbe_add_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_t rx_queue);
+static int ixgbe_remove_syn_filter(struct rte_eth_dev *dev);
+static int ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_t *rx_queue);
+static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_ethertype_filter *filter, uint16_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, uint16_t *rx_queue);
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+			struct rte_5tuple_filter *filter, uint16_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, uint16_t *rx_queue);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -326,6 +344,15 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 #endif /* RTE_NIC_BYPASS */
 	.rss_hash_update      = ixgbe_dev_rss_hash_update,
 	.rss_hash_conf_get    = ixgbe_dev_rss_hash_conf_get,
+	.add_syn_filter	         = ixgbe_add_syn_filter,
+	.remove_syn_filter       = ixgbe_remove_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,
 };
 
 /*
@@ -3388,6 +3415,419 @@ ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index)
 	}
 }
 
+/*
+ * add syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * 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_syn_filter(struct rte_eth_dev *dev,
+			struct rte_syn_filter *filter, uint16_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 (synqf & IXGBE_SYN_FILTER_ENABLE)
+		return -EINVAL;
+
+	synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
+		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;
+}
+
+/*
+ * remove syn filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_remove_syn_filter(struct rte_eth_dev *dev)
+{
+	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);
+
+	synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
+
+	IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
+	return 0;
+}
+
+
+/*
+ * get the syn filter's info
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * filter: ponter to the filter that returns.
+ * *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, uint16_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);
+	if (synqf & IXGBE_SYN_FILTER_ENABLE) {
+		filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0;
+		*rx_queue = (uint16_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1);
+		return 0;
+	}
+	return -ENOENT;
+}
+
+/*
+ * 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,
+			uint16_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,
+			uint16_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, uint16_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, uint16_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 7a4f84c..a5159e5 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -74,6 +74,30 @@
 	(IXGBE_RTTBCNRC_RF_INT_MASK_BASE << IXGBE_RTTBCNRC_RF_INT_SHIFT)
 
 #define IXGBE_MAX_QUEUE_NUM_PER_VF  8
+
+#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.
  */
@@ -157,6 +181,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] 7+ messages in thread

* [dpdk-dev] [PATCH v4 4/4] app/test-pmd: add commands in testpmd for NIC filters
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (2 preceding siblings ...)
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 3/4] ixgbe: add ixgbe " Jingjing Wu
@ 2014-06-16  7:31 ` Jingjing Wu
  2014-06-16 14:15 ` [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Cao, Waterman
  2014-06-16 18:00 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Jingjing Wu @ 2014-06-16  7:31 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 | 909 ++++++++++++++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c  | 147 ++++++++
 app/test-pmd/testpmd.h |   5 +
 3 files changed, 1060 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4678977..8065836 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"
 	);
 
@@ -554,6 +555,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 =
@@ -562,7 +624,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,
@@ -5534,6 +5596,836 @@ 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;
+	uint16_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, UINT16);
+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;
+	uint16_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;
+	struct rte_syn_filter filter;
+
+	if (!strcmp(res->filter, "add_syn_filter")) {
+		if (!strcmp(res->high, "high"))
+			filter.hig_pri = 1;
+		else
+			filter.hig_pri = 0;
+		ret = rte_eth_dev_add_syn_filter(res->port_id,
+				&filter, 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, UINT16);
+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;
+	uint16_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, UINT16);
+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;
+	uint16_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, UINT16);
+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;
+	uint16_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, UINT16);
+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 */
@@ -5624,6 +6516,21 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_rss_hash_key,
 	(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 52ad01a..7a505a1 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1871,3 +1871,150 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
 	return diag;
 }
 
+void
+get_ethertype_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_ethertype_filter filter;
+	int ret = 0;
+	uint16_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;
+	uint16_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+
+	if (ret < 0) {
+		if (ret == (-ENOENT))
+			printf("syn filter is not enabled\n");
+		else
+			printf("get syn filter fails(%s)\n", strerror(-ret));
+		return;
+	}
+	printf("syn filter: priority: %s, queue: %d\n",
+		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;
+	uint16_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;
+	uint16_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;
+	uint16_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 4fabf1c..d750a35 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -538,6 +538,11 @@ int set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate,
 
 void port_rss_hash_conf_show(portid_t port_id, int show_rss_key);
 void port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key);
+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
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (3 preceding siblings ...)
  2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 4/4] app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
@ 2014-06-16 14:15 ` Cao, Waterman
  2014-06-16 18:00 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Cao, Waterman @ 2014-06-16 14:15 UTC (permalink / raw)
  To: Wu, Jingjing, dev

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

This patch includes 4 files, and has been tested by Intel.
Please see test environment 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 above NICs.
 Total cases        Passed               Failed   
     27               25                   2
Failures were caused by HW issues, no impact on functionality.
Please see example: how to distribute specific packet to assigned queue.
  Firstly, 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] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter
  2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
                   ` (4 preceding siblings ...)
  2014-06-16 14:15 ` [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Cao, Waterman
@ 2014-06-16 18:00 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Monjalon @ 2014-06-16 18:00 UTC (permalink / raw)
  To: Jingjing Wu; +Cc: dev

2014-06-16 15:31, 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

Reviewed-by: Vladimir Medvedkin <medvedkinv@gmail.com>
Acked-by: Thomas Monjalon <thomas.monjalon@6wind.com>
I've fixed some doxygen comments and logs.

Applied for version 1.7.0.

Hope to see more patches about filtering in coming weeks.
Thanks
-- 
Thomas

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

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

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-16  7:31 [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Jingjing Wu
2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 1/4] ethdev: add ethdev APIs for NIC filters of " Jingjing Wu
2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 2/4] e1000: add igb NIC filters of generic filter feature Jingjing Wu
2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 3/4] ixgbe: add ixgbe " Jingjing Wu
2014-06-16  7:31 ` [dpdk-dev] [PATCH v4 4/4] app/test-pmd: add commands in testpmd for NIC filters Jingjing Wu
2014-06-16 14:15 ` [dpdk-dev] [PATCH v4 0/4] NIC filters support for generic filter Cao, Waterman
2014-06-16 18:00 ` Thomas Monjalon

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).