@@ -67,14 +67,6 @@
#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
@@ -96,11 +88,6 @@
#define E1000_MAX_FTQF_FILTERS 8
#define E1000_FTQF_PROTOCOL_MASK 0x000000FF
#define E1000_FTQF_5TUPLE_MASK_SHIFT 28
-#define E1000_FTQF_PROTOCOL_COMP_MASK 0x10000000
-#define E1000_FTQF_SOURCE_ADDR_MASK 0x20000000
-#define E1000_FTQF_DEST_ADDR_MASK 0x40000000
-#define E1000_FTQF_SOURCE_PORT_MASK 0x80000000
-#define E1000_FTQF_VF_MASK_EN 0x00008000
#define E1000_FTQF_QUEUE_MASK 0x03ff0000
#define E1000_FTQF_QUEUE_SHIFT 16
#define E1000_FTQF_QUEUE_ENABLE 0x00000100
@@ -131,6 +118,68 @@ struct e1000_vf_info {
uint16_t tx_rate;
};
+TAILQ_HEAD(e1000_5tuple_filter_list, e1000_5tuple_filter);
+TAILQ_HEAD(e1000_2tuple_filter_list, e1000_2tuple_filter);
+
+struct e1000_5tuple_filter_info {
+ uint32_t dst_ip;
+ uint32_t src_ip;
+ uint16_t dst_port;
+ uint16_t src_port;
+ uint8_t proto; /* l4 protocol. */
+ /* the packet matched above 5tuple and contain any set bit will hit this filter. */
+ uint8_t tcp_flags;
+ 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. */
+};
+
+struct e1000_2tuple_filter_info {
+ uint16_t dst_port;
+ uint8_t proto; /* l4 protocol. */
+ /* the packet matched above 2tuple and contain any set bit will hit this filter. */
+ uint8_t tcp_flags;
+ 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 e1000_5tuple_filter {
+ TAILQ_ENTRY(e1000_5tuple_filter) entries;
+ uint16_t index; /* the index of 5tuple filter */
+ struct e1000_5tuple_filter_info filter_info;
+ uint16_t queue; /* rx queue assigned to */
+};
+
+/* 2tuple filter structure */
+struct e1000_2tuple_filter {
+ TAILQ_ENTRY(e1000_2tuple_filter) entries;
+ uint16_t index; /* the index of 2tuple filter */
+ struct e1000_2tuple_filter_info filter_info;
+ uint16_t queue; /* rx queue assigned to */
+};
+
+/*
+ * Structure to store filters' info.
+ */
+struct e1000_filter_info {
+ /* Bit mask for every used 5tuple filter */
+ uint8_t fivetuple_mask;
+ struct e1000_5tuple_filter_list fivetuple_list;
+ /* Bit mask for every used 2tuple filter */
+ uint8_t twotuple_mask;
+ struct e1000_2tuple_filter_list twotuple_list;
+};
+
/*
* Structure to store private data for each driver instance (for each port).
*/
@@ -140,6 +189,7 @@ struct e1000_adapter {
struct e1000_interrupt intr;
struct e1000_vfta shadow_vfta;
struct e1000_vf_info *vfdata;
+ struct e1000_filter_info filter;
};
#define E1000_DEV_PRIVATE_TO_HW(adapter) \
@@ -157,6 +207,9 @@ struct e1000_adapter {
#define E1000_DEV_PRIVATE_TO_P_VFDATA(adapter) \
(&((struct e1000_adapter *)adapter)->vfdata)
+#define E1000_DEV_PRIVATE_TO_FILTER_INFO(adapter) \
+ (&((struct e1000_adapter *)adapter)->filter)
+
/*
* RX/TX IGB function prototypes
*/
@@ -162,14 +162,10 @@ static int eth_igb_remove_ethertype_filter(struct rte_eth_dev *dev,
static int eth_igb_get_ethertype_filter(struct rte_eth_dev *dev,
uint16_t index,
struct rte_ethertype_filter *filter, uint16_t *rx_queue);
-static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,
- uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t rx_queue);
-static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
- uint16_t index);
-static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev,
- uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t *rx_queue);
+static int igb_add_2tuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter);
+static int igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter);
static int eth_igb_add_flex_filter(struct rte_eth_dev *dev,
uint16_t index,
struct rte_flex_filter *filter, uint16_t rx_queue);
@@ -178,14 +174,22 @@ static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,
static int eth_igb_get_flex_filter(struct rte_eth_dev *dev,
uint16_t index,
struct rte_flex_filter *filter, uint16_t *rx_queue);
-static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev,
- uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t rx_queue);
-static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
- uint16_t index);
-static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,
- uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t *rx_queue);
+static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter);
+static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter);
+static int igb_add_del_ntuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *filter,
+ bool add);
+static int igb_get_ntuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *filter);
+static int igb_ntuple_filter_handle(struct rte_eth_dev *dev,
+ enum rte_filter_op filter_op,
+ void *arg);
+static int eth_igb_filter_ctrl(struct rte_eth_dev *dev,
+ enum rte_filter_type filter_type,
+ enum rte_filter_op filter_op,
+ void *arg);
/*
* Define VF Stats MACRO for Non "cleared on read" register
@@ -267,15 +271,10 @@ static struct eth_dev_ops eth_igb_ops = {
.add_ethertype_filter = eth_igb_add_ethertype_filter,
.remove_ethertype_filter = eth_igb_remove_ethertype_filter,
.get_ethertype_filter = eth_igb_get_ethertype_filter,
- .add_2tuple_filter = eth_igb_add_2tuple_filter,
- .remove_2tuple_filter = eth_igb_remove_2tuple_filter,
- .get_2tuple_filter = eth_igb_get_2tuple_filter,
.add_flex_filter = eth_igb_add_flex_filter,
.remove_flex_filter = eth_igb_remove_flex_filter,
.get_flex_filter = eth_igb_get_flex_filter,
- .add_5tuple_filter = eth_igb_add_5tuple_filter,
- .remove_5tuple_filter = eth_igb_remove_5tuple_filter,
- .get_5tuple_filter = eth_igb_get_5tuple_filter,
+ .filter_ctrl = eth_igb_filter_ctrl,
};
/*
@@ -468,6 +467,8 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
struct e1000_vfta * shadow_vfta =
E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
uint32_t ctrl_ext;
pci_dev = eth_dev->pci_dev;
@@ -599,6 +600,12 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
/* enable support intr */
igb_intr_enable(eth_dev);
+ /* initialize ntuple filter list */
+ TAILQ_INIT(&filter_info->twotuple_list);
+ filter_info->twotuple_mask = 0;
+ TAILQ_INIT(&filter_info->fivetuple_list);
+ filter_info->fivetuple_mask = 0;
+
return 0;
err_late:
@@ -924,7 +931,11 @@ static void
eth_igb_stop(struct rte_eth_dev *dev)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
struct rte_eth_link link;
+ struct e1000_5tuple_filter *p_5tuple, *p_5tuple_next;
+ struct e1000_2tuple_filter *p_2tuple, *p_2tuple_next;
igb_intr_disable(hw);
igb_pf_reset_hw(hw);
@@ -947,6 +958,24 @@ eth_igb_stop(struct rte_eth_dev *dev)
/* clear the recorded link status */
memset(&link, 0, sizeof(link));
rte_igb_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);
+ }
+ filter_info->fivetuple_mask = 0;
+ for (p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list);
+ p_2tuple != NULL; p_2tuple = p_2tuple_next) {
+ p_2tuple_next = TAILQ_NEXT(p_2tuple, entries);
+ TAILQ_REMOVE(&filter_info->twotuple_list,
+ p_2tuple, entries);
+ rte_free(p_2tuple);
+ }
+ filter_info->twotuple_mask = 0;
}
static void
@@ -2388,7 +2417,7 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
#define MAC_TYPE_FILTER_SUP(type) do {\
if ((type) != e1000_82580 && (type) != e1000_i350 &&\
(type) != e1000_82576)\
- return -ENOSYS;\
+ return -ENOTSUP;\
} while (0)
/*
@@ -2595,165 +2624,209 @@ eth_igb_get_ethertype_filter(struct rte_eth_dev *dev, uint16_t index,
return -ENOSYS; \
} while (0)
-/*
- * add a 2tuple filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- * filter: ponter to the filter that will be added.
- * rx_queue: the queue id the filter assigned to.
- *
- * @return
- * - On success, zero.
- * - On failure, a negative value.
- */
-static int
-eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t rx_queue)
+/* translate elements in struct rte_eth_ntuple_filter to struct e1000_2tuple_filter_info*/
+static inline int
+ntuple_filter_to_2tuple(struct rte_eth_ntuple_filter *filter,
+ struct e1000_2tuple_filter_info *filter_info)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t ttqf, imir = 0;
- uint32_t imir_ext = 0;
-
- MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
-
- if (index >= E1000_MAX_TTQF_FILTERS ||
- rx_queue >= IGB_MAX_RX_QUEUE_NUM ||
- filter->priority > E1000_2TUPLE_MAX_PRI)
+ if (filter->queue >= IGB_MAX_RX_QUEUE_NUM)
+ return -EINVAL;
+ if (filter->priority > E1000_2TUPLE_MAX_PRI)
return -EINVAL; /* filter index is out of range. */
- if (filter->tcp_flags > TCP_FLAG_ALL)
+ 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;
+ 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;
+ }
- imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+ switch (filter->proto_mask) {
+ case UINT8_MAX:
+ filter_info->proto_mask = 0;
+ filter_info->proto = filter->proto;
+ break;
+ case 0:
+ filter_info->proto_mask = 1;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "invalid protocol mask.");
+ return -EINVAL;
+ }
- 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;
+ filter_info->priority = (uint8_t)filter->priority;
+ if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG)
+ filter_info->tcp_flags = filter->tcp_flags;
else
- ttqf &= ~E1000_TTQF_MASK_ENABLE;
+ filter_info->tcp_flags = 0;
- 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;
}
+static inline struct e1000_2tuple_filter *
+igb_2tuple_filter_lookup(struct e1000_2tuple_filter_list *filter_list,
+ struct e1000_2tuple_filter_info *key)
+{
+ struct e1000_2tuple_filter *it;
+
+ TAILQ_FOREACH(it, filter_list, entries) {
+ if (memcmp(key, &it->filter_info,
+ sizeof(struct e1000_2tuple_filter_info)) == 0) {
+ return it;
+ }
+ }
+ return NULL;
+}
+
/*
- * remove a 2tuple filter
+ * igb_add_2tuple_filter - add a 2tuple filter
*
* @param
* dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
+ * ntuple_filter: ponter to the filter that will be added.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
static int
-eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,
- uint16_t index)
+igb_add_2tuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+ struct e1000_2tuple_filter *filter;
+ uint32_t ttqf = E1000_TTQF_DISABLE_MASK;
+ uint32_t imir, imir_ext = E1000_IMIREXT_SIZE_BP;
+ int i, ret;
+
+ filter = rte_zmalloc("e1000_2tuple_filter",
+ sizeof(struct e1000_2tuple_filter), 0);
+ if (filter == NULL)
+ return -ENOMEM;
- MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+ ret = ntuple_filter_to_2tuple(ntuple_filter,
+ &filter->filter_info);
+ if (ret < 0) {
+ rte_free(filter);
+ return ret;
+ }
+ if (igb_2tuple_filter_lookup(&filter_info->twotuple_list,
+ &filter->filter_info) != NULL) {
+ PMD_DRV_LOG(ERR, "filter exists.");
+ rte_free(filter);
+ return -EEXIST;
+ }
+ filter->queue = ntuple_filter->queue;
+
+ /*
+ * look for an unused 2tuple filter index,
+ * and insert the filter to list.
+ */
+ for (i = 0; i < E1000_MAX_TTQF_FILTERS; i++) {
+ if (!(filter_info->twotuple_mask & (1 << i))) {
+ filter_info->twotuple_mask |= 1 << i;
+ filter->index = i;
+ TAILQ_INSERT_TAIL(&filter_info->twotuple_list,
+ filter,
+ entries);
+ break;
+ }
+ }
+ if (i >= E1000_MAX_TTQF_FILTERS) {
+ PMD_DRV_LOG(ERR, "2tuple filters are full.");
+ rte_free(filter);
+ return -ENOSYS;
+ }
- if (index >= E1000_MAX_TTQF_FILTERS)
- return -EINVAL; /* filter index is out of range */
+ imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
+ if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
+ imir |= E1000_IMIR_PORT_BP;
+ else
+ imir &= ~E1000_IMIR_PORT_BP;
+
+ imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
+
+ ttqf |= E1000_TTQF_QUEUE_ENABLE;
+ ttqf |= (uint32_t)(filter->queue << E1000_TTQF_QUEUE_SHIFT);
+ ttqf |= (uint32_t)(filter->filter_info.proto & E1000_TTQF_PROTOCOL_MASK);
+ if (filter->filter_info.proto_mask == 0)
+ ttqf &= ~E1000_TTQF_MASK_ENABLE;
- E1000_WRITE_REG(hw, E1000_TTQF(index), 0);
- E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
- E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+ /* tcp flags bits setting. */
+ if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
+ if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_URG;
+ if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_ACK;
+ if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_PSH;
+ if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_RST;
+ if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_SYN;
+ if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_FIN;
+ } else
+ imir_ext |= E1000_IMIREXT_CTRL_BP;
+ E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
+ E1000_WRITE_REG(hw, E1000_TTQF(i), ttqf);
+ E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
return 0;
}
/*
- * get a 2tuple filter
+ * igb_remove_2tuple_filter - remove 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.
+ * ntuple_filter: ponter to the filter that will be removed.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
static int
-eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,
- struct rte_2tuple_filter *filter, uint16_t *rx_queue)
+igb_remove_2tuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t imir, ttqf, imir_ext;
-
- MAC_TYPE_FILTER_SUP_EXT(hw->mac.type);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+ struct e1000_2tuple_filter_info filter_2tuple;
+ struct e1000_2tuple_filter *filter;
+ int ret;
- if (index >= E1000_MAX_TTQF_FILTERS)
- return -EINVAL; /* filter index is out of range. */
+ memset(&filter_2tuple, 0, sizeof(struct e1000_2tuple_filter_info));
+ ret = ntuple_filter_to_2tuple(ntuple_filter,
+ &filter_2tuple);
+ if (ret < 0)
+ return ret;
- ttqf = E1000_READ_REG(hw, E1000_TTQF(index));
- if (ttqf & E1000_TTQF_QUEUE_ENABLE) {
- imir = E1000_READ_REG(hw, E1000_IMIR(index));
- filter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;
- filter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;
- *rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >>
- E1000_TTQF_QUEUE_SHIFT;
- filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
- filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
- filter->priority = (imir & E1000_IMIR_PRIORITY) >>
- E1000_IMIR_PRIORITY_SHIFT;
-
- imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
- if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
- if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
- filter->tcp_flags |= TCP_UGR_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
- filter->tcp_flags |= TCP_ACK_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
- filter->tcp_flags |= TCP_PSH_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
- filter->tcp_flags |= TCP_RST_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
- filter->tcp_flags |= TCP_SYN_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
- filter->tcp_flags |= TCP_FIN_FLAG;
- } else
- filter->tcp_flags = 0;
- return 0;
+ filter = igb_2tuple_filter_lookup(&filter_info->twotuple_list,
+ &filter_2tuple);
+ if (filter == NULL) {
+ PMD_DRV_LOG(ERR, "filter doesn't exist.");
+ return -ENOENT;
}
- return -ENOENT;
+
+ filter_info->twotuple_mask &= ~(1 << filter->index);
+ TAILQ_REMOVE(&filter_info->twotuple_list, filter, entries);
+ rte_free(filter);
+
+ E1000_WRITE_REG(hw, E1000_TTQF(filter->index), E1000_TTQF_DISABLE_MASK);
+ E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
+ E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
+ return 0;
}
/*
@@ -2911,192 +2984,265 @@ eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,
return -ENOENT;
}
-/*
- * add a 5tuple filter
- *
- * @param
- * dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates.
- * filter: ponter to the filter that will be added.
- * rx_queue: the queue id the filter assigned to.
- *
- * @return
- * - On success, zero.
- * - On failure, a negative value.
- */
-static int
-eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t rx_queue)
+/* translate elements in struct rte_eth_ntuple_filter to struct e1000_5tuple_filter_info*/
+static inline int
+ntuple_filter_to_5tuple_82576(struct rte_eth_ntuple_filter *filter,
+ struct e1000_5tuple_filter_info *filter_info)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t ftqf, spqf = 0;
- uint32_t imir = 0;
- uint32_t imir_ext = 0;
+ if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576)
+ return -EINVAL;
+ if (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. */
- if (hw->mac.type != e1000_82576)
- return -ENOSYS;
+ 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;
+ }
- if (index >= E1000_MAX_FTQF_FILTERS ||
- rx_queue >= IGB_MAX_RX_QUEUE_NUM_82576)
- return -EINVAL; /* filter index is out of range. */
+ 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;
+ }
- ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
- if (ftqf & E1000_FTQF_QUEUE_ENABLE)
- return -EINVAL; /* filter index is in use. */
+ 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;
+ }
- ftqf = 0;
- ftqf |= filter->protocol & E1000_FTQF_PROTOCOL_MASK;
- if (filter->src_ip_mask == 1) /* 1b means not compare. */
- ftqf |= E1000_FTQF_SOURCE_ADDR_MASK;
- if (filter->dst_ip_mask == 1)
- ftqf |= E1000_FTQF_DEST_ADDR_MASK;
- if (filter->src_port_mask == 1)
- ftqf |= E1000_FTQF_SOURCE_PORT_MASK;
- if (filter->protocol_mask == 1)
- ftqf |= E1000_FTQF_PROTOCOL_COMP_MASK;
- ftqf |= (rx_queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK;
- ftqf |= E1000_FTQF_VF_MASK_EN;
- ftqf |= E1000_FTQF_QUEUE_ENABLE;
- E1000_WRITE_REG(hw, E1000_FTQF(index), ftqf);
- E1000_WRITE_REG(hw, E1000_DAQF(index), filter->dst_ip);
- E1000_WRITE_REG(hw, E1000_SAQF(index), filter->src_ip);
+ 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;
+ }
- spqf |= filter->src_port & E1000_SPQF_SRCPORT;
- E1000_WRITE_REG(hw, E1000_SPQF(index), spqf);
+ switch (filter->proto_mask) {
+ case UINT8_MAX:
+ filter_info->proto_mask = 0;
+ filter_info->proto = filter->proto;
+ break;
+ case 0:
+ filter_info->proto_mask = 1;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "invalid protocol mask.");
+ return -EINVAL;
+ }
- imir |= (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);
- if (filter->dst_port_mask == 1) /* 1b means not compare. */
- imir |= E1000_IMIR_PORT_BP;
+ filter_info->priority = (uint8_t)filter->priority;
+ if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG)
+ filter_info->tcp_flags = filter->tcp_flags;
else
- imir &= ~E1000_IMIR_PORT_BP;
- imir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;
+ filter_info->tcp_flags = 0;
- imir_ext |= E1000_IMIR_EXT_SIZE_BP;
- /* tcp flags bits setting. */
- if (filter->tcp_flags & TCP_FLAG_ALL) {
- if (filter->tcp_flags & TCP_UGR_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_UGR;
- if (filter->tcp_flags & TCP_ACK_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_ACK;
- if (filter->tcp_flags & TCP_PSH_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_PSH;
- if (filter->tcp_flags & TCP_RST_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_RST;
- if (filter->tcp_flags & TCP_SYN_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_SYN;
- if (filter->tcp_flags & TCP_FIN_FLAG)
- imir_ext |= E1000_IMIR_EXT_CTRL_FIN;
- } else
- imir_ext |= E1000_IMIR_EXT_CTRL_BP;
- E1000_WRITE_REG(hw, E1000_IMIR(index), imir);
- E1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);
return 0;
}
+static inline struct e1000_5tuple_filter *
+igb_5tuple_filter_lookup_82576(struct e1000_5tuple_filter_list *filter_list,
+ struct e1000_5tuple_filter_info *key)
+{
+ struct e1000_5tuple_filter *it;
+
+ TAILQ_FOREACH(it, filter_list, entries) {
+ if (memcmp(key, &it->filter_info,
+ sizeof(struct e1000_5tuple_filter_info)) == 0) {
+ return it;
+ }
+ }
+ return NULL;
+}
+
/*
- * remove a 5tuple filter
+ * igb_add_5tuple_filter_82576 - add a 5tuple filter
*
* @param
* dev: Pointer to struct rte_eth_dev.
- * index: the index the filter allocates
+ * ntuple_filter: ponter to the filter that will be added.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
static int
-eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,
- uint16_t index)
+igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+ struct e1000_5tuple_filter *filter;
+ uint32_t ftqf = E1000_FTQF_VF_BP | E1000_FTQF_MASK;
+ uint32_t spqf, imir, imir_ext = E1000_IMIREXT_SIZE_BP;
+ uint8_t i;
+ int ret;
- if (hw->mac.type != e1000_82576)
+ filter = rte_zmalloc("e1000_5tuple_filter",
+ sizeof(struct e1000_5tuple_filter), 0);
+ if (filter == NULL)
+ return -ENOMEM;
+
+ ret = ntuple_filter_to_5tuple_82576(ntuple_filter,
+ &filter->filter_info);
+ if (ret < 0) {
+ rte_free(filter);
+ return ret;
+ }
+
+ if (igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list,
+ &filter->filter_info) != NULL) {
+ PMD_DRV_LOG(ERR, "filter exists.");
+ rte_free(filter);
+ return -EEXIST;
+ }
+ filter->queue = ntuple_filter->queue;
+
+ /*
+ * look for an unused 5tuple filter index,
+ * and insert the filter to list.
+ */
+ for (i = 0; i < E1000_MAX_FTQF_FILTERS; i++) {
+ if (!(filter_info->fivetuple_mask & (1 << i))) {
+ filter_info->fivetuple_mask |= 1 << i;
+ filter->index = i;
+ TAILQ_INSERT_TAIL(&filter_info->fivetuple_list,
+ filter,
+ entries);
+ break;
+ }
+ }
+ if (i >= E1000_MAX_FTQF_FILTERS) {
+ PMD_DRV_LOG(ERR, "5tuple filters are full.");
+ rte_free(filter);
return -ENOSYS;
+ }
- if (index >= E1000_MAX_FTQF_FILTERS)
- return -EINVAL; /* filter index is out of range. */
+ ftqf |= filter->filter_info.proto & E1000_FTQF_PROTOCOL_MASK;
+ if (filter->filter_info.src_ip_mask == 0) /* 0b means compare. */
+ ftqf &= ~E1000_FTQF_MASK_SOURCE_ADDR_BP;
+ if (filter->filter_info.dst_ip_mask == 0)
+ ftqf &= ~E1000_FTQF_MASK_DEST_ADDR_BP;
+ if (filter->filter_info.src_port_mask == 0)
+ ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
+ if (filter->filter_info.proto_mask == 0)
+ ftqf &= ~E1000_FTQF_MASK_PROTO_BP;
+ ftqf |= (filter->queue << E1000_FTQF_QUEUE_SHIFT) &
+ E1000_FTQF_QUEUE_MASK;
+ ftqf |= E1000_FTQF_QUEUE_ENABLE;
+ E1000_WRITE_REG(hw, E1000_FTQF(i), ftqf);
+ E1000_WRITE_REG(hw, E1000_DAQF(i), filter->filter_info.dst_ip);
+ E1000_WRITE_REG(hw, E1000_SAQF(i), filter->filter_info.src_ip);
+
+ spqf = filter->filter_info.src_port & E1000_SPQF_SRCPORT;
+ E1000_WRITE_REG(hw, E1000_SPQF(i), spqf);
- E1000_WRITE_REG(hw, E1000_FTQF(index), 0);
- E1000_WRITE_REG(hw, E1000_DAQF(index), 0);
- E1000_WRITE_REG(hw, E1000_SAQF(index), 0);
- E1000_WRITE_REG(hw, E1000_SPQF(index), 0);
- E1000_WRITE_REG(hw, E1000_IMIR(index), 0);
- E1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);
+ imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);
+ if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */
+ imir |= E1000_IMIR_PORT_BP;
+ else
+ imir &= ~E1000_IMIR_PORT_BP;
+ imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;
+
+ /* tcp flags bits setting. */
+ if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {
+ if (filter->filter_info.tcp_flags & TCP_URG_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_URG;
+ if (filter->filter_info.tcp_flags & TCP_ACK_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_ACK;
+ if (filter->filter_info.tcp_flags & TCP_PSH_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_PSH;
+ if (filter->filter_info.tcp_flags & TCP_RST_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_RST;
+ if (filter->filter_info.tcp_flags & TCP_SYN_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_SYN;
+ if (filter->filter_info.tcp_flags & TCP_FIN_FLAG)
+ imir_ext |= E1000_IMIREXT_CTRL_FIN;
+ } else
+ imir_ext |= E1000_IMIREXT_CTRL_BP;
+ E1000_WRITE_REG(hw, E1000_IMIR(i), imir);
+ E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);
return 0;
}
/*
- * get a 5tuple filter
+ * igb_remove_5tuple_filter_82576 - remove 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
+ * ntuple_filter: ponter to the filter that will be removed.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
static int
-eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,
- struct rte_5tuple_filter *filter, uint16_t *rx_queue)
+igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t spqf, ftqf, imir, imir_ext;
-
- if (hw->mac.type != e1000_82576)
- return -ENOSYS;
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+ struct e1000_5tuple_filter_info filter_5tuple;
+ struct e1000_5tuple_filter *filter;
+ int ret;
- if (index >= E1000_MAX_FTQF_FILTERS)
- return -EINVAL; /* filter index is out of range. */
+ memset(&filter_5tuple, 0, sizeof(struct e1000_5tuple_filter_info));
+ ret = ntuple_filter_to_5tuple_82576(ntuple_filter,
+ &filter_5tuple);
+ if (ret < 0)
+ return ret;
- ftqf = E1000_READ_REG(hw, E1000_FTQF(index));
- if (ftqf & E1000_FTQF_QUEUE_ENABLE) {
- filter->src_ip_mask =
- (ftqf & E1000_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;
- filter->dst_ip_mask =
- (ftqf & E1000_FTQF_DEST_ADDR_MASK) ? 1 : 0;
- filter->src_port_mask =
- (ftqf & E1000_FTQF_SOURCE_PORT_MASK) ? 1 : 0;
- filter->protocol_mask =
- (ftqf & E1000_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;
- filter->protocol =
- (uint8_t)ftqf & E1000_FTQF_PROTOCOL_MASK;
- *rx_queue = (uint16_t)((ftqf & E1000_FTQF_QUEUE_MASK) >>
- E1000_FTQF_QUEUE_SHIFT);
-
- spqf = E1000_READ_REG(hw, E1000_SPQF(index));
- filter->src_port = spqf & E1000_SPQF_SRCPORT;
-
- filter->dst_ip = E1000_READ_REG(hw, E1000_DAQF(index));
- filter->src_ip = E1000_READ_REG(hw, E1000_SAQF(index));
-
- imir = E1000_READ_REG(hw, E1000_IMIR(index));
- filter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;
- filter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);
- filter->priority = (imir & E1000_IMIR_PRIORITY) >>
- E1000_IMIR_PRIORITY_SHIFT;
-
- imir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));
- if (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {
- if (imir_ext & E1000_IMIR_EXT_CTRL_UGR)
- filter->tcp_flags |= TCP_UGR_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_ACK)
- filter->tcp_flags |= TCP_ACK_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_PSH)
- filter->tcp_flags |= TCP_PSH_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_RST)
- filter->tcp_flags |= TCP_RST_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_SYN)
- filter->tcp_flags |= TCP_SYN_FLAG;
- if (imir_ext & E1000_IMIR_EXT_CTRL_FIN)
- filter->tcp_flags |= TCP_FIN_FLAG;
- } else
- filter->tcp_flags = 0;
- return 0;
+ filter = igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list,
+ &filter_5tuple);
+ if (filter == NULL) {
+ PMD_DRV_LOG(ERR, "filter doesn't exist.");
+ return -ENOENT;
}
- return -ENOENT;
+
+ filter_info->fivetuple_mask &= ~(1 << filter->index);
+ TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries);
+ rte_free(filter);
+
+ E1000_WRITE_REG(hw, E1000_FTQF(filter->index),
+ E1000_FTQF_VF_BP | E1000_FTQF_MASK);
+ E1000_WRITE_REG(hw, E1000_DAQF(filter->index), 0);
+ E1000_WRITE_REG(hw, E1000_SAQF(filter->index), 0);
+ E1000_WRITE_REG(hw, E1000_SPQF(filter->index), 0);
+ E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);
+ E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);
+ return 0;
}
static int
@@ -3149,6 +3295,196 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
return 0;
}
+/*
+ * igb_add_del_ntuple_filter - 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
+igb_add_del_ntuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter,
+ bool add)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ int ret;
+
+ switch (ntuple_filter->flags) {
+ case RTE_5TUPLE_FLAGS:
+ case (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):
+ if (hw->mac.type != e1000_82576)
+ return -ENOTSUP;
+ if (add)
+ ret = igb_add_5tuple_filter_82576(dev,
+ ntuple_filter);
+ else
+ ret = igb_remove_5tuple_filter_82576(dev,
+ ntuple_filter);
+ break;
+ case RTE_2TUPLE_FLAGS:
+ case (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):
+ if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350)
+ return -ENOTSUP;
+ if (add)
+ ret = igb_add_2tuple_filter(dev, ntuple_filter);
+ else
+ ret = igb_remove_2tuple_filter(dev, ntuple_filter);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * igb_get_ntuple_filter - 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
+igb_get_ntuple_filter(struct rte_eth_dev *dev,
+ struct rte_eth_ntuple_filter *ntuple_filter)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_filter_info *filter_info =
+ E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
+ struct e1000_5tuple_filter_info filter_5tuple;
+ struct e1000_2tuple_filter_info filter_2tuple;
+ struct e1000_5tuple_filter *p_5tuple_filter;
+ struct e1000_2tuple_filter *p_2tuple_filter;
+ int ret;
+
+ switch (ntuple_filter->flags) {
+ case RTE_5TUPLE_FLAGS:
+ case (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):
+ if (hw->mac.type != e1000_82576)
+ return -ENOTSUP;
+ memset(&filter_5tuple,
+ 0,
+ sizeof(struct e1000_5tuple_filter_info));
+ ret = ntuple_filter_to_5tuple_82576(ntuple_filter,
+ &filter_5tuple);
+ if (ret < 0)
+ return ret;
+ p_5tuple_filter = igb_5tuple_filter_lookup_82576(
+ &filter_info->fivetuple_list,
+ &filter_5tuple);
+ if (p_5tuple_filter == NULL) {
+ PMD_DRV_LOG(ERR, "filter doesn't exist.");
+ return -ENOENT;
+ }
+ ntuple_filter->queue = p_5tuple_filter->queue;
+ break;
+ case RTE_2TUPLE_FLAGS:
+ case (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):
+ if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350)
+ return -ENOTSUP;
+ memset(&filter_2tuple,
+ 0,
+ sizeof(struct e1000_2tuple_filter_info));
+ ret = ntuple_filter_to_2tuple(ntuple_filter, &filter_2tuple);
+ if (ret < 0)
+ return ret;
+ p_2tuple_filter = igb_2tuple_filter_lookup(
+ &filter_info->twotuple_list,
+ &filter_2tuple);
+ if (p_2tuple_filter == NULL) {
+ PMD_DRV_LOG(ERR, "filter doesn't exist.");
+ return -ENOENT;
+ }
+ ntuple_filter->queue = p_2tuple_filter->queue;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * igb_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
+ */
+static int
+igb_ntuple_filter_handle(struct rte_eth_dev *dev,
+ enum rte_filter_op filter_op,
+ void *arg)
+{
+ struct e1000_hw *hw = E1000_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 = igb_add_del_ntuple_filter(dev,
+ (struct rte_eth_ntuple_filter *)arg,
+ TRUE);
+ break;
+ case RTE_ETH_FILTER_DELETE:
+ ret = igb_add_del_ntuple_filter(dev,
+ (struct rte_eth_ntuple_filter *)arg,
+ FALSE);
+ break;
+ case RTE_ETH_FILTER_GET:
+ ret = igb_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
+eth_igb_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 = igb_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 pmd_igb_drv = {
.type = PMD_PDEV,
.init = rte_igb_pmd_init,