* [dpdk-dev] [PATCH 1/4][PMD][GENERIC_FILTER]add ethdev APIs for NIC filters of generic filter feature
  2014-05-20  3:53 [dpdk-dev] [PATCH 0/4][PMD][GENERIC_FILTER] ***NIC filters support of generic feature*** Jingjing Wu
@ 2014-05-20  3:53 ` Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 2/4][PMD][GENERIC_FILTER]add igb " Jingjing Wu
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jingjing Wu @ 2014-05-20  3:53 UTC (permalink / raw)
  To: dev
This patch add 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 | 300 +++++++++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.h | 428 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 727 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a5727dd..ec411db 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -41,6 +41,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <netinet/in.h>
 
 #include <rte_byteorder.h>
 #include <rte_log.h>
@@ -2335,3 +2336,302 @@ rte_eth_dev_bypass_wd_reset(uint8_t port_id)
 	return 0;
 }
 #endif
+
+int
+rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+			uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 1;
+	filter.hig_pri = high_pri;
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_syn_filter(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_syn_filter filter;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	filter.enable = 0;
+	filter.hig_pri = 0;
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_syn_filter, -ENOTSUP);
+	return (*dev->dev_ops->set_syn_filter)(dev, &filter, 0);
+}
+
+int
+rte_eth_dev_get_syn_filter(uint8_t port_id,
+			struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+	
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_syn_filter, -ENOTSUP);
+	return(*dev->dev_ops->get_syn_filter)(dev, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index,
+				struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->ethertype == ETHER_TYPE_IPv4 || filter->ethertype == ETHER_TYPE_IPv6){
+		PMD_DEBUG_TRACE("IP and IPv6 are not supported in ethertype filter\n");
+		return (-EINVAL);
+	}
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_ethertype_filter)(dev, index, 
+							filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_ethertype_filter(uint8_t port_id,  uint16_t index)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_ethertype_filter)(dev, index);
+}
+
+int
+rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, 
+				struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_ethertype_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_ethertype_filter)(dev, index, 
+						filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if (filter->protocol != IPPROTO_TCP &&
+		filter->tcp_flags != 0){
+		PMD_DEBUG_TRACE("tcp flags is 0x%x, but the protocol value is not TCP\n",
+			filter->tcp_flags);
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_2tuple_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+	
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_2tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_2tuple_filter)(dev, index, filter, rx_queue);
+}
+
+int
+rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+	if ((filter->l4type == RTE_FILTER_L4TYPE_NONE) &&
+		(filter->dst_port_mask == 0 || filter->src_port_mask == 0)) {
+		PMD_DEBUG_TRACE(" the L4 protocol type is none, port are meaningless " \
+				"should not involve!\n");
+		return (-EINVAL);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_5tuple_filter)(dev, index, filter, rx_queue);
+	
+}
+
+int
+rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_5tuple_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_5tuple_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_5tuple_filter)(dev, index, filter,
+						rx_queue);
+}
+
+int
+rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->add_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->add_flex_filter)(dev, index, filter, rx_queue);
+	
+}
+
+int
+rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index)
+{
+
+	struct rte_eth_dev *dev;
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->remove_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->remove_flex_filter)(dev, index);
+
+}
+
+int
+rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct rte_eth_dev *dev;
+	
+	if (filter == NULL || rx_queue == NULL)
+		return (-EINVAL);
+
+	if (port_id >= nb_ports) {
+		PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+		return (-ENODEV);
+	}
+
+	dev = &rte_eth_devices[port_id];
+	
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_flex_filter, -ENOTSUP);
+	return (*dev->dev_ops->get_flex_filter)(dev, index, filter,
+						rx_queue);
+}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index dea7471..1e5c09b 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -808,6 +808,80 @@ struct rte_eth_dev_callback;
 /** @internal Structure to keep track of registered callbacks */
 TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);
 
+
+/**
+ *  Possible l4type of 5tuple filters.
+ */
+enum rte_filter_l4type{
+	RTE_FILTER_L4TYPE_TCP = 0,
+	RTE_FILTER_L4TYPE_UDP,
+	RTE_FILTER_L4TYPE_SCTP,
+	RTE_FILTER_L4TYPE_NONE,
+};
+#define TCP_UGR_FLAG 0x20
+#define TCP_ACK_FLAG 0x10
+#define TCP_PSH_FLAG 0x08
+#define TCP_RST_FLAG 0x04
+#define TCP_SYN_FLAG 0x02
+#define TCP_FIN_FLAG 0x01
+#define TCP_FLAG_ALL 0x3F
+
+/**
+ *  A structure used to define an ethertype filter.
+ */
+struct rte_ethertype_filter{
+	uint16_t ethertype;  /**<little endian*/
+	uint8_t priority_en; /**<compare priority enable*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define an syn filter.
+ */
+struct rte_syn_filter{
+	uint8_t enable;  /**<1 means enable, 0 means disable*/
+	uint8_t hig_pri; /**< 1 means higher pri than 2tuple,5tupe, and flex filter, 0 means llower pri*/
+};
+
+/**
+ *  A structure used to define a 2tuple filter.
+ */
+struct rte_2tuple_filter{
+	uint16_t dst_port;  /**<big endian*/
+	uint8_t protocol;
+	uint8_t tcp_flags;
+	uint16_t priority; /**< used when more than one filter matches */
+	uint8_t dst_port_mask : 1,  /**<if mask is 1b, means not compare*/
+			protocol_mask   : 1;
+};
+
+/**
+ *  A structure used to define a flex filter.
+ */
+struct rte_flex_filter{  /** for E1000 filters*/
+	uint16_t len;
+	uint32_t dwords[32];  /**<flex bytes in big endian*/
+	uint8_t mask[16];     /**<if mask bit is 1b, means compare corresponding byte in dwords*/
+	uint8_t priority;
+};
+
+/**
+ *  A structure used to define a 5tuple filter.
+ */
+struct rte_5tuple_filter{
+	uint32_t dst_ip;   /**<destination IP address in big endian*/
+	uint32_t src_ip;   /**<source IP address in big endian*/
+	uint16_t dst_port; /**<destination port in big endian*/
+	uint16_t src_port; /**<source Port big endian*/
+	enum rte_filter_l4type l4type; /**< l4type to match: TCP/UDP/SCTP/NONE. */
+	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*/
+			l4type_mask   : 1; /**<	if mask is 1b, do not compare protocol*/
+};
+
 /*
  * Definitions of all functions exported by an Ethernet driver through the
  * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev*
@@ -1076,6 +1150,69 @@ typedef int32_t (*bypass_ver_show_t)(struct rte_eth_dev *dev, uint32_t *ver);
 typedef int32_t (*bypass_wd_reset_t)(struct rte_eth_dev *dev);
 #endif
 
+typedef int (*eth_set_syn_filter_t)(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+/**< @internal Set syn filter rule on an Ethernet device */
+
+typedef int (*eth_get_syn_filter_t)(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+/**< @internal Get syn filter rule on an Ethernet device */
+
+typedef int (*eth_add_ethertype_filter_t)(struct rte_eth_dev *dev, 
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_remove_ethertype_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_get_ethertype_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get an ethertype filter rule on an Ethernet device */
+
+typedef int (*eth_add_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_2tuple_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_2tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_2tuple_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a 2tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_5tuple_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_remove_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_get_5tuple_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_5tuple_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a 5tuple filter rule on an Ethernet device */
+
+typedef int (*eth_add_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_flex_filter *filter,
+				uint8_t rx_queue);
+/**< @internal Setup a new flex filter rule on an Ethernet device */
+
+typedef int (*eth_remove_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index);
+/**< @internal Remove a flex filter rule on an Ethernet device */
+
+typedef int (*eth_get_flex_filter_t)(struct rte_eth_dev *dev,
+				uint16_t index, struct rte_flex_filter *filter,
+				uint8_t *rx_queue);
+/**< @internal Get a flex filter rule on an Ethernet device */
 
 /**
  * @internal A structure containing the functions exported by an Ethernet driver.
@@ -1152,7 +1289,20 @@ struct eth_dev_ops {
   bypass_ver_show_t bypass_ver_show;
   bypass_wd_reset_t bypass_wd_reset;
 #endif
-
+	eth_set_syn_filter_t           set_syn_filter;  /**< set syn filter. */
+	eth_get_syn_filter_t           get_syn_filter;  /**< get syn filter. */
+	eth_add_ethertype_filter_t     add_ethertype_filter;  /**< add ethertype filter. */
+	eth_remove_ethertype_filter_t  remove_ethertype_filter;  /**< remove ethertype filter*/
+	eth_get_ethertype_filter_t     get_ethertype_filter;  /**< get ethertype filter*/
+	eth_add_2tuple_filter_t        add_2tuple_filter;  /**<add 2tuple filter */
+	eth_remove_2tuple_filter_t     remove_2tuple_filter;  /**< remove 2tuple filter*/
+	eth_get_2tuple_filter_t        get_2tuple_filter;  /**< get 2tuple filter*/
+	eth_add_5tuple_filter_t        add_5tuple_filter;  /**< add 5tuple filter*/
+	eth_remove_5tuple_filter_t     remove_5tuple_filter;  /**< remove 5tuple filter*/
+	eth_get_5tuple_filter_t        get_5tuple_filter;   /**< get 5tuple filter*/
+	eth_add_flex_filter_t        add_flex_filter;  /**< add flex filter*/
+	eth_remove_flex_filter_t     remove_flex_filter;  /**< remove flex filter*/
+	eth_get_flex_filter_t        get_flex_filter;  /**< get flex filter*/
 };
 
 /**
@@ -2859,6 +3009,282 @@ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout);
  */
 int rte_eth_dev_bypass_wd_reset(uint8_t port);
 
+/**
+ * add syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the syn filter.
+ * @param high_pri
+ *    1 means higher pri than 2tuple,5tupe, and flex filter, 0 means lower priority
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_add_syn_filter(uint8_t port_id, uint8_t high_pri,
+				uint8_t rx_queue);
+
+/**
+ * remove syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_remove_syn_filter(uint8_t port_id);
+
+/**
+ * get syn filter
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   The pointer to the structure describing the syn filter.
+ * @param rx_queue
+ *   the point of a int type to get the queue of syn filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_eth_dev_get_syn_filter(uint8_t port_id,
+					struct rte_syn_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @param filter
+ *   The pointer to the structure describing the ethertype filter rule.
+ *   The *rte_ethertype_filter* structure includes the values of the different fields
+ *   to match: ethertype and priority in vlan tag.
+ *   priority in vlan tag is not supported for E1000 dev.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_ethertype_filter(uint8_t port_id, uint16_t index, 
+					struct rte_ethertype_filter *filter, uint8_t rx_queue);
+/**
+ * remove an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of ethertype filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_ethertype_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an ethertype filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param filter
+ *   A pointer to a structure of type *rte_ethertype_filter* to be filled with
+ *   the information of the Ethertype filter. 
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support ethertype filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_ethertype_filter(uint8_t port_id, uint16_t index, 
+					struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+/**
+ * Add a new 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 2tuple filter rule.
+ *   The *rte_2tuple_filter* structure includes the values of the different fields
+ *   to match: protocol, dst_port and tcp_flags if the protocol is tcp type.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+
+int rte_eth_dev_add_2tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_2tuple_filter *filter, uint8_t rx_queue);
+/**
+ * remove a 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_2tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 2tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 2tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_2tuple_filter* to be filled with
+ *   the information of the 2tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 2tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_get_2tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   The pointer to the structure describing the 5tuple filter rule.
+ *   The *rte_5tuple_filter* structure includes the values of the different fields
+ *   to match: dst src IP, dst src port, l4type and relative masks..
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_add_5tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_5tuple_filter *filter, uint8_t rx_queue);
+
+/**
+ * remove a 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_5tuple_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an 5tuple filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of 5tuple filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_5tuple_filter* to be filled with
+ *   the information of the 5tuple filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support 5tuple filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_get_5tuple_filter(uint8_t port_id, uint16_t index,
+					struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
+/**
+ * Add a new flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   The pointer to the structure describing the flex filter rule.
+ *   The *rte_flex_filter* structure includes the values of the different fields
+ *   to match: the dwords (first len bytes of packet ) and relative masks.
+ * @param rx_queue
+ *   The index of the RX queue where to store RX packets matching the added
+ *   flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+int rte_eth_dev_add_flex_filter(uint8_t port_id, uint16_t index,
+					struct rte_flex_filter *filter, uint8_t rx_queue);
+/**
+ * remove a flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ */
+int rte_eth_dev_remove_flex_filter(uint8_t port_id, uint16_t index);
+
+/**
+ * Get an flex filter rule on an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+  * @param index
+ *   The identifier of flex filter.
+ * @param filter
+ *   A pointer to a structure of type *rte_flex_filter* to be filled with
+ *   the information of the flex filter.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if hardware doesn't support flex filter.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if the filter information is not correct.
+ *   - (-ENOENT) if no enabled filter in this index.
+ */
+
+int rte_eth_dev_get_flex_filter(uint8_t port_id, uint16_t index,
+					struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.8.1.4
^ permalink raw reply	[flat|nested] 5+ messages in thread* [dpdk-dev] [PATCH 2/4][PMD][GENERIC_FILTER]add igb NIC filters of generic filter feature
  2014-05-20  3:53 [dpdk-dev] [PATCH 0/4][PMD][GENERIC_FILTER] ***NIC filters support of generic feature*** Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 1/4][PMD][GENERIC_FILTER]add ethdev APIs for NIC filters of generic filter feature Jingjing Wu
@ 2014-05-20  3:53 ` Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 3/4][PMD][GENERIC_FILTER]add ixgbe " Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 4/4][PMD][GENERIC_FILTER] add commands in testpmd for NIC filters Jingjing Wu
  3 siblings, 0 replies; 5+ messages in thread
From: Jingjing Wu @ 2014-05-20  3:53 UTC (permalink / raw)
  To: dev
This patch adds following igb NIC filters implement for intel NIC 82580 and i350
  syn filter, ethertype filter, 2tuple filter, flex filter
Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_e1000/e1000_ethdev.h |  38 +++
 lib/librte_pmd_e1000/igb_ethdev.c   | 512 ++++++++++++++++++++++++++++++++++++
 2 files changed, 550 insertions(+)
diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h
index d09064e..6b11289 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -52,6 +52,44 @@
 #define E1000_CTRL_EXT_EXTEND_VLAN  (1<<26)    /* EXTENDED VLAN */
 #define IGB_VFTA_SIZE 128
 
+#define IGB_MAX_RX_QUEUE_NUM	8
+
+#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 IXGBE_WUFC_FLEX_HQ	0x00004000
+
 /* 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 673b4de..478688f 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -123,6 +123,28 @@ static int eth_igb_rss_reta_update(struct rte_eth_dev *dev,
 static int eth_igb_rss_reta_query(struct rte_eth_dev *dev,
 		struct rte_eth_rss_reta *reta_conf);
 
+static int eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, 
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index);
+static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue);
+static int eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue);
+static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -193,6 +215,17 @@ static struct eth_dev_ops eth_igb_ops = {
 	.mac_addr_remove      = eth_igb_rar_clear,
 	.reta_update          = eth_igb_rss_reta_update,
 	.reta_query           = eth_igb_rss_reta_query,
+	.set_syn_filter		     = eth_igb_set_syn_filter,
+	.get_syn_filter          = eth_igb_get_syn_filter,
+	.add_ethertype_filter	 = eth_igb_add_ethertype_filter,
+	.remove_ethertype_filter = eth_igb_remove_ethertype_filter,
+	.get_ethertype_filter	 = eth_igb_get_ethertype_filter,
+	.add_2tuple_filter 	     = eth_igb_add_2tuple_filter,
+	.remove_2tuple_filter	 = eth_igb_remove_2tuple_filter,
+	.get_2tuple_filter	 	 = eth_igb_get_2tuple_filter,
+	.add_flex_filter 	     = eth_igb_add_flex_filter,
+	.remove_flex_filter	 	 = eth_igb_remove_flex_filter,
+	.get_flex_filter	 	 = eth_igb_get_flex_filter,
 };
 
 /*
@@ -2182,3 +2215,482 @@ 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) \
+		return -ENOSYS;\
+}while(0)
+
+/*
+ *set the syn filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	
+    if (filter->enable){
+		if (synqf & E1000_SYN_FILTER_ENABLE)
+			return (-EINVAL);
+		synqf = (uint32_t)(((rx_queue << E1000_SYN_FILTER_QUEUE_SHIFT) & E1000_SYN_FILTER_QUEUE) |
+						E1000_SYN_FILTER_ENABLE);
+    }else
+		synqf = 0;
+	
+	if (filter->hig_pri)
+		rfctl |= E1000_RFCTL_SYNQFP;
+	else
+		rfctl &= ~E1000_RFCTL_SYNQFP;
+	
+	E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf);
+	E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+	return 0;
+}
+
+/*
+ *get the syn filter's info
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf, rfctl;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	synqf = E1000_READ_REG(hw, E1000_SYNQF(0));
+	rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+	filter->enable = (synqf & E1000_SYN_FILTER_ENABLE)? 1 : 0;
+	filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE)>> E1000_SYN_FILTER_QUEUE_SHIFT);
+
+	return 0;
+}
+
+/*
+ *add an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_ETQF_FILTERS || rx_queue >= IGB_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE){
+		return (-EINVAL);  /**filter index is in use*/
+	}
+	else 
+		etqf = 0;
+		
+	etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE;
+	etqf |= (uint32_t)(filter->ethertype & E1000_ETQF_ETHERTYPE);
+	etqf |= rx_queue << E1000_ETQF_QUEUE_SHIFT;
+	
+	if (filter->priority_en){
+		PMD_INIT_LOG(ERR, "vlan and priority (%d) is not support in E1000.\n",
+			filter->priority);
+		return (-EINVAL);
+	}
+	
+	E1000_WRITE_REG(hw, E1000_ETQF(index), etqf);
+	
+	return 0;
+}
+
+/*
+ *remove an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+	
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	E1000_WRITE_REG(hw, E1000_ETQF(index), 0);
+	
+	return 0;
+}
+
+/*
+ *gets an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf;
+		
+	MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+	if (index >= E1000_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	etqf = E1000_READ_REG(hw, E1000_ETQF(index));
+	if (etqf & E1000_ETQF_FILTER_ENABLE ){
+		filter->ethertype = etqf & E1000_ETQF_ETHERTYPE;
+		filter->priority_en = 0;
+		*rx_queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ttqf, imir = 0;
+	uint32_t imir_ext = 0;
+	
+	MAC_TYPE_FILTER_SUP(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(hw->mac.type);
+	
+	if (index >= E1000_MAX_TTQF_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
+	E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+	return 0;
+
+}
+
+/*
+ *get a 2tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_2tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t imir, ttqf;
+	
+	MAC_TYPE_FILTER_SUP(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;
+		return 0;
+	}
+	return (-ENOENT);
+}
+
+/*
+ *add a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_add_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, en_bits = 0;
+	uint32_t queueing = 0;
+	uint32_t reg_off = 0;
+	uint8_t i, j= 0;
+
+	MAC_TYPE_FILTER_SUP(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 = IXGBE_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << index);
+	if ((wufc & en_bits) == en_bits)
+		return (-EINVAL);  /**the filter is  enabled*/
+	
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc | IXGBE_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(hw->mac.type);
+	
+	if (index >= E1000_MAX_FLEXIBLE_FILTERS)
+		return (-EINVAL);  /**filter index is out of range*/
+	
+	wufc = E1000_READ_REG(hw, E1000_WUFC);
+	E1000_WRITE_REG(hw, E1000_WUFC, wufc &(~(E1000_WUFC_FLX0 << index)));
+	
+	if (index < E1000_MAX_FHFT)
+		reg_off = E1000_FHFT(index);
+	else
+		reg_off = E1000_FHFT_EXT(index - E1000_MAX_FHFT);
+	
+	for (i = 0; i < 64; i++)
+		E1000_WRITE_REG(hw, reg_off + i*4, 0);
+	return 0;
+}
+
+/*
+ *get a flex filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: the pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_flex_filter *filter, uint8_t *rx_queue)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t wufc, queueing, wufc_en = 0;
+	uint8_t i,j;
+
+	MAC_TYPE_FILTER_SUP(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 = IXGBE_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);
+}
-- 
1.8.1.4
^ permalink raw reply	[flat|nested] 5+ messages in thread* [dpdk-dev] [PATCH 3/4][PMD][GENERIC_FILTER]add ixgbe NIC filters of generic filter feature
  2014-05-20  3:53 [dpdk-dev] [PATCH 0/4][PMD][GENERIC_FILTER] ***NIC filters support of generic feature*** Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 1/4][PMD][GENERIC_FILTER]add ethdev APIs for NIC filters of generic filter feature Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 2/4][PMD][GENERIC_FILTER]add igb " Jingjing Wu
@ 2014-05-20  3:53 ` Jingjing Wu
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 4/4][PMD][GENERIC_FILTER] add commands in testpmd for NIC filters Jingjing Wu
  3 siblings, 0 replies; 5+ messages in thread
From: Jingjing Wu @ 2014-05-20  3:53 UTC (permalink / raw)
  To: dev
This patch adds following ixgbe NIC filters implement for intel NIC 82599
  syn filter, ethertype filter, 5tuple filter
Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 365 ++++++++++++++++++++++++++++++++++++
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  33 ++++
 2 files changed, 398 insertions(+)
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 89ab4aa..49ff0d1 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -181,6 +181,22 @@ static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev,
 static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev,
 		uint8_t	rule_id);
 
+static int ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue);
+static int ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, uint16_t index, 
+					   struct rte_ethertype_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev, uint16_t index);
+static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_ethertype_filter *filter, uint8_t *rx_queue);
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue);
+static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+					   uint16_t index);
+static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue);
+
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
  */
@@ -300,6 +316,14 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.bypass_ver_show      = ixgbe_bypass_ver_show,
 	.bypass_wd_reset      = ixgbe_bypass_wd_reset,
 #endif /* RTE_NIC_BYPASS */
+	.set_syn_filter		     = ixgbe_set_syn_filter,
+	.get_syn_filter          = ixgbe_get_syn_filter,
+	.add_ethertype_filter	 = ixgbe_add_ethertype_filter,
+	.remove_ethertype_filter = ixgbe_remove_ethertype_filter,
+	.get_ethertype_filter	 = ixgbe_get_ethertype_filter,
+	.add_5tuple_filter 	     = ixgbe_add_5tuple_filter,
+	.remove_5tuple_filter	 = ixgbe_remove_5tuple_filter,
+	.get_5tuple_filter	 	 = ixgbe_get_5tuple_filter,
 };
 
 /*
@@ -3060,3 +3084,344 @@ ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id)
 
 	return 0;
 }
+
+/*
+ * set the syn filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * syn: 1 means enable, 0 means disable.
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_set_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	if (rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	
+    if (filter->enable)
+		synqf = (uint32_t)(((rx_queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) &
+			IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE);
+	else
+		synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE);
+
+	
+	if (filter->hig_pri)
+		synqf |= IXGBE_SYN_FILTER_SYNQFP;
+	else
+		synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
+
+	IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
+	
+	return 0;
+}
+
+/*
+ * get the syn filter's info
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * *syn: pointer to syn value (1 means enable, 0 means disable).
+ * *rx_queue: pointer to the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_syn_filter(struct rte_eth_dev *dev,
+					   struct rte_syn_filter *filter, uint8_t *rx_queue)
+
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t synqf;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+
+	synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
+	filter->enable = (synqf & IXGBE_SYN_FILTER_ENABLE) ? 1 : 0;
+	filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0;
+	*rx_queue = (uint8_t)((synqf & IXGBE_SYN_FILTER_QUEUE)>> 1);
+
+	return 0;
+}
+
+/*
+ * add an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_add_ethertype_filter(struct rte_eth_dev *dev, 
+				uint16_t index, struct rte_ethertype_filter *filter,
+				uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs = 0;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS || rx_queue >= IXGBE_MAX_RX_QUEUE_NUM)
+		return (-EINVAL);
+	
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN)
+		return (-EINVAL);  /** filter index is in use*/
+	
+	etqf = 0;
+	etqf |= IXGBE_ETQF_FILTER_EN;
+	etqf |= (uint32_t)filter->ethertype;
+	
+	if (filter->priority_en){
+		if (filter->priority > IXGBE_ETQF_MAX_PRI)
+			return (-EINVAL);
+		etqf |= (uint32_t)((filter->priority << IXGBE_ETQF_SHIFT ) & IXGBE_ETQF_UP);
+		etqf |= IXGBE_ETQF_UP_EN;
+	}
+	etqs |= (uint32_t)((rx_queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE);
+	etqs |= IXGBE_ETQS_QUEUE_EN;
+	
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), etqf);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), etqs);
+	
+	return 0;
+}
+
+/*
+ * remove an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_remove_ethertype_filter(struct rte_eth_dev *dev,
+					uint16_t index)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	IXGBE_WRITE_REG(hw, IXGBE_ETQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_ETQS(index), 0);
+	
+	return 0;
+}
+
+/*
+ * gets an ethertype filter
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be gotten
+ * *rx_queue: the ponited of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_ethertype_filter(struct rte_eth_dev *dev,
+					uint16_t index, struct rte_ethertype_filter *filter,
+					uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t etqf, etqs;
+	
+	if (hw->mac.type != ixgbe_mac_82599EB)
+		return -ENOSYS;
+	
+	if (index >= IXGBE_MAX_ETQF_FILTERS)
+		return (-EINVAL);
+	
+	etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(index));
+	etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(index));
+	if (etqf & IXGBE_ETQF_FILTER_EN){
+		filter->ethertype = etqf & IXGBE_ETQF_ETHERTYPE;
+		filter->priority_en = (etqf & IXGBE_ETQF_UP_EN)? 1 : 0;
+		if (filter->priority_en)
+			filter->priority = (etqf & IXGBE_ETQF_UP) >> 16;
+		*rx_queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT;
+		return 0;
+	}
+	
+	return (-ENOENT);
+}
+
+/*
+ * add a 5tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that will be added
+ * rx_queue: the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t ftqf, sdpqf = 0;
+	uint32_t l34timir = 0;
+	
+	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*/
+	
+	ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
+	if (ftqf & IXGBR_FTQF_ENABLE)
+		return (-EINVAL);  /** filter index is in use*/
+	ftqf = 0;
+		
+	sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDQPF_DSTPORT_SHIFT);
+	sdpqf = sdpqf |(filter->src_port & IXGBE_SDQPF_SRCPORT);
+
+	ftqf |= (uint32_t)(filter->l4type & IXGBR_FTQF_PROTOCOL);
+	ftqf |= (uint32_t)((filter->priority << IXGBR_FTQF_PRIORITY_SHIFT) & IXGBR_FTQF_PRIORITY);
+	if (filter->src_ip_mask == 1) /** 1b means not compare*/
+		ftqf |= IXGBR_FTQF_SRCIP_MASK;
+	if (filter->dst_ip_mask == 1)
+		ftqf |= IXGBR_FTQF_DSTIP_MASK;
+	if (filter->src_port_mask == 1)
+		ftqf |= IXGBR_FTQF_SRCPORT_MASK;
+	if (filter->dst_port_mask == 1)
+		ftqf |= IXGBR_FTQF_DSTPORT_MASK;
+	if (filter->l4type_mask == 1)
+		ftqf |= IXGBR_FTQF_L4TYPE_MASK;
+	ftqf |= IXGBR_FTQF_POOL_MASK;
+	ftqf |= IXGBR_FTQF_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_FTQF(index), 0);
+	IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0);
+	return 0;
+
+}
+
+/*
+ * get a 5tuple filter 
+ *
+ * @param 
+ * dev: Pointer to struct rte_eth_dev.
+ * index: the index the filter allocates
+ * filter: ponter to the filter that returns
+ * *rx_queue: pointer of the queue id the filter assigned to
+ *
+ * @return
+ *	- On success, zero.
+ *	- On failure, a negative value.
+ */
+static int
+ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
+					   struct rte_5tuple_filter *filter, uint8_t *rx_queue)
+{
+	struct ixgbe_hw *hw= IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t sdpqf, ftqf, l34timir;
+
+	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 & IXGBR_FTQF_ENABLE){
+		filter->l4type = (enum rte_filter_l4type)(ftqf & IXGBR_FTQF_PROTOCOL);
+		filter->priority = (ftqf & IXGBR_FTQF_PRIORITY) >> IXGBR_FTQF_PRIORITY_SHIFT;
+		filter->src_ip_mask = (ftqf & IXGBR_FTQF_SRCIP_MASK) ? 1 : 0;
+		filter->dst_ip_mask = (ftqf & IXGBR_FTQF_DSTIP_MASK) ? 1 : 0;
+		filter->src_port_mask = (ftqf & IXGBR_FTQF_SRCPORT_MASK) ? 1 : 0;
+		filter->dst_port_mask = (ftqf & IXGBR_FTQF_DSTPORT_MASK) ? 1 : 0;
+		filter->l4type_mask = (ftqf & IXGBR_FTQF_L4TYPE_MASK) ? 1 : 0;
+		
+		sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index));
+		filter->dst_port = (sdpqf & IXGBE_SDQPF_DSTPORT) >> IXGBE_SDQPF_DSTPORT_SHIFT;
+		filter->src_port = sdpqf & IXGBE_SDQPF_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);
+}
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index 9d7e93f..7c6139b 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -67,6 +67,39 @@
 #define IXGBE_LPBK_82599_NONE		0x0 /* Default value. Loopback is disabled. */
 #define IXGBE_LPBK_82599_TX_RX		0x1 /* Tx->Rx loopback operation is enabled. */
 
+#define IXGBE_SYN_FILTER_ENABLE			0x00000001 /** syn filter enable field*/
+#define IXGBE_SYN_FILTER_QUEUE      	0x000000FE /** syn filter queue field*/
+#define IXGBE_SYN_FILTER_QUEUE_SHIFT 	1        /** syn filter queue field shift*/
+#define IXGBE_SYN_FILTER_SYNQFP     	0x80000000 /**syn filter SYNQFP*/
+
+#define IXGBE_ETQF_UP 			0x00070000 /** ethertype filter priority field*/ 
+#define IXGBE_ETQF_SHIFT 		16
+#define IXGBE_ETQF_UP_EN 		0x00080000
+#define IXGBE_ETQF_ETHERTYPE 	0x0000FFFF /** ethertype filter ethertype field*/
+#define IXGBE_ETQF_MAX_PRI 		7
+
+#define IXGBE_SDQPF_DSTPORT			0xFFFF0000 /** dst port field */
+#define IXGBE_SDQPF_DSTPORT_SHIFT	16 /** dst port field shift*/
+#define IXGBE_SDQPF_SRCPORT			0x0000FFFF /** src port field */
+#define IXGBR_FTQF_PROTOCOL			0x00000003 /** protocol */
+#define IXGBR_FTQF_PRIORITY			0x0000001C /** priority */
+#define IXGBR_FTQF_PRIORITY_SHIFT   2
+#define IXGBR_FTQF_SRCIP_MASK   	0x02000000 /** src IP mask */
+#define IXGBR_FTQF_DSTIP_MASK   	0x04000000 /** dst IP mask */
+#define IXGBR_FTQF_SRCPORT_MASK 	0x08000000 /** src port mask */
+#define IXGBR_FTQF_DSTPORT_MASK 	0x10000000 /** dst port mask */
+#define IXGBR_FTQF_L4TYPE_MASK		0x20000000 /** protocol mask */
+#define IXGBR_FTQF_POOL_MASK		0x40000000 /** pool mask */
+#define IXGBR_FTQF_ENABLE			0x80000000 /** enable bit */
+#define IXGBR_FTQF_PRIORITY_DEFAULT 0x00000004
+#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.
  */
-- 
1.8.1.4
^ permalink raw reply	[flat|nested] 5+ messages in thread* [dpdk-dev] [PATCH 4/4][PMD][GENERIC_FILTER] add commands in testpmd for NIC filters
  2014-05-20  3:53 [dpdk-dev] [PATCH 0/4][PMD][GENERIC_FILTER] ***NIC filters support of generic feature*** Jingjing Wu
                   ` (2 preceding siblings ...)
  2014-05-20  3:53 ` [dpdk-dev] [PATCH 3/4][PMD][GENERIC_FILTER]add ixgbe " Jingjing Wu
@ 2014-05-20  3:53 ` Jingjing Wu
  3 siblings, 0 replies; 5+ messages in thread
From: Jingjing Wu @ 2014-05-20  3:53 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 | 905 ++++++++++++++++++++++++++++++++++++++++++++++++-
 app/test-pmd/config.c  | 143 ++++++++
 app/test-pmd/testpmd.h |   6 +
 3 files changed, 1053 insertions(+), 1 deletion(-)
diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 7becedc..fadfe32 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"
 	);
 
@@ -550,6 +551,68 @@ 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 (tcp|udp|sctp|none)"
+			" mask (mask_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 =
@@ -558,7 +621,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,
@@ -5107,6 +5170,831 @@ cmdline_parse_inst_t cmd_dump_one = {
 	},
 };
 
+/* *** ADD/REMOVE an ethertype FILTER *** */
+struct cmd_ethertype_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t ethertype;
+	uint16_t ethertype_value;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t priority_en;
+	uint8_t priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_ethertype_filter_result *res = parsed_result;
+	struct rte_ethertype_filter filter;
+
+	
+	memset(&filter, 0, sizeof(struct rte_ethertype_filter));
+	filter.ethertype = rte_cpu_to_le_16(res->ethertype_value);
+	filter.priority = res->priority_value;
+	
+	if (!strcmp(res->priority_en, "enable"))
+		filter.priority_en = 1;
+	if (!strcmp(res->filter, "add_ethertype_filter"))
+		ret = rte_eth_dev_add_ethertype_filter(res->port_id, res->index_value,
+					  &filter, res->queue_id);
+	else if (!strcmp(res->filter, "remove_ethertype_filter"))
+		ret = rte_eth_dev_remove_ethertype_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_ethertype_filter"))
+		get_ethertype_filter(res->port_id, res->index_value);
+	
+	if (ret < 0)
+		printf("ethertype filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 ethertype, "ethertype");
+cmdline_parse_token_ipaddr_t cmd_ethertype_filter_ethertype_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				 ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority, "priority");
+cmdline_parse_token_string_t cmd_ethertype_filter_priority_en =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority_en, "enable#disable");
+cmdline_parse_token_num_t cmd_ethertype_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+				 priority_value, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_ethertype_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "add_ethertype_filter");
+cmdline_parse_inst_t cmd_add_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "add an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_add_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_ethertype,
+		(void *)&cmd_ethertype_filter_ethertype_value,
+		(void *)&cmd_ethertype_filter_priority,
+		(void *)&cmd_ethertype_filter_priority_en,
+		(void *)&cmd_ethertype_filter_priority_value,
+		(void *)&cmd_ethertype_filter_queue,
+		(void *)&cmd_ethertype_filter_queue_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "remove_ethertype_filter");
+cmdline_parse_inst_t cmd_remove_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "remove an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_remove_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_ethertype_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+				 filter, "get_ethertype_filter");
+cmdline_parse_inst_t cmd_get_ethertype_filter = {
+	.f = cmd_ethertype_filter_parsed,
+	.data = NULL,
+	.help_str = "get an ethertype filter",
+	.tokens = {
+		(void *)&cmd_ethertype_filter_get_filter,
+		(void *)&cmd_ethertype_filter_port_id,
+		(void *)&cmd_ethertype_filter_index,
+		(void *)&cmd_ethertype_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** set SYN filter *** */
+struct cmd_set_syn_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t port_id;
+	cmdline_fixed_string_t priority;
+	cmdline_fixed_string_t high;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+};
+
+static void
+cmd_set_syn_filter_parsed(void *parsed_result,
+		       __attribute__((unused)) struct cmdline *cl,
+		       __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct cmd_set_syn_filter_result *res = parsed_result;
+	if (!strcmp(res->filter, "add_syn_filter")){
+		if(!strcmp(res->high, "high"))
+			ret = rte_eth_dev_add_syn_filter(res->port_id, 1, res->queue_id);
+		else
+			ret = rte_eth_dev_add_syn_filter(res->port_id, 0, res->queue_id);
+	}else if(!strcmp(res->filter, "remove_syn_filter"))
+		ret = rte_eth_dev_remove_syn_filter(res->port_id);
+	else if(!strcmp(res->filter, "get_syn_filter"))
+		get_syn_filter(res->port_id);
+	if(ret < 0)
+		printf("syn filter setting error: (%s)\n", strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_syn_filter_portid =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				 priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_set_syn_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "add_syn_filter");
+cmdline_parse_token_string_t cmd_syn_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "remove_syn_filter");
+cmdline_parse_inst_t cmd_add_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "add syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_add_filter,
+			(void *)&cmd_syn_filter_portid,
+			(void *)&cmd_syn_filter_priority,
+			(void *)&cmd_syn_filter_high,
+			(void *)&cmd_syn_filter_queue,
+			(void *)&cmd_syn_filter_queue_id,
+			NULL,
+		},
+};
+cmdline_parse_inst_t cmd_remove_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "remove syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_remove_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+cmdline_parse_token_string_t cmd_syn_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_set_syn_filter_result,
+				filter, "get_syn_filter");
+
+cmdline_parse_inst_t cmd_get_syn_filter = {
+		.f = cmd_set_syn_filter_parsed,
+		.data = NULL,
+		.help_str = "get syn filter",
+		.tokens = {
+			(void *)&cmd_syn_filter_get_filter,
+			(void *)&cmd_syn_filter_portid,
+			NULL,
+		},
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t protocol;
+	uint8_t protocol_value;
+	uint8_t protocol_mask;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	uint16_t dst_port_mask;
+	cmdline_fixed_string_t flags;
+	uint8_t flags_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_2tuple_filter filter;
+	struct cmd_2tuple_filter_result *res = parsed_result;
+
+	memset(&filter, 0, sizeof(struct rte_2tuple_filter));
+	
+	if (!strcmp(res->filter, "add_2tuple_filter")){
+		/** need convert to big endian*/
+		filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+		filter.protocol = res->protocol_value;
+		filter.dst_port_mask = (res->dst_port_mask) ? 0 : 1;
+		filter.protocol_mask = (res->protocol_mask) ? 0 : 1;
+		filter.priority = res->priority_value;
+		filter.tcp_flags = res->flags_value;
+		
+		ret = rte_eth_dev_add_2tuple_filter(res->port_id, res->index_value,
+				  &filter, res->queue_id);
+	} else if (!strcmp(res->filter, "remove_2tuple_filter"))
+		ret = rte_eth_dev_remove_2tuple_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_2tuple_filter"))
+		get_2tuple_filter(res->port_id, res->index_value);
+
+	if(ret < 0)
+		printf("2tuple filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol, "protocol");
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 protocol_value, UINT8);
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     protocol_mask, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     dst_port_value, UINT16);
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			     dst_port_mask, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_flags =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 flags, "flags");
+cmdline_parse_token_string_t cmd_2tuple_filter_flags_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+				 flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_2tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "add_2tuple_filter");
+cmdline_parse_inst_t cmd_add_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_add_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_protocol,
+		(void *)&cmd_2tuple_filter_protocol_value,
+		(void *)&cmd_2tuple_filter_protocol_mask,
+		(void *)&cmd_2tuple_filter_dst_port,
+		(void *)&cmd_2tuple_filter_dst_port_value,
+		(void *)&cmd_2tuple_filter_dst_port_mask,
+		(void *)&cmd_2tuple_filter_flags,
+		(void *)&cmd_2tuple_filter_flags_value,
+		(void *)&cmd_2tuple_filter_priority,
+		(void *)&cmd_2tuple_filter_priority_value,
+		(void *)&cmd_2tuple_filter_queue,
+		(void *)&cmd_2tuple_filter_queue_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_2tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "remove_2tuple_filter");
+cmdline_parse_inst_t cmd_remove_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_remove_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+cmdline_parse_token_string_t cmd_2tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+				 filter, "get_2tuple_filter");
+cmdline_parse_inst_t cmd_get_2tuple_filter = {
+	.f = cmd_2tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 2tuple filter",
+	.tokens = {
+		(void *)&cmd_2tuple_filter_get_filter,
+		(void *)&cmd_2tuple_filter_port_id,
+		(void *)&cmd_2tuple_filter_index,
+		(void *)&cmd_2tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t dst_ip;
+	cmdline_ipaddr_t dst_ip_value;
+	cmdline_fixed_string_t src_ip;
+	cmdline_ipaddr_t src_ip_value;
+	cmdline_fixed_string_t dst_port;
+	uint16_t dst_port_value;
+	cmdline_fixed_string_t src_port;
+	uint16_t src_port_value;
+	cmdline_fixed_string_t protocol;
+	cmdline_fixed_string_t protocol_value;
+	cmdline_fixed_string_t mask;
+	uint8_t  mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static 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.l4type_mask = (res->mask_value & 0x01) ? 0 : 1;
+		filter.priority = res->priority_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 invovle 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 invovle 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);
+
+		if (!strcmp(res->protocol_value, "udp"))
+			filter.l4type = RTE_FILTER_L4TYPE_UDP;
+		else if (!strcmp(res->protocol_value, "tcp"))
+			filter.l4type = RTE_FILTER_L4TYPE_TCP;
+		else if (!strcmp(res->protocol_value, "sctp"))
+			filter.l4type = RTE_FILTER_L4TYPE_SCTP;
+		else 
+			filter.l4type = RTE_FILTER_L4TYPE_NONE;
+		
+		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_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 protocol_value, "tcp#udp#sctp#none");
+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_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_5tuple_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+			      index_value, UINT16);
+
+cmdline_parse_token_string_t cmd_5tuple_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "add_5tuple_filter");
+cmdline_parse_inst_t cmd_add_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "add a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_add_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_dst_ip,
+		(void *)&cmd_5tuple_filter_dst_ip_value,
+		(void *)&cmd_5tuple_filter_src_ip,
+		(void *)&cmd_5tuple_filter_src_ip_value,
+		(void *)&cmd_5tuple_filter_dst_port,
+		(void *)&cmd_5tuple_filter_dst_port_value,
+		(void *)&cmd_5tuple_filter_src_port,
+		(void *)&cmd_5tuple_filter_src_port_value,
+		(void *)&cmd_5tuple_filter_protocol,
+		(void *)&cmd_5tuple_filter_protocol_value,
+		(void *)&cmd_5tuple_filter_mask,
+		(void *)&cmd_5tuple_filter_mask_value,
+		(void *)&cmd_5tuple_filter_priority,
+		(void *)&cmd_5tuple_filter_priority_value,
+		(void *)&cmd_5tuple_filter_queue,
+		(void *)&cmd_5tuple_filter_queue_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "remove_5tuple_filter");
+cmdline_parse_inst_t cmd_remove_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_remove_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_5tuple_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+				 filter, "get_5tuple_filter");
+cmdline_parse_inst_t cmd_get_5tuple_filter = {
+	.f = cmd_5tuple_filter_parsed,
+	.data = NULL,
+	.help_str = "get a 5tuple filter",
+	.tokens = {
+		(void *)&cmd_5tuple_filter_get_filter,
+		(void *)&cmd_5tuple_filter_port_id,
+		(void *)&cmd_5tuple_filter_index,
+		(void *)&cmd_5tuple_filter_index_value,
+		NULL,
+	},
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+	cmdline_fixed_string_t filter;
+	uint8_t  port_id;
+	cmdline_fixed_string_t len;
+	uint8_t len_value;
+	cmdline_fixed_string_t bytes;
+	cmdline_fixed_string_t bytes_value;
+	cmdline_fixed_string_t mask;
+	cmdline_fixed_string_t mask_value;
+	cmdline_fixed_string_t priority;
+	uint8_t  priority_value;
+	cmdline_fixed_string_t queue;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t index;
+	uint16_t  index_value;
+};
+
+static int xdigit2val(unsigned char c)
+{
+	int val;
+	if(isdigit(c)) 
+		val = c - '0';
+	else if(isupper(c))
+		val = c - 'A' + 10;
+	else 
+		val = c - 'a' + 10;
+	return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	int ret = 0;
+	struct rte_flex_filter filter;
+	struct cmd_flex_filter_result *res = parsed_result;
+	char * bytes_ptr, *mask_ptr;
+	uint16_t len, i, j;
+	char c;
+	int val, mod = 0;
+	uint32_t dword = 0;
+	uint8_t byte = 0;
+	uint8_t hex = 0;
+
+	if (!strcmp(res->filter, "add_flex_filter")){
+		if(res->len_value > 128){
+			printf("the len exceed the max length 128\n");
+			return;
+		}
+		memset(&filter, 0, sizeof(struct rte_flex_filter));
+		filter.len = res->len_value;
+		filter.priority = res->priority_value;
+		bytes_ptr = res->bytes_value;
+		mask_ptr = res->mask_value;
+
+		j = 0;
+		 /** translate bytes string to uint_32 array*/
+		if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+			(bytes_ptr[1] == 'X')) )
+			bytes_ptr += 2;
+		
+		len = strnlen(bytes_ptr, res->len_value * 2);
+		if (len == 0 || (len % 8 != 0)){
+			printf("please check len and bytes input\n");
+			return;
+		}
+		
+		for (i = 0; i < len; i++) { 
+			c = bytes_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			mod = i % 8;
+			if (i % 2){
+				byte |= val;
+				dword |= byte << (4 * mod - 4);
+				byte = 0;
+			}
+			else
+				byte |= val << 4;
+			if (mod == 7){
+				filter.dwords[j] = dword;
+				printf("dwords[%d]:%08x ",j, filter.dwords[j]);
+				j++;
+				dword = 0;
+			}
+		}
+		printf("\n");
+		 /** translate mask string to uint8_t array*/
+		j = 0;  
+		if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+			(mask_ptr[1] == 'X')) )
+			mask_ptr += 2;
+		len = strnlen(mask_ptr, (res->len_value+3)/4);
+		if (len == 0){
+			printf("invalid input\n");
+			return;
+		}
+		for (i = 0; i < len; i++) {
+			c = mask_ptr[i];
+			if (isxdigit(c) == 0) {
+				/** invalid characters */
+				printf("invalid input\n");
+				return;
+			}
+			val = xdigit2val(c);
+			hex |= (uint8_t)(val & 0x8) >> 3;
+			hex |= (uint8_t)(val & 0x4) >> 1;
+			hex |= (uint8_t)(val & 0x2) << 1;
+			hex |= (uint8_t)(val & 0x1) << 3;
+
+			if (i % 2){
+				byte |= hex << 4;
+				filter.mask[j] = byte;
+				printf("mask[%d]:%02x ",j, filter.mask[j]);
+				j++;
+				byte = 0;
+			}
+			else
+				byte |= hex;
+			hex = 0;
+		}
+		printf("\n");
+		printf("call function rte_eth_dev_add_flex_filter: "
+			"index = %d, queue-id = %d, len = %d, priority = %d\n",
+			res->index_value, res->queue_id,
+			filter.len, filter.priority);
+		ret = rte_eth_dev_add_flex_filter(res->port_id, res->index_value,
+				  &filter, res->queue_id);
+		
+	}else if (!strcmp(res->filter, "remove_flex_filter"))
+		ret = rte_eth_dev_remove_flex_filter(res->port_id, res->index_value);
+	else if (!strcmp(res->filter, "get_flex_filter"))
+		get_flex_filter(res->port_id, res->index_value);
+
+	if(ret < 0)
+		printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_len =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 len, "len");
+cmdline_parse_token_string_t cmd_flex_filter_len_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+				 len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      queue_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 index, "index");
+cmdline_parse_token_num_t cmd_flex_filter_index_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+			      index_value, UINT16);
+cmdline_parse_token_string_t cmd_flex_filter_add_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "add_flex_filter");
+cmdline_parse_inst_t cmd_add_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "add a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_add_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_len,
+		(void *)&cmd_flex_filter_len_value,
+		(void *)&cmd_flex_filter_bytes,
+		(void *)&cmd_flex_filter_bytes_value,
+		(void *)&cmd_flex_filter_mask,
+		(void *)&cmd_flex_filter_mask_value,
+		(void *)&cmd_flex_filter_priority,
+		(void *)&cmd_flex_filter_priority_value,
+		(void *)&cmd_flex_filter_queue,
+		(void *)&cmd_flex_filter_queue_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_remove_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "remove_flex_filter");
+cmdline_parse_inst_t cmd_remove_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "remove a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_remove_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
+cmdline_parse_token_string_t cmd_flex_filter_get_filter =
+	TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+				 filter, "get_flex_filter");
+cmdline_parse_inst_t cmd_get_flex_filter = {
+	.f = cmd_flex_filter_parsed,
+	.data = NULL,
+	.help_str = "get a flex filter",
+	.tokens = {
+		(void *)&cmd_flex_filter_get_filter,
+		(void *)&cmd_flex_filter_port_id,
+		(void *)&cmd_flex_filter_index,
+		(void *)&cmd_flex_filter_index_value,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -5189,6 +6077,21 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
 	(cmdline_parse_inst_t *)&cmd_dump,
 	(cmdline_parse_inst_t *)&cmd_dump_one,
+	(cmdline_parse_inst_t *)&cmd_add_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_get_ethertype_filter,
+	(cmdline_parse_inst_t *)&cmd_add_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_get_syn_filter,
+	(cmdline_parse_inst_t *)&cmd_add_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_2tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_get_5tuple_filter,
+	(cmdline_parse_inst_t *)&cmd_add_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_remove_flex_filter,
+	(cmdline_parse_inst_t *)&cmd_get_flex_filter,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 134bf07..5d8b92f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1641,3 +1641,146 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 	       "diag=%d\n", port_id, diag);
 }
 
+void
+get_ethertype_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_ethertype_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_ethertype_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get ethertype filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: \n", index);
+		printf("    ethertype:  0x%04x  \n",
+			rte_le_to_cpu_32(filter.ethertype));
+		printf("    priority: %s, %d \n",
+			filter.priority_en ? "enable" : "disable",
+			filter.priority);
+		printf("    queue: %d \n", rx_queue);
+	}
+}
+
+void
+get_syn_filter(uint8_t port_id)
+{
+	struct rte_syn_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+	
+	if (ret < 0){
+		printf("get syn filter fails(%s)\n", strerror(-ret));
+		return;
+	}
+	printf("syn filter: %s, priority: %s, queue: %d\n", 
+		filter.enable? "on" : "off",
+		filter.hig_pri? "high" : "low",
+		rx_queue);
+}
+void
+get_2tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_2tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_2tuple_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: \n", index);
+		printf("    Destination Port:       0x%04x    mask: %d  \n",
+			rte_be_to_cpu_16(filter.dst_port),
+			filter.dst_port_mask ? 0 : 1);
+		printf("    protocol:  0x%02x    mask:%d",
+			filter.protocol, filter.protocol_mask ? 0 : 1);
+		printf("    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
+
+void
+get_5tuple_filter(uint8_t port_id, uint16_t index)
+{
+	struct rte_5tuple_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	const char *protocol_type[] = {"tcp", "udp", "sctp", "none"};
+	
+	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_type: %s            mask: %d  \n",
+			protocol_type[filter.l4type],
+			filter.l4type_mask ? 0 : 1);
+		printf("    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
+void
+get_flex_filter(uint8_t port_id, uint16_t index)
+
+{
+	struct rte_flex_filter filter;
+	int ret = 0;
+	uint8_t rx_queue;
+	int i, j;
+	
+	memset(&filter, 0, sizeof(filter));
+	ret = rte_eth_dev_get_flex_filter(port_id, index,
+				&filter, &rx_queue);
+	if (ret < 0){
+		if (ret == (-ENOENT))
+			printf("filter[%d] is not enabled\n", index);
+		else
+			printf("get flex filter fails(%s)\n", strerror(-ret));
+		return;
+	}else{
+		printf("filter[%d]: ", index);
+		printf("\n    length: %d", filter.len);
+		printf("\n    dword[]: 0x");
+		for (i = 0; i < 32; i++)
+			printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i]));
+		printf("\n    mask[]: 0b");
+		for (i = 0; i < 16; i++){
+			for(j = 0; j < 8; j++){
+				printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0');
+			}
+		}
+		printf("\n    priority: %d    queue: %d \n", filter.priority, rx_queue);
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 5b4ee6f..1b50898 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -521,6 +521,12 @@ void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
 void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, 
 		uint64_t vf_mask, uint8_t on);
 
+void get_syn_filter(uint8_t port_id);
+void get_ethertype_filter(uint8_t port_id, uint16_t index);
+void get_2tuple_filter(uint8_t port_id, uint16_t index);
+void get_5tuple_filter(uint8_t port_id, uint16_t index);
+void get_flex_filter(uint8_t port_id, uint16_t index);
+
 /*
  * Work-around of a compilation error with ICC on invocations of the
  * rte_be_to_cpu_16() function.
-- 
1.8.1.4
^ permalink raw reply	[flat|nested] 5+ messages in thread