This patch defines new functions dealing with ntuple filters which is
corresponding to 5tuple in HW.
It removes old functions which deal with 5tuple filters.
It also defines ixgbe_dev_filter_ctrl which is binding to filter_ctrl API,
and ntuple filter can be dealt with through this new entrance.

Signed-off-by: Jingjing Wu <jingjing.wu at intel.com>
---
 lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 489 +++++++++++++++++++++++++++---------
 lib/librte_pmd_ixgbe/ixgbe_ethdev.h |  62 ++++-
 2 files changed, 421 insertions(+), 130 deletions(-)

diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c 
b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
index 3fc3738..02a6be1 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c
@@ -237,13 +237,22 @@ static int ixgbe_remove_ethertype_filter(struct 
rte_eth_dev *dev,
                        uint16_t index);
 static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
                        struct rte_ethertype_filter *filter, uint16_t 
*rx_queue);
-static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_5tuple_filter *filter, uint16_t rx_queue);
-static int ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
-                       uint16_t index);
-static int ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_5tuple_filter *filter, uint16_t *rx_queue);
-
+static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev,
+                       struct ixgbe_5tuple_filter *filter);
+static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
+                       struct ixgbe_5tuple_filter *filter);
+static int ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ntuple_filter *filter,
+                       bool add);
+static int ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev,
+                               enum rte_filter_op filter_op,
+                               void *arg);
+static int ixgbe_get_ntuple_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ntuple_filter *filter);
+static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg);
 static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);

 /*
@@ -383,9 +392,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
        .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,
+       .filter_ctrl             = ixgbe_dev_filter_ctrl,
 };

 /*
@@ -732,6 +739,8 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct 
eth_driver *eth_drv,
                IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(eth_dev->data->dev_private);
        struct ixgbe_dcb_config *dcb_config =
                IXGBE_DEV_PRIVATE_TO_DCB_CFG(eth_dev->data->dev_private);
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
        uint32_t ctrl_ext;
        uint16_t csum;
        int diag, i;
@@ -913,6 +922,11 @@ eth_ixgbe_dev_init(__attribute__((unused)) struct 
eth_driver *eth_drv,
        /* enable support intr */
        ixgbe_enable_intr(eth_dev);

+       /* initialize 5tuple filter list */
+       TAILQ_INIT(&filter_info->fivetuple_list);
+       memset(filter_info->fivetuple_mask, 0,
+               sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
+
        return 0;
 }

@@ -1602,6 +1616,9 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_vf_info *vfinfo =
                *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       struct ixgbe_5tuple_filter *p_5tuple, *p_5tuple_next;
        int vf;

        PMD_INIT_FUNC_TRACE();
@@ -1631,6 +1648,18 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        /* Clear recorded link status */
        memset(&link, 0, sizeof(link));
        rte_ixgbe_dev_atomic_write_link_status(dev, &link);
+
+       /* Remove all ntuple filters of the device */
+       for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list);
+            p_5tuple != NULL; p_5tuple = p_5tuple_next) {
+               p_5tuple_next = TAILQ_NEXT(p_5tuple, entries);
+               TAILQ_REMOVE(&filter_info->fivetuple_list,
+                            p_5tuple, entries);
+               rte_free(p_5tuple);
+       }
+       memset(filter_info->fivetuple_mask, 0,
+               sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
+
 }

 /*
@@ -3933,62 +3962,69 @@ revert_protocol_type(enum ixgbe_5tuple_protocol 
protocol)
  *    - On failure, a negative value.
  */
 static int
-ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_5tuple_filter *filter, uint16_t rx_queue)
+ixgbe_add_5tuple_filter(struct rte_eth_dev *dev,
+                       struct ixgbe_5tuple_filter *filter)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t ftqf, sdpqf = 0;
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       int i, idx, shift;
+       uint32_t ftqf, sdpqf;
        uint32_t l34timir = 0;
        uint8_t mask = 0xff;

-       if (hw->mac.type != ixgbe_mac_82599EB)
+       /*
+        * look for an unused 5tuple filter index,
+        * and insert the filter to list.
+        */
+       for (i = 0; i < IXGBE_MAX_FTQF_FILTERS; i++) {
+               idx = i / UINT32_BIT;
+               shift = i % UINT32_BIT;
+               if (!(filter_info->fivetuple_mask[idx] & (1 << shift))) {
+                       filter_info->fivetuple_mask[idx] |= 1 << shift;
+                       filter->index = i;
+                       TAILQ_INSERT_TAIL(&filter_info->fivetuple_list,
+                                         filter,
+                                         entries);
+                       break;
+               }
+       }
+       if (i >= IXGBE_MAX_FTQF_FILTERS) {
+               PMD_DRV_LOG(ERR, "5tuple filters are full.");
                return -ENOSYS;
-
-       if (index >= IXGBE_MAX_FTQF_FILTERS ||
-               rx_queue >= IXGBE_MAX_RX_QUEUE_NUM ||
-               filter->priority > IXGBE_5TUPLE_MAX_PRI ||
-               filter->priority < IXGBE_5TUPLE_MIN_PRI)
-               return -EINVAL;  /* filter index is out of range. */
-
-       if (filter->tcp_flags) {
-               PMD_INIT_LOG(INFO, "82599EB not tcp flags in 5tuple");
-               return -EINVAL;
        }

-       ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
-       if (ftqf & IXGBE_FTQF_QUEUE_ENABLE)
-               return -EINVAL;  /* filter index is in use. */
+       sdpqf = (uint32_t)(filter->filter_info.dst_port <<
+                               IXGBE_SDPQF_DSTPORT_SHIFT);
+       sdpqf = sdpqf | (filter->filter_info.src_port & IXGBE_SDPQF_SRCPORT);

-       ftqf = 0;
-       sdpqf = (uint32_t)(filter->dst_port << IXGBE_SDPQF_DSTPORT_SHIFT);
-       sdpqf = sdpqf | (filter->src_port & IXGBE_SDPQF_SRCPORT);
-
-       ftqf |= (uint32_t)(convert_protocol_type(filter->protocol) &
+       ftqf = (uint32_t)(filter->filter_info.proto &
                IXGBE_FTQF_PROTOCOL_MASK);
-       ftqf |= (uint32_t)((filter->priority & IXGBE_FTQF_PRIORITY_MASK) <<
-               IXGBE_FTQF_PRIORITY_SHIFT);
-       if (filter->src_ip_mask == 0) /* 0 means compare. */
+       ftqf |= (uint32_t)((filter->filter_info.priority &
+               IXGBE_FTQF_PRIORITY_MASK) << IXGBE_FTQF_PRIORITY_SHIFT);
+       if (filter->filter_info.src_ip_mask == 0) /* 0 means compare. */
                mask &= IXGBE_FTQF_SOURCE_ADDR_MASK;
-       if (filter->dst_ip_mask == 0)
+       if (filter->filter_info.dst_ip_mask == 0)
                mask &= IXGBE_FTQF_DEST_ADDR_MASK;
-       if (filter->src_port_mask == 0)
+       if (filter->filter_info.src_port_mask == 0)
                mask &= IXGBE_FTQF_SOURCE_PORT_MASK;
-       if (filter->dst_port_mask == 0)
+       if (filter->filter_info.dst_port_mask == 0)
                mask &= IXGBE_FTQF_DEST_PORT_MASK;
-       if (filter->protocol_mask == 0)
+       if (filter->filter_info.proto_mask == 0)
                mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK;
        ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT;
        ftqf |= IXGBE_FTQF_POOL_MASK_EN;
        ftqf |= IXGBE_FTQF_QUEUE_ENABLE;

-       IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), filter->dst_ip);
-       IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), filter->src_ip);
-       IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), sdpqf);
-       IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), ftqf);
+       IXGBE_WRITE_REG(hw, IXGBE_DAQF(idx), filter->filter_info.dst_ip);
+       IXGBE_WRITE_REG(hw, IXGBE_SAQF(idx), filter->filter_info.src_ip);
+       IXGBE_WRITE_REG(hw, IXGBE_SDPQF(idx), sdpqf);
+       IXGBE_WRITE_REG(hw, IXGBE_FTQF(idx), 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);
+       l34timir |= (uint32_t)(filter->queue <<
+                               IXGBE_L34T_IMIR_QUEUE_SHIFT);
+       IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(i), l34timir);
        return 0;
 }

@@ -3997,92 +4033,27 @@ ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, 
uint16_t index,
  *
  * @param
  * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- *
- * @return
- *    - On success, zero.
- *    - On failure, a negative value.
+ * filter: the pointer of the filter will be removed.
  */
-static int
+static void
 ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
-                       uint16_t index)
+                       struct ixgbe_5tuple_filter *filter)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       uint16_t index = filter->index;

-       if (hw->mac.type != ixgbe_mac_82599EB)
-               return -ENOSYS;
-
-       if (index >= IXGBE_MAX_FTQF_FILTERS)
-               return -EINVAL;  /* filter index is out of range. */
+       filter_info->fivetuple_mask[index / UINT32_BIT] &=
+                                       ~(1 << (index % UINT32_BIT));
+       TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries);
+       rte_free(filter);

        IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0);
        IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0);
        IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0);
        IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0);
        IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0);
-       return 0;
-}
-
-/*
- * get a 5tuple filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates
- * filter: ponter to the filter that returns.
- * *rx_queue: pointer of the queue id the filter assigned to.
- *
- * @return
- *    - On success, zero.
- *    - On failure, a negative value.
- */
-static int
-ixgbe_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
-                       struct rte_5tuple_filter *filter, uint16_t *rx_queue)
-{
-       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint32_t sdpqf, ftqf, l34timir;
-       uint8_t mask;
-       enum ixgbe_5tuple_protocol proto;
-
-       if (hw->mac.type != ixgbe_mac_82599EB)
-               return -ENOSYS;
-
-       if (index >= IXGBE_MAX_FTQF_FILTERS)
-               return -EINVAL;  /* filter index is out of range. */
-
-       ftqf = IXGBE_READ_REG(hw, IXGBE_FTQF(index));
-       if (ftqf & IXGBE_FTQF_QUEUE_ENABLE) {
-               proto = (enum ixgbe_5tuple_protocol)(ftqf & 
IXGBE_FTQF_PROTOCOL_MASK);
-               filter->protocol = revert_protocol_type(proto);
-               filter->priority = (ftqf >> IXGBE_FTQF_PRIORITY_SHIFT) &
-                                       IXGBE_FTQF_PRIORITY_MASK;
-               mask = (uint8_t)((ftqf >> IXGBE_FTQF_5TUPLE_MASK_SHIFT) &
-                                       IXGBE_FTQF_5TUPLE_MASK_MASK);
-               filter->src_ip_mask =
-                       (mask & IXGBE_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
-               filter->dst_ip_mask =
-                       (mask & IXGBE_FTQF_DEST_ADDR_MASK) ? 1 : 0;
-               filter->src_port_mask =
-                       (mask & IXGBE_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
-               filter->dst_port_mask =
-                       (mask & IXGBE_FTQF_DEST_PORT_MASK) ? 1 : 0;
-               filter->protocol_mask =
-                       (mask & IXGBE_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
-
-               sdpqf = IXGBE_READ_REG(hw, IXGBE_SDPQF(index));
-               filter->dst_port = (sdpqf & IXGBE_SDPQF_DSTPORT) >>
-                                       IXGBE_SDPQF_DSTPORT_SHIFT;
-               filter->src_port = sdpqf & IXGBE_SDPQF_SRCPORT;
-               filter->dst_ip = IXGBE_READ_REG(hw, IXGBE_DAQF(index));
-               filter->src_ip = IXGBE_READ_REG(hw, IXGBE_SAQF(index));
-
-               l34timir = IXGBE_READ_REG(hw, IXGBE_L34T_IMIR(index));
-               *rx_queue = (l34timir & IXGBE_L34T_IMIR_QUEUE) >>
-                                       IXGBE_L34T_IMIR_QUEUE_SHIFT;
-               return 0;
-       }
-       return -ENOENT;
 }

 static int
@@ -4119,6 +4090,284 @@ ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t 
mtu)
        return 0;
 }

+#define MAC_TYPE_FILTER_SUP(type)    do {\
+       if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540)\
+               return -ENOTSUP;\
+} while (0)
+
+static inline struct ixgbe_5tuple_filter *
+ixgbe_5tuple_filter_lookup(struct ixgbe_5tuple_filter_list *filter_list,
+                       struct ixgbe_5tuple_filter_info *key)
+{
+       struct ixgbe_5tuple_filter *it;
+
+       TAILQ_FOREACH(it, filter_list, entries) {
+               if (memcmp(key, &it->filter_info,
+                       sizeof(struct ixgbe_5tuple_filter_info)) == 0) {
+                       return it;
+               }
+       }
+       return NULL;
+}
+
+/* translate elements in struct rte_eth_ntuple_filter to struct 
ixgbe_5tuple_filter_info*/
+static inline int
+ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter,
+                       struct ixgbe_5tuple_filter_info *filter_info)
+{
+       if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM ||
+               filter->priority > IXGBE_5TUPLE_MAX_PRI ||
+               filter->priority < IXGBE_5TUPLE_MIN_PRI)
+               return -EINVAL;
+
+       switch (filter->dst_ip_mask) {
+       case UINT32_MAX:
+               filter_info->dst_ip_mask = 0;
+               filter_info->dst_ip = filter->dst_ip;
+               break;
+       case 0:
+               filter_info->dst_ip_mask = 1;
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "invalid dst_ip mask.");
+               return -EINVAL;
+       }
+
+       switch (filter->src_ip_mask) {
+       case UINT32_MAX:
+               filter_info->src_ip_mask = 0;
+               filter_info->src_ip = filter->src_ip;
+               break;
+       case 0:
+               filter_info->src_ip_mask = 1;
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "invalid src_ip mask.");
+               return -EINVAL;
+       }
+
+       switch (filter->dst_port_mask) {
+       case UINT16_MAX:
+               filter_info->dst_port_mask = 0;
+               filter_info->dst_port = filter->dst_port;
+               break;
+       case 0:
+               filter_info->dst_port_mask = 1;
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "invalid dst_port mask.");
+               return -EINVAL;
+       }
+
+       switch (filter->src_port_mask) {
+       case UINT16_MAX:
+               filter_info->src_port_mask = 0;
+               filter_info->src_port = filter->src_port;
+               break;
+       case 0:
+               filter_info->src_port_mask = 1;
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "invalid src_port mask.");
+               return -EINVAL;
+       }
+
+       switch (filter->proto_mask) {
+       case UINT8_MAX:
+               filter_info->proto_mask = 0;
+               filter_info->proto =
+                       convert_protocol_type(filter->proto);
+               break;
+       case 0:
+               filter_info->proto_mask = 1;
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "invalid protocol mask.");
+               return -EINVAL;
+       }
+
+       filter_info->priority = (uint8_t)filter->priority;
+       return 0;
+}
+
+/*
+ * add or delete a ntuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * ntuple_filter: Pointer to struct rte_eth_ntuple_filter
+ * add: if true, add filter, if false, remove filter
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ntuple_filter *ntuple_filter,
+                       bool add)
+{
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       struct ixgbe_5tuple_filter_info filter_5tuple;
+       struct ixgbe_5tuple_filter *filter;
+       int ret;
+
+       if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) {
+               PMD_DRV_LOG(ERR, "only 5tuple is supported.");
+               return -EINVAL;
+       }
+
+       memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info));
+       ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple);
+       if (ret < 0)
+               return ret;
+
+       filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list,
+                                        &filter_5tuple);
+       if (filter != NULL && add) {
+               PMD_DRV_LOG(ERR, "filter exists.");
+               return -EEXIST;
+       }
+       if (filter == NULL && !add) {
+               PMD_DRV_LOG(ERR, "filter doesn't exist.");
+               return -ENOENT;
+       }
+
+       if (add) {
+               filter = rte_zmalloc("ixgbe_5tuple_filter",
+                               sizeof(struct ixgbe_5tuple_filter), 0);
+               if (filter == NULL)
+                       return -ENOMEM;
+               (void)rte_memcpy(&filter->filter_info,
+                                &filter_5tuple,
+                                sizeof(struct ixgbe_5tuple_filter_info));
+               filter->queue = ntuple_filter->queue;
+               ret = ixgbe_add_5tuple_filter(dev, filter);
+               if (ret < 0) {
+                       rte_free(filter);
+                       return ret;
+               }
+       } else
+               ixgbe_remove_5tuple_filter(dev, filter);
+
+       return 0;
+}
+
+/*
+ * get a ntuple filter
+ *
+ * @param
+ * dev: Pointer to struct rte_eth_dev.
+ * ntuple_filter: Pointer to struct rte_eth_ntuple_filter
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_get_ntuple_filter(struct rte_eth_dev *dev,
+                       struct rte_eth_ntuple_filter *ntuple_filter)
+{
+       struct ixgbe_filter_info *filter_info =
+               IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+       struct ixgbe_5tuple_filter_info filter_5tuple;
+       struct ixgbe_5tuple_filter *filter;
+       int ret;
+
+       if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) {
+               PMD_DRV_LOG(ERR, "only 5tuple is supported.");
+               return -EINVAL;
+       }
+
+       memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info));
+       ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple);
+       if (ret < 0)
+               return ret;
+
+       filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list,
+                                        &filter_5tuple);
+       if (filter == NULL) {
+               PMD_DRV_LOG(ERR, "filter doesn't exist.");
+               return -ENOENT;
+       }
+       ntuple_filter->queue = filter->queue;
+       return 0;
+}
+
+/*
+ * ixgbe_ntuple_filter_handle - Handle operations for ntuple filter.
+ * @dev: pointer to rte_eth_dev structure
+ * @filter_op:operation will be taken.
+ * @arg: a pointer to specific structure corresponding to the filter_op
+ *
+ * @return
+ *    - On success, zero.
+ *    - On failure, a negative value.
+ */
+static int
+ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev,
+                               enum rte_filter_op filter_op,
+                               void *arg)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+
+       MAC_TYPE_FILTER_SUP(hw->mac.type);
+
+       if (filter_op == RTE_ETH_FILTER_NOP)
+               return 0;
+
+       if (arg == NULL) {
+               PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.",
+                           filter_op);
+               return -EINVAL;
+       }
+
+       switch (filter_op) {
+       case RTE_ETH_FILTER_ADD:
+               ret = ixgbe_add_del_ntuple_filter(dev,
+                       (struct rte_eth_ntuple_filter *)arg,
+                       TRUE);
+               break;
+       case RTE_ETH_FILTER_DELETE:
+               ret = ixgbe_add_del_ntuple_filter(dev,
+                       (struct rte_eth_ntuple_filter *)arg,
+                       FALSE);
+               break;
+       case RTE_ETH_FILTER_GET:
+               ret = ixgbe_get_ntuple_filter(dev,
+                       (struct rte_eth_ntuple_filter *)arg);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int
+ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg)
+{
+       int ret = -EINVAL;
+
+       switch (filter_type) {
+       case RTE_ETH_FILTER_NTUPLE:
+               ret = ixgbe_ntuple_filter_handle(dev, filter_op, arg);
+               break;
+       default:
+               PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+                                                       filter_type);
+               break;
+       }
+
+       return ret;
+}
+
 static struct rte_driver rte_ixgbe_driver = {
        .type = PMD_PDEV,
        .init = rte_ixgbe_pmd_init,
diff --git a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h 
b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
index ca99170..69f0326 100644
--- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
+++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.h
@@ -162,6 +162,54 @@ struct ixgbe_vf_info {
 };

 /*
+ *  Possible l4type of 5tuple filters.
+ */
+enum ixgbe_5tuple_protocol {
+       IXGBE_FILTER_PROTOCOL_TCP = 0,
+       IXGBE_FILTER_PROTOCOL_UDP,
+       IXGBE_FILTER_PROTOCOL_SCTP,
+       IXGBE_FILTER_PROTOCOL_NONE,
+};
+
+TAILQ_HEAD(ixgbe_5tuple_filter_list, ixgbe_5tuple_filter);
+
+struct ixgbe_5tuple_filter_info {
+       uint32_t dst_ip;
+       uint32_t src_ip;
+       uint16_t dst_port;
+       uint16_t src_port;
+       enum ixgbe_5tuple_protocol proto;        /* l4 protocol. */
+       uint8_t priority;        /* seven levels (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. */
+               proto_mask:1;    /* if mask is 1b, do not compare protocol. */
+};
+
+/* 5tuple filter structure */
+struct ixgbe_5tuple_filter {
+       TAILQ_ENTRY(ixgbe_5tuple_filter) entries;
+       uint16_t index;       /* the index of 5tuple filter */
+       struct ixgbe_5tuple_filter_info filter_info;
+       uint16_t queue;       /* rx queue assigned to */
+};
+
+#define UINT32_BIT 32
+#define IXGBE_5TUPLE_ARRAY_SIZE \
+       (RTE_ALIGN(IXGBE_MAX_FTQF_FILTERS, UINT32_BIT) / (UINT32_BIT))
+
+/*
+ * Structure to store filters' info.
+ */
+struct ixgbe_filter_info {
+       /* Bit mask for every used 5tuple filter */
+       uint32_t fivetuple_mask[IXGBE_5TUPLE_ARRAY_SIZE];
+       struct ixgbe_5tuple_filter_list fivetuple_list;
+};
+
+/*
  * Structure to store private data for each driver instance (for each port).
  */
 struct ixgbe_adapter {
@@ -179,16 +227,7 @@ struct ixgbe_adapter {
 #ifdef RTE_NIC_BYPASS
        struct ixgbe_bypass_info    bps;
 #endif /* RTE_NIC_BYPASS */
-};
-
-/*
- *  Possible l4type of 5tuple filters.
- */
-enum ixgbe_5tuple_protocol {
-       IXGBE_FILTER_PROTOCOL_TCP = 0,
-       IXGBE_FILTER_PROTOCOL_UDP,
-       IXGBE_FILTER_PROTOCOL_SCTP,
-       IXGBE_FILTER_PROTOCOL_NONE,
+       struct ixgbe_filter_info    filter;
 };

 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -224,6 +263,9 @@ enum ixgbe_5tuple_protocol {
 #define IXGBE_DEV_PRIVATE_TO_UTA(adapter) \
        (&((struct ixgbe_adapter *)adapter)->uta_info)

+#define IXGBE_DEV_PRIVATE_TO_FILTER_INFO(adapter) \
+       (&((struct ixgbe_adapter *)adapter)->filter)
+
 /*
  * RX/TX function prototypes
  */
-- 
1.9.3

Reply via email to