get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2465/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2465,
    "url": "https://patches.dpdk.org/api/patches/2465/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1421912305-2022-4-git-send-email-jingjing.wu@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1421912305-2022-4-git-send-email-jingjing.wu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1421912305-2022-4-git-send-email-jingjing.wu@intel.com",
    "date": "2015-01-22T07:38:22",
    "name": "[dpdk-dev,v2,3/6] e1000: ntuple filter functions replace old ones for 2tuple and 5tuple filter",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "732925b0a4eb39007676729b9a8bb7b32b593746",
    "submitter": {
        "id": 47,
        "url": "https://patches.dpdk.org/api/people/47/?format=api",
        "name": "Jingjing Wu",
        "email": "jingjing.wu@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1421912305-2022-4-git-send-email-jingjing.wu@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2465/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2465/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id B17C35AB8;\n\tThu, 22 Jan 2015 08:38:50 +0100 (CET)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 6D8515A99\n\tfor <dev@dpdk.org>; Thu, 22 Jan 2015 08:38:44 +0100 (CET)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga103.jf.intel.com with ESMTP; 21 Jan 2015 23:34:41 -0800",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga003.jf.intel.com with ESMTP; 21 Jan 2015 23:31:58 -0800",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id t0M7cZbW012850;\n\tThu, 22 Jan 2015 15:38:35 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t0M7cYD2002077; Thu, 22 Jan 2015 15:38:36 +0800",
            "(from wujingji@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t0M7cXdl002073; \n\tThu, 22 Jan 2015 15:38:33 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.09,447,1418112000\"; d=\"scan'208\";a=\"515840940\"",
        "From": "Jingjing Wu <jingjing.wu@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Thu, 22 Jan 2015 15:38:22 +0800",
        "Message-Id": "<1421912305-2022-4-git-send-email-jingjing.wu@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1421912305-2022-1-git-send-email-jingjing.wu@intel.com>",
        "References": "<1421286361-11504-1-git-send-email-jingjing.wu@intel.com>\n\t<1421912305-2022-1-git-send-email-jingjing.wu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 3/6] e1000: ntuple filter functions replace\n\told ones for 2tuple and 5tuple filter",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch defines new functions dealing with ntuple filters which is\ncorresponding to 2tuple filter for 82580 and i350 in HW, and to 5tuple\nfilter for 82576 in HW.\nIt removes old functions which deal with 2tuple and 5tuple filters in igb driver.\nNtuple filter is dealt with through entrance eth_igb_filter_ctrl.\n\nSigned-off-by: Jingjing Wu <jingjing.wu@intel.com>\n---\n lib/librte_pmd_e1000/e1000_ethdev.h |  69 ++-\n lib/librte_pmd_e1000/igb_ethdev.c   | 869 ++++++++++++++++++++++++------------\n 2 files changed, 647 insertions(+), 291 deletions(-)",
    "diff": "diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h b/lib/librte_pmd_e1000/e1000_ethdev.h\nindex d155e77..571a70d 100644\n--- a/lib/librte_pmd_e1000/e1000_ethdev.h\n+++ b/lib/librte_pmd_e1000/e1000_ethdev.h\n@@ -67,14 +67,6 @@\n \n #define E1000_IMIR_DSTPORT             0x0000FFFF\n #define E1000_IMIR_PRIORITY            0xE0000000\n-#define E1000_IMIR_EXT_SIZE_BP         0x00001000\n-#define E1000_IMIR_EXT_CTRL_UGR        0x00002000\n-#define E1000_IMIR_EXT_CTRL_ACK        0x00004000\n-#define E1000_IMIR_EXT_CTRL_PSH        0x00008000\n-#define E1000_IMIR_EXT_CTRL_RST        0x00010000\n-#define E1000_IMIR_EXT_CTRL_SYN        0x00020000\n-#define E1000_IMIR_EXT_CTRL_FIN        0x00040000\n-#define E1000_IMIR_EXT_CTRL_BP         0x00080000\n #define E1000_MAX_TTQF_FILTERS         8\n #define E1000_2TUPLE_MAX_PRI           7\n \n@@ -96,11 +88,6 @@\n #define E1000_MAX_FTQF_FILTERS           8\n #define E1000_FTQF_PROTOCOL_MASK         0x000000FF\n #define E1000_FTQF_5TUPLE_MASK_SHIFT     28\n-#define E1000_FTQF_PROTOCOL_COMP_MASK    0x10000000\n-#define E1000_FTQF_SOURCE_ADDR_MASK      0x20000000\n-#define E1000_FTQF_DEST_ADDR_MASK        0x40000000\n-#define E1000_FTQF_SOURCE_PORT_MASK      0x80000000\n-#define E1000_FTQF_VF_MASK_EN            0x00008000\n #define E1000_FTQF_QUEUE_MASK            0x03ff0000\n #define E1000_FTQF_QUEUE_SHIFT           16\n #define E1000_FTQF_QUEUE_ENABLE          0x00000100\n@@ -131,6 +118,56 @@ struct e1000_vf_info {\n \tuint16_t tx_rate;\n };\n \n+TAILQ_HEAD(e1000_5tuple_filter_list, e1000_5tuple_filter);\n+TAILQ_HEAD(e1000_2tuple_filter_list, e1000_2tuple_filter);\n+\n+struct e1000_5tuple_filter_info {\n+\tuint32_t dst_ip;\n+\tuint32_t src_ip;\n+\tuint16_t dst_port;\n+\tuint16_t src_port;\n+\tuint8_t proto;           /* l4 protocol. */\n+\t/* the packet matched above 5tuple and contain any set bit will hit this filter. */\n+\tuint8_t tcp_flags;\n+\tuint8_t priority;        /* seven levels (001b-111b), 111b is highest,\n+\t\t\t\t      used when more than one filter matches. */\n+\tuint8_t dst_ip_mask:1,   /* if mask is 1b, do not compare dst ip. */\n+\t\tsrc_ip_mask:1,   /* if mask is 1b, do not compare src ip. */\n+\t\tdst_port_mask:1, /* if mask is 1b, do not compare dst port. */\n+\t\tsrc_port_mask:1, /* if mask is 1b, do not compare src port. */\n+\t\tproto_mask:1;    /* if mask is 1b, do not compare protocol. */\n+};\n+\n+struct e1000_2tuple_filter_info {\n+\tuint16_t dst_port;\n+\tuint8_t proto;           /* l4 protocol. */\n+\t/* the packet matched above 2tuple and contain any set bit will hit this filter. */\n+\tuint8_t tcp_flags;\n+\tuint8_t priority;        /* seven levels (001b-111b), 111b is highest,\n+\t\t\t\t      used when more than one filter matches. */\n+\tuint8_t dst_ip_mask:1,   /* if mask is 1b, do not compare dst ip. */\n+\t\tsrc_ip_mask:1,   /* if mask is 1b, do not compare src ip. */\n+\t\tdst_port_mask:1, /* if mask is 1b, do not compare dst port. */\n+\t\tsrc_port_mask:1, /* if mask is 1b, do not compare src port. */\n+\t\tproto_mask:1;    /* if mask is 1b, do not compare protocol. */\n+};\n+\n+/* 5tuple filter structure */\n+struct e1000_5tuple_filter {\n+\tTAILQ_ENTRY(e1000_5tuple_filter) entries;\n+\tuint16_t index;       /* the index of 5tuple filter */\n+\tstruct e1000_5tuple_filter_info filter_info;\n+\tuint16_t queue;       /* rx queue assigned to */\n+};\n+\n+/* 2tuple filter structure */\n+struct e1000_2tuple_filter {\n+\tTAILQ_ENTRY(e1000_2tuple_filter) entries;\n+\tuint16_t index;         /* the index of 2tuple filter */\n+\tstruct e1000_2tuple_filter_info filter_info;\n+\tuint16_t queue;       /* rx queue assigned to */\n+};\n+\n /*\n  * Structure to store filters' info.\n  */\n@@ -138,6 +175,12 @@ struct e1000_filter_info {\n \tuint8_t ethertype_mask; /* Bit mask for every used ethertype filter */\n \t/* store used ethertype filters*/\n \tuint16_t ethertype_filters[E1000_MAX_ETQF_FILTERS];\n+\t/* Bit mask for every used 5tuple filter */\n+\tuint8_t fivetuple_mask;\n+\tstruct e1000_5tuple_filter_list fivetuple_list;\n+\t/* Bit mask for every used 2tuple filter */\n+\tuint8_t twotuple_mask;\n+\tstruct e1000_2tuple_filter_list twotuple_list;\n };\n \n /*\ndiff --git a/lib/librte_pmd_e1000/igb_ethdev.c b/lib/librte_pmd_e1000/igb_ethdev.c\nindex 81b2ca7..ebef67f 100644\n--- a/lib/librte_pmd_e1000/igb_ethdev.c\n+++ b/lib/librte_pmd_e1000/igb_ethdev.c\n@@ -154,14 +154,10 @@ static int eth_igb_add_syn_filter(struct rte_eth_dev *dev,\n static int eth_igb_remove_syn_filter(struct rte_eth_dev *dev);\n static int eth_igb_get_syn_filter(struct rte_eth_dev *dev,\n \t\t\tstruct rte_syn_filter *filter, uint16_t *rx_queue);\n-static int eth_igb_add_2tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index,\n-\t\t\tstruct rte_2tuple_filter *filter, uint16_t rx_queue);\n-static int eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index);\n-static int eth_igb_get_2tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index,\n-\t\t\tstruct rte_2tuple_filter *filter, uint16_t *rx_queue);\n+static int igb_add_2tuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n+static int igb_remove_2tuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n static int eth_igb_add_flex_filter(struct rte_eth_dev *dev,\n \t\t\tuint16_t index,\n \t\t\tstruct rte_flex_filter *filter, uint16_t rx_queue);\n@@ -170,14 +166,18 @@ static int eth_igb_remove_flex_filter(struct rte_eth_dev *dev,\n static int eth_igb_get_flex_filter(struct rte_eth_dev *dev,\n \t\t\tuint16_t index,\n \t\t\tstruct rte_flex_filter *filter, uint16_t *rx_queue);\n-static int eth_igb_add_5tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index,\n-\t\t\tstruct rte_5tuple_filter *filter, uint16_t rx_queue);\n-static int eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index);\n-static int eth_igb_get_5tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index,\n-\t\t\tstruct rte_5tuple_filter *filter, uint16_t *rx_queue);\n+static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n+static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n+static int igb_add_del_ntuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *filter,\n+\t\t\tbool add);\n+static int igb_get_ntuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *filter);\n+static int igb_ntuple_filter_handle(struct rte_eth_dev *dev,\n+\t\t\t\tenum rte_filter_op filter_op,\n+\t\t\t\tvoid *arg);\n static int igb_add_del_ethertype_filter(struct rte_eth_dev *dev,\n \t\t\tstruct rte_eth_ethertype_filter *filter,\n \t\t\tbool add);\n@@ -268,15 +268,9 @@ static struct eth_dev_ops eth_igb_ops = {\n \t.add_syn_filter          = eth_igb_add_syn_filter,\n \t.remove_syn_filter       = eth_igb_remove_syn_filter,\n \t.get_syn_filter          = eth_igb_get_syn_filter,\n-\t.add_2tuple_filter       = eth_igb_add_2tuple_filter,\n-\t.remove_2tuple_filter    = eth_igb_remove_2tuple_filter,\n-\t.get_2tuple_filter       = eth_igb_get_2tuple_filter,\n \t.add_flex_filter         = eth_igb_add_flex_filter,\n \t.remove_flex_filter      = eth_igb_remove_flex_filter,\n \t.get_flex_filter         = eth_igb_get_flex_filter,\n-\t.add_5tuple_filter       = eth_igb_add_5tuple_filter,\n-\t.remove_5tuple_filter    = eth_igb_remove_5tuple_filter,\n-\t.get_5tuple_filter       = eth_igb_get_5tuple_filter,\n \t.filter_ctrl             = eth_igb_filter_ctrl,\n };\n \n@@ -470,6 +464,8 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,\n \t\tE1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);\n \tstruct e1000_vfta * shadow_vfta =\n \t\t\tE1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);\n \tuint32_t ctrl_ext;\n \n \tpci_dev = eth_dev->pci_dev;\n@@ -601,6 +597,12 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,\n \t/* enable support intr */\n \tigb_intr_enable(eth_dev);\n \n+\t/* initialize ntuple filter list */\n+\tTAILQ_INIT(&filter_info->twotuple_list);\n+\tfilter_info->twotuple_mask = 0;\n+\tTAILQ_INIT(&filter_info->fivetuple_list);\n+\tfilter_info->fivetuple_mask = 0;\n+\n \treturn 0;\n \n err_late:\n@@ -926,7 +928,11 @@ static void\n eth_igb_stop(struct rte_eth_dev *dev)\n {\n \tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n \tstruct rte_eth_link link;\n+\tstruct e1000_5tuple_filter *p_5tuple, *p_5tuple_next;\n+\tstruct e1000_2tuple_filter *p_2tuple, *p_2tuple_next;\n \n \tigb_intr_disable(hw);\n \tigb_pf_reset_hw(hw);\n@@ -949,6 +955,24 @@ eth_igb_stop(struct rte_eth_dev *dev)\n \t/* clear the recorded link status */\n \tmemset(&link, 0, sizeof(link));\n \trte_igb_dev_atomic_write_link_status(dev, &link);\n+\n+\t/* Remove all ntuple filters of the device */\n+\tfor (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list);\n+\t     p_5tuple != NULL; p_5tuple = p_5tuple_next) {\n+\t\tp_5tuple_next = TAILQ_NEXT(p_5tuple, entries);\n+\t\tTAILQ_REMOVE(&filter_info->fivetuple_list,\n+\t\t\t     p_5tuple, entries);\n+\t\trte_free(p_5tuple);\n+\t}\n+\tfilter_info->fivetuple_mask = 0;\n+\tfor (p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list);\n+\t     p_2tuple != NULL; p_2tuple = p_2tuple_next) {\n+\t\tp_2tuple_next = TAILQ_NEXT(p_2tuple, entries);\n+\t\tTAILQ_REMOVE(&filter_info->twotuple_list,\n+\t\t\t     p_2tuple, entries);\n+\t\trte_free(p_2tuple);\n+\t}\n+\tfilter_info->twotuple_mask = 0;\n }\n \n static void\n@@ -2492,165 +2516,209 @@ eth_igb_get_syn_filter(struct rte_eth_dev *dev,\n \t\treturn -ENOSYS; \\\n } while (0)\n \n-/*\n- * add a 2tuple filter\n- *\n- * @param\n- * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates.\n- * filter: ponter to the filter that will be added.\n- * rx_queue: the queue id the filter assigned to.\n- *\n- * @return\n- *    - On success, zero.\n- *    - On failure, a negative value.\n- */\n-static int\n-eth_igb_add_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,\n-\t\t\tstruct rte_2tuple_filter *filter, uint16_t rx_queue)\n+/* translate elements in struct rte_eth_ntuple_filter to struct e1000_2tuple_filter_info*/\n+static inline int\n+ntuple_filter_to_2tuple(struct rte_eth_ntuple_filter *filter,\n+\t\t\tstruct e1000_2tuple_filter_info *filter_info)\n {\n-\tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tuint32_t ttqf, imir = 0;\n-\tuint32_t imir_ext = 0;\n-\n-\tMAC_TYPE_FILTER_SUP_EXT(hw->mac.type);\n-\n-\tif (index >= E1000_MAX_TTQF_FILTERS ||\n-\t\trx_queue >= IGB_MAX_RX_QUEUE_NUM ||\n-\t\tfilter->priority > E1000_2TUPLE_MAX_PRI)\n+\tif (filter->queue >= IGB_MAX_RX_QUEUE_NUM)\n+\t\treturn -EINVAL;\n+\tif (filter->priority > E1000_2TUPLE_MAX_PRI)\n \t\treturn -EINVAL;  /* filter index is out of range. */\n-\tif  (filter->tcp_flags > TCP_FLAG_ALL)\n+\tif (filter->tcp_flags > TCP_FLAG_ALL)\n \t\treturn -EINVAL;  /* flags is invalid. */\n \n-\tttqf = E1000_READ_REG(hw, E1000_TTQF(index));\n-\tif (ttqf & E1000_TTQF_QUEUE_ENABLE)\n-\t\treturn -EINVAL;  /* filter index is in use. */\n-\n-\timir = (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);\n-\tif (filter->dst_port_mask == 1) /* 1b means not compare. */\n-\t\timir |= E1000_IMIR_PORT_BP;\n-\telse\n-\t\timir &= ~E1000_IMIR_PORT_BP;\n+\tswitch (filter->dst_port_mask) {\n+\tcase UINT16_MAX:\n+\t\tfilter_info->dst_port_mask = 0;\n+\t\tfilter_info->dst_port = filter->dst_port;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->dst_port_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid dst_port mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\timir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;\n+\tswitch (filter->proto_mask) {\n+\tcase UINT8_MAX:\n+\t\tfilter_info->proto_mask = 0;\n+\t\tfilter_info->proto = filter->proto;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->proto_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid protocol mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\tttqf = 0;\n-\tttqf |= E1000_TTQF_QUEUE_ENABLE;\n-\tttqf |= (uint32_t)(rx_queue << E1000_TTQF_QUEUE_SHIFT);\n-\tttqf |= (uint32_t)(filter->protocol & E1000_TTQF_PROTOCOL_MASK);\n-\tif (filter->protocol_mask == 1)\n-\t\tttqf |= E1000_TTQF_MASK_ENABLE;\n+\tfilter_info->priority = (uint8_t)filter->priority;\n+\tif (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG)\n+\t\tfilter_info->tcp_flags = filter->tcp_flags;\n \telse\n-\t\tttqf &= ~E1000_TTQF_MASK_ENABLE;\n+\t\tfilter_info->tcp_flags = 0;\n \n-\timir_ext |= E1000_IMIR_EXT_SIZE_BP;\n-\t/* tcp flags bits setting. */\n-\tif (filter->tcp_flags & TCP_FLAG_ALL) {\n-\t\tif (filter->tcp_flags & TCP_UGR_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_UGR;\n-\t\tif (filter->tcp_flags & TCP_ACK_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_ACK;\n-\t\tif (filter->tcp_flags & TCP_PSH_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_PSH;\n-\t\tif (filter->tcp_flags & TCP_RST_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_RST;\n-\t\tif (filter->tcp_flags & TCP_SYN_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_SYN;\n-\t\tif (filter->tcp_flags & TCP_FIN_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_FIN;\n-\t\timir_ext &= ~E1000_IMIR_EXT_CTRL_BP;\n-\t} else\n-\t\timir_ext |= E1000_IMIR_EXT_CTRL_BP;\n-\tE1000_WRITE_REG(hw, E1000_IMIR(index), imir);\n-\tE1000_WRITE_REG(hw, E1000_TTQF(index), ttqf);\n-\tE1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);\n \treturn 0;\n }\n \n+static inline struct e1000_2tuple_filter *\n+igb_2tuple_filter_lookup(struct e1000_2tuple_filter_list *filter_list,\n+\t\t\tstruct e1000_2tuple_filter_info *key)\n+{\n+\tstruct e1000_2tuple_filter *it;\n+\n+\tTAILQ_FOREACH(it, filter_list, entries) {\n+\t\tif (memcmp(key, &it->filter_info,\n+\t\t\tsizeof(struct e1000_2tuple_filter_info)) == 0) {\n+\t\t\treturn it;\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\n+\n /*\n- * remove a 2tuple filter\n+ * igb_add_2tuple_filter - add a 2tuple filter\n  *\n  * @param\n  * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates.\n+ * ntuple_filter: ponter to the filter that will be added.\n  *\n  * @return\n  *    - On success, zero.\n  *    - On failure, a negative value.\n  */\n static int\n-eth_igb_remove_2tuple_filter(struct rte_eth_dev *dev,\n-\t\t\tuint16_t index)\n+igb_add_2tuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter)\n {\n \tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n+\tstruct e1000_2tuple_filter *filter;\n+\tuint32_t ttqf = E1000_TTQF_DISABLE_MASK;\n+\tuint32_t imir, imir_ext = E1000_IMIREXT_SIZE_BP;\n+\tint i, ret;\n+\n+\tfilter = rte_zmalloc(\"e1000_2tuple_filter\",\n+\t\t\tsizeof(struct e1000_2tuple_filter), 0);\n+\tif (filter == NULL)\n+\t\treturn -ENOMEM;\n \n-\tMAC_TYPE_FILTER_SUP_EXT(hw->mac.type);\n+\tret = ntuple_filter_to_2tuple(ntuple_filter,\n+\t\t\t\t      &filter->filter_info);\n+\tif (ret < 0) {\n+\t\trte_free(filter);\n+\t\treturn ret;\n+\t}\n+\tif (igb_2tuple_filter_lookup(&filter_info->twotuple_list,\n+\t\t\t\t\t &filter->filter_info) != NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"filter exists.\");\n+\t\trte_free(filter);\n+\t\treturn -EEXIST;\n+\t}\n+\tfilter->queue = ntuple_filter->queue;\n \n-\tif (index >= E1000_MAX_TTQF_FILTERS)\n-\t\treturn -EINVAL;  /* filter index is out of range */\n+\t/*\n+\t * look for an unused 2tuple filter index,\n+\t * and insert the filter to list.\n+\t */\n+\tfor (i = 0; i < E1000_MAX_TTQF_FILTERS; i++) {\n+\t\tif (!(filter_info->twotuple_mask & (1 << i))) {\n+\t\t\tfilter_info->twotuple_mask |= 1 << i;\n+\t\t\tfilter->index = i;\n+\t\t\tTAILQ_INSERT_TAIL(&filter_info->twotuple_list,\n+\t\t\t\t\t  filter,\n+\t\t\t\t\t  entries);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (i >= E1000_MAX_TTQF_FILTERS) {\n+\t\tPMD_DRV_LOG(ERR, \"2tuple filters are full.\");\n+\t\trte_free(filter);\n+\t\treturn -ENOSYS;\n+\t}\n+\n+\timir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);\n+\tif (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */\n+\t\timir |= E1000_IMIR_PORT_BP;\n+\telse\n+\t\timir &= ~E1000_IMIR_PORT_BP;\n \n-\tE1000_WRITE_REG(hw, E1000_TTQF(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_IMIR(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);\n+\timir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;\n+\n+\tttqf |= E1000_TTQF_QUEUE_ENABLE;\n+\tttqf |= (uint32_t)(filter->queue << E1000_TTQF_QUEUE_SHIFT);\n+\tttqf |= (uint32_t)(filter->filter_info.proto & E1000_TTQF_PROTOCOL_MASK);\n+\tif (filter->filter_info.proto_mask == 0)\n+\t\tttqf &= ~E1000_TTQF_MASK_ENABLE;\n+\n+\t/* tcp flags bits setting. */\n+\tif (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {\n+\t\tif (filter->filter_info.tcp_flags & TCP_URG_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_URG;\n+\t\tif (filter->filter_info.tcp_flags & TCP_ACK_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_ACK;\n+\t\tif (filter->filter_info.tcp_flags & TCP_PSH_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_PSH;\n+\t\tif (filter->filter_info.tcp_flags & TCP_RST_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_RST;\n+\t\tif (filter->filter_info.tcp_flags & TCP_SYN_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_SYN;\n+\t\tif (filter->filter_info.tcp_flags & TCP_FIN_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_FIN;\n+\t} else\n+\t\timir_ext |= E1000_IMIREXT_CTRL_BP;\n+\tE1000_WRITE_REG(hw, E1000_IMIR(i), imir);\n+\tE1000_WRITE_REG(hw, E1000_TTQF(i), ttqf);\n+\tE1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);\n \treturn 0;\n }\n \n /*\n- * get a 2tuple filter\n+ * igb_remove_2tuple_filter - remove a 2tuple filter\n  *\n  * @param\n  * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates.\n- * filter: ponter to the filter that returns.\n- * *rx_queue: pointer of the queue id the filter assigned to.\n+ * ntuple_filter: ponter to the filter that will be removed.\n  *\n  * @return\n  *    - On success, zero.\n  *    - On failure, a negative value.\n  */\n static int\n-eth_igb_get_2tuple_filter(struct rte_eth_dev *dev, uint16_t index,\n-\t\t\tstruct rte_2tuple_filter *filter, uint16_t *rx_queue)\n+igb_remove_2tuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter)\n {\n \tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tuint32_t imir, ttqf, imir_ext;\n-\n-\tMAC_TYPE_FILTER_SUP_EXT(hw->mac.type);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n+\tstruct e1000_2tuple_filter_info filter_2tuple;\n+\tstruct e1000_2tuple_filter *filter;\n+\tint ret;\n \n-\tif (index >= E1000_MAX_TTQF_FILTERS)\n-\t\treturn -EINVAL;  /* filter index is out of range. */\n+\tmemset(&filter_2tuple, 0, sizeof(struct e1000_2tuple_filter_info));\n+\tret = ntuple_filter_to_2tuple(ntuple_filter,\n+\t\t\t\t      &filter_2tuple);\n+\tif (ret < 0)\n+\t\treturn ret;\n \n-\tttqf = E1000_READ_REG(hw, E1000_TTQF(index));\n-\tif (ttqf & E1000_TTQF_QUEUE_ENABLE) {\n-\t\timir = E1000_READ_REG(hw, E1000_IMIR(index));\n-\t\tfilter->protocol = ttqf & E1000_TTQF_PROTOCOL_MASK;\n-\t\tfilter->protocol_mask = (ttqf & E1000_TTQF_MASK_ENABLE) ? 1 : 0;\n-\t\t*rx_queue = (ttqf & E1000_TTQF_RX_QUEUE_MASK) >>\n-\t\t\t\tE1000_TTQF_QUEUE_SHIFT;\n-\t\tfilter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);\n-\t\tfilter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;\n-\t\tfilter->priority = (imir & E1000_IMIR_PRIORITY) >>\n-\t\t\tE1000_IMIR_PRIORITY_SHIFT;\n-\n-\t\timir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));\n-\t\tif (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_UGR)\n-\t\t\t\tfilter->tcp_flags |= TCP_UGR_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_ACK)\n-\t\t\t\tfilter->tcp_flags |= TCP_ACK_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_PSH)\n-\t\t\t\tfilter->tcp_flags |= TCP_PSH_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_RST)\n-\t\t\t\tfilter->tcp_flags |= TCP_RST_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_SYN)\n-\t\t\t\tfilter->tcp_flags |= TCP_SYN_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_FIN)\n-\t\t\t\tfilter->tcp_flags |= TCP_FIN_FLAG;\n-\t\t} else\n-\t\t\tfilter->tcp_flags = 0;\n-\t\treturn 0;\n+\tfilter = igb_2tuple_filter_lookup(&filter_info->twotuple_list,\n+\t\t\t\t\t &filter_2tuple);\n+\tif (filter == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"filter doesn't exist.\");\n+\t\treturn -ENOENT;\n \t}\n-\treturn -ENOENT;\n+\n+\tfilter_info->twotuple_mask &= ~(1 << filter->index);\n+\tTAILQ_REMOVE(&filter_info->twotuple_list, filter, entries);\n+\trte_free(filter);\n+\n+\tE1000_WRITE_REG(hw, E1000_TTQF(filter->index), E1000_TTQF_DISABLE_MASK);\n+\tE1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);\n+\tE1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);\n+\treturn 0;\n }\n \n /*\n@@ -2808,192 +2876,265 @@ eth_igb_get_flex_filter(struct rte_eth_dev *dev, uint16_t index,\n \treturn -ENOENT;\n }\n \n-/*\n- * add a 5tuple filter\n- *\n- * @param\n- * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates.\n- * filter: ponter to the filter that will be added.\n- * rx_queue: the queue id the filter assigned to.\n- *\n- * @return\n- *    - On success, zero.\n- *    - On failure, a negative value.\n- */\n-static int\n-eth_igb_add_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,\n-\t\t\tstruct rte_5tuple_filter *filter, uint16_t rx_queue)\n+/* translate elements in struct rte_eth_ntuple_filter to struct e1000_5tuple_filter_info*/\n+static inline int\n+ntuple_filter_to_5tuple_82576(struct rte_eth_ntuple_filter *filter,\n+\t\t\tstruct e1000_5tuple_filter_info *filter_info)\n {\n-\tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tuint32_t ftqf, spqf = 0;\n-\tuint32_t imir = 0;\n-\tuint32_t imir_ext = 0;\n+\tif (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576)\n+\t\treturn -EINVAL;\n+\tif (filter->priority > E1000_2TUPLE_MAX_PRI)\n+\t\treturn -EINVAL;  /* filter index is out of range. */\n+\tif (filter->tcp_flags > TCP_FLAG_ALL)\n+\t\treturn -EINVAL;  /* flags is invalid. */\n \n-\tif (hw->mac.type != e1000_82576)\n-\t\treturn -ENOSYS;\n+\tswitch (filter->dst_ip_mask) {\n+\tcase UINT32_MAX:\n+\t\tfilter_info->dst_ip_mask = 0;\n+\t\tfilter_info->dst_ip = filter->dst_ip;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->dst_ip_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid dst_ip mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\tif (index >= E1000_MAX_FTQF_FILTERS ||\n-\t\trx_queue >= IGB_MAX_RX_QUEUE_NUM_82576)\n-\t\treturn -EINVAL;  /* filter index is out of range. */\n+\tswitch (filter->src_ip_mask) {\n+\tcase UINT32_MAX:\n+\t\tfilter_info->src_ip_mask = 0;\n+\t\tfilter_info->src_ip = filter->src_ip;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->src_ip_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid src_ip mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\tftqf = E1000_READ_REG(hw, E1000_FTQF(index));\n-\tif (ftqf & E1000_FTQF_QUEUE_ENABLE)\n-\t\treturn -EINVAL;  /* filter index is in use. */\n-\n-\tftqf = 0;\n-\tftqf |= filter->protocol & E1000_FTQF_PROTOCOL_MASK;\n-\tif (filter->src_ip_mask == 1) /* 1b means not compare. */\n-\t\tftqf |= E1000_FTQF_SOURCE_ADDR_MASK;\n-\tif (filter->dst_ip_mask == 1)\n-\t\tftqf |= E1000_FTQF_DEST_ADDR_MASK;\n-\tif (filter->src_port_mask == 1)\n-\t\tftqf |= E1000_FTQF_SOURCE_PORT_MASK;\n-\tif (filter->protocol_mask == 1)\n-\t\tftqf |= E1000_FTQF_PROTOCOL_COMP_MASK;\n-\tftqf |= (rx_queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK;\n-\tftqf |= E1000_FTQF_VF_MASK_EN;\n-\tftqf |= E1000_FTQF_QUEUE_ENABLE;\n-\tE1000_WRITE_REG(hw, E1000_FTQF(index), ftqf);\n-\tE1000_WRITE_REG(hw, E1000_DAQF(index), filter->dst_ip);\n-\tE1000_WRITE_REG(hw, E1000_SAQF(index), filter->src_ip);\n+\tswitch (filter->dst_port_mask) {\n+\tcase UINT16_MAX:\n+\t\tfilter_info->dst_port_mask = 0;\n+\t\tfilter_info->dst_port = filter->dst_port;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->dst_port_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid dst_port mask.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tswitch (filter->src_port_mask) {\n+\tcase UINT16_MAX:\n+\t\tfilter_info->src_port_mask = 0;\n+\t\tfilter_info->src_port = filter->src_port;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->src_port_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid src_port mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\tspqf |= filter->src_port & E1000_SPQF_SRCPORT;\n-\tE1000_WRITE_REG(hw, E1000_SPQF(index), spqf);\n+\tswitch (filter->proto_mask) {\n+\tcase UINT8_MAX:\n+\t\tfilter_info->proto_mask = 0;\n+\t\tfilter_info->proto = filter->proto;\n+\t\tbreak;\n+\tcase 0:\n+\t\tfilter_info->proto_mask = 1;\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"invalid protocol mask.\");\n+\t\treturn -EINVAL;\n+\t}\n \n-\timir |= (uint32_t)(filter->dst_port & E1000_IMIR_DSTPORT);\n-\tif (filter->dst_port_mask == 1) /* 1b means not compare. */\n-\t\timir |= E1000_IMIR_PORT_BP;\n+\tfilter_info->priority = (uint8_t)filter->priority;\n+\tif (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG)\n+\t\tfilter_info->tcp_flags = filter->tcp_flags;\n \telse\n-\t\timir &= ~E1000_IMIR_PORT_BP;\n-\timir |= filter->priority << E1000_IMIR_PRIORITY_SHIFT;\n+\t\tfilter_info->tcp_flags = 0;\n \n-\timir_ext |= E1000_IMIR_EXT_SIZE_BP;\n-\t/* tcp flags bits setting. */\n-\tif (filter->tcp_flags & TCP_FLAG_ALL) {\n-\t\tif (filter->tcp_flags & TCP_UGR_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_UGR;\n-\t\tif (filter->tcp_flags & TCP_ACK_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_ACK;\n-\t\tif (filter->tcp_flags & TCP_PSH_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_PSH;\n-\t\tif (filter->tcp_flags & TCP_RST_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_RST;\n-\t\tif (filter->tcp_flags & TCP_SYN_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_SYN;\n-\t\tif (filter->tcp_flags & TCP_FIN_FLAG)\n-\t\t\timir_ext |= E1000_IMIR_EXT_CTRL_FIN;\n-\t} else\n-\t\timir_ext |= E1000_IMIR_EXT_CTRL_BP;\n-\tE1000_WRITE_REG(hw, E1000_IMIR(index), imir);\n-\tE1000_WRITE_REG(hw, E1000_IMIREXT(index), imir_ext);\n \treturn 0;\n }\n \n+static inline struct e1000_5tuple_filter *\n+igb_5tuple_filter_lookup_82576(struct e1000_5tuple_filter_list *filter_list,\n+\t\t\tstruct e1000_5tuple_filter_info *key)\n+{\n+\tstruct e1000_5tuple_filter *it;\n+\n+\tTAILQ_FOREACH(it, filter_list, entries) {\n+\t\tif (memcmp(key, &it->filter_info,\n+\t\t\tsizeof(struct e1000_5tuple_filter_info)) == 0) {\n+\t\t\treturn it;\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\n+\n /*\n- * remove a 5tuple filter\n+ * igb_add_5tuple_filter_82576 - add a 5tuple filter\n  *\n  * @param\n  * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates\n+ * ntuple_filter: ponter to the filter that will be added.\n  *\n  * @return\n  *    - On success, zero.\n  *    - On failure, a negative value.\n  */\n static int\n-eth_igb_remove_5tuple_filter(struct rte_eth_dev *dev,\n-\t\t\t\tuint16_t index)\n+igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter)\n {\n \tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n+\tstruct e1000_5tuple_filter *filter;\n+\tuint32_t ftqf = E1000_FTQF_VF_BP | E1000_FTQF_MASK;\n+\tuint32_t spqf, imir, imir_ext = E1000_IMIREXT_SIZE_BP;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tfilter = rte_zmalloc(\"e1000_5tuple_filter\",\n+\t\t\tsizeof(struct e1000_5tuple_filter), 0);\n+\tif (filter == NULL)\n+\t\treturn -ENOMEM;\n+\n+\tret = ntuple_filter_to_5tuple_82576(ntuple_filter,\n+\t\t\t\t\t    &filter->filter_info);\n+\tif (ret < 0) {\n+\t\trte_free(filter);\n+\t\treturn ret;\n+\t}\n \n-\tif (hw->mac.type != e1000_82576)\n+\tif (igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list,\n+\t\t\t\t\t &filter->filter_info) != NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"filter exists.\");\n+\t\trte_free(filter);\n+\t\treturn -EEXIST;\n+\t}\n+\tfilter->queue = ntuple_filter->queue;\n+\n+\t/*\n+\t * look for an unused 5tuple filter index,\n+\t * and insert the filter to list.\n+\t */\n+\tfor (i = 0; i < E1000_MAX_FTQF_FILTERS; i++) {\n+\t\tif (!(filter_info->fivetuple_mask & (1 << i))) {\n+\t\t\tfilter_info->fivetuple_mask |= 1 << i;\n+\t\t\tfilter->index = i;\n+\t\t\tTAILQ_INSERT_TAIL(&filter_info->fivetuple_list,\n+\t\t\t\t\t  filter,\n+\t\t\t\t\t  entries);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tif (i >= E1000_MAX_FTQF_FILTERS) {\n+\t\tPMD_DRV_LOG(ERR, \"5tuple filters are full.\");\n+\t\trte_free(filter);\n \t\treturn -ENOSYS;\n+\t}\n \n-\tif (index >= E1000_MAX_FTQF_FILTERS)\n-\t\treturn -EINVAL;  /* filter index is out of range. */\n+\tftqf |= filter->filter_info.proto & E1000_FTQF_PROTOCOL_MASK;\n+\tif (filter->filter_info.src_ip_mask == 0) /* 0b means compare. */\n+\t\tftqf &= ~E1000_FTQF_MASK_SOURCE_ADDR_BP;\n+\tif (filter->filter_info.dst_ip_mask == 0)\n+\t\tftqf &= ~E1000_FTQF_MASK_DEST_ADDR_BP;\n+\tif (filter->filter_info.src_port_mask == 0)\n+\t\tftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;\n+\tif (filter->filter_info.proto_mask == 0)\n+\t\tftqf &= ~E1000_FTQF_MASK_PROTO_BP;\n+\tftqf |= (filter->queue << E1000_FTQF_QUEUE_SHIFT) &\n+\t\tE1000_FTQF_QUEUE_MASK;\n+\tftqf |= E1000_FTQF_QUEUE_ENABLE;\n+\tE1000_WRITE_REG(hw, E1000_FTQF(i), ftqf);\n+\tE1000_WRITE_REG(hw, E1000_DAQF(i), filter->filter_info.dst_ip);\n+\tE1000_WRITE_REG(hw, E1000_SAQF(i), filter->filter_info.src_ip);\n+\n+\tspqf = filter->filter_info.src_port & E1000_SPQF_SRCPORT;\n+\tE1000_WRITE_REG(hw, E1000_SPQF(i), spqf);\n \n-\tE1000_WRITE_REG(hw, E1000_FTQF(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_DAQF(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_SAQF(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_SPQF(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_IMIR(index), 0);\n-\tE1000_WRITE_REG(hw, E1000_IMIREXT(index), 0);\n+\timir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT);\n+\tif (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */\n+\t\timir |= E1000_IMIR_PORT_BP;\n+\telse\n+\t\timir &= ~E1000_IMIR_PORT_BP;\n+\timir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT;\n+\n+\t/* tcp flags bits setting. */\n+\tif (filter->filter_info.tcp_flags & TCP_FLAG_ALL) {\n+\t\tif (filter->filter_info.tcp_flags & TCP_URG_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_URG;\n+\t\tif (filter->filter_info.tcp_flags & TCP_ACK_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_ACK;\n+\t\tif (filter->filter_info.tcp_flags & TCP_PSH_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_PSH;\n+\t\tif (filter->filter_info.tcp_flags & TCP_RST_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_RST;\n+\t\tif (filter->filter_info.tcp_flags & TCP_SYN_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_SYN;\n+\t\tif (filter->filter_info.tcp_flags & TCP_FIN_FLAG)\n+\t\t\timir_ext |= E1000_IMIREXT_CTRL_FIN;\n+\t} else\n+\t\timir_ext |= E1000_IMIREXT_CTRL_BP;\n+\tE1000_WRITE_REG(hw, E1000_IMIR(i), imir);\n+\tE1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext);\n \treturn 0;\n }\n \n /*\n- * get a 5tuple filter\n+ * igb_remove_5tuple_filter_82576 - remove a 5tuple filter\n  *\n  * @param\n  * dev: Pointer to struct rte_eth_dev.\n- * index: the index the filter allocates\n- * filter: ponter to the filter that returns\n- * *rx_queue: pointer of the queue id the filter assigned to\n+ * ntuple_filter: ponter to the filter that will be removed.\n  *\n  * @return\n  *    - On success, zero.\n  *    - On failure, a negative value.\n  */\n static int\n-eth_igb_get_5tuple_filter(struct rte_eth_dev *dev, uint16_t index,\n-\t\t\tstruct rte_5tuple_filter *filter, uint16_t *rx_queue)\n+igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,\n+\t\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter)\n {\n \tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tuint32_t spqf, ftqf, imir, imir_ext;\n-\n-\tif (hw->mac.type != e1000_82576)\n-\t\treturn -ENOSYS;\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n+\tstruct e1000_5tuple_filter_info filter_5tuple;\n+\tstruct e1000_5tuple_filter *filter;\n+\tint ret;\n \n-\tif (index >= E1000_MAX_FTQF_FILTERS)\n-\t\treturn -EINVAL;  /* filter index is out of range. */\n+\tmemset(&filter_5tuple, 0, sizeof(struct e1000_5tuple_filter_info));\n+\tret = ntuple_filter_to_5tuple_82576(ntuple_filter,\n+\t\t\t\t\t    &filter_5tuple);\n+\tif (ret < 0)\n+\t\treturn ret;\n \n-\tftqf = E1000_READ_REG(hw, E1000_FTQF(index));\n-\tif (ftqf & E1000_FTQF_QUEUE_ENABLE) {\n-\t\tfilter->src_ip_mask =\n-\t\t\t(ftqf & E1000_FTQF_SOURCE_ADDR_MASK) ? 1 : 0;\n-\t\tfilter->dst_ip_mask =\n-\t\t\t(ftqf & E1000_FTQF_DEST_ADDR_MASK) ? 1 : 0;\n-\t\tfilter->src_port_mask =\n-\t\t\t(ftqf & E1000_FTQF_SOURCE_PORT_MASK) ? 1 : 0;\n-\t\tfilter->protocol_mask =\n-\t\t\t(ftqf & E1000_FTQF_PROTOCOL_COMP_MASK) ? 1 : 0;\n-\t\tfilter->protocol =\n-\t\t\t(uint8_t)ftqf & E1000_FTQF_PROTOCOL_MASK;\n-\t\t*rx_queue = (uint16_t)((ftqf & E1000_FTQF_QUEUE_MASK) >>\n-\t\t\t\tE1000_FTQF_QUEUE_SHIFT);\n-\n-\t\tspqf = E1000_READ_REG(hw, E1000_SPQF(index));\n-\t\tfilter->src_port = spqf & E1000_SPQF_SRCPORT;\n-\n-\t\tfilter->dst_ip = E1000_READ_REG(hw, E1000_DAQF(index));\n-\t\tfilter->src_ip = E1000_READ_REG(hw, E1000_SAQF(index));\n-\n-\t\timir = E1000_READ_REG(hw, E1000_IMIR(index));\n-\t\tfilter->dst_port_mask = (imir & E1000_IMIR_PORT_BP) ? 1 : 0;\n-\t\tfilter->dst_port = (uint16_t)(imir & E1000_IMIR_DSTPORT);\n-\t\tfilter->priority = (imir & E1000_IMIR_PRIORITY) >>\n-\t\t\tE1000_IMIR_PRIORITY_SHIFT;\n-\n-\t\timir_ext = E1000_READ_REG(hw, E1000_IMIREXT(index));\n-\t\tif (!(imir_ext & E1000_IMIR_EXT_CTRL_BP)) {\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_UGR)\n-\t\t\t\tfilter->tcp_flags |= TCP_UGR_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_ACK)\n-\t\t\t\tfilter->tcp_flags |= TCP_ACK_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_PSH)\n-\t\t\t\tfilter->tcp_flags |= TCP_PSH_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_RST)\n-\t\t\t\tfilter->tcp_flags |= TCP_RST_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_SYN)\n-\t\t\t\tfilter->tcp_flags |= TCP_SYN_FLAG;\n-\t\t\tif (imir_ext & E1000_IMIR_EXT_CTRL_FIN)\n-\t\t\t\tfilter->tcp_flags |= TCP_FIN_FLAG;\n-\t\t} else\n-\t\t\tfilter->tcp_flags = 0;\n-\t\treturn 0;\n+\tfilter = igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list,\n+\t\t\t\t\t &filter_5tuple);\n+\tif (filter == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"filter doesn't exist.\");\n+\t\treturn -ENOENT;\n \t}\n-\treturn -ENOENT;\n+\n+\tfilter_info->fivetuple_mask &= ~(1 << filter->index);\n+\tTAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries);\n+\trte_free(filter);\n+\n+\tE1000_WRITE_REG(hw, E1000_FTQF(filter->index),\n+\t\t\tE1000_FTQF_VF_BP | E1000_FTQF_MASK);\n+\tE1000_WRITE_REG(hw, E1000_DAQF(filter->index), 0);\n+\tE1000_WRITE_REG(hw, E1000_SAQF(filter->index), 0);\n+\tE1000_WRITE_REG(hw, E1000_SPQF(filter->index), 0);\n+\tE1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0);\n+\tE1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0);\n+\treturn 0;\n }\n \n static int\n@@ -3046,6 +3187,175 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)\n \treturn 0;\n }\n \n+/*\n+ * igb_add_del_ntuple_filter - add or delete a ntuple filter\n+ *\n+ * @param\n+ * dev: Pointer to struct rte_eth_dev.\n+ * ntuple_filter: Pointer to struct rte_eth_ntuple_filter\n+ * add: if true, add filter, if false, remove filter\n+ *\n+ * @return\n+ *    - On success, zero.\n+ *    - On failure, a negative value.\n+ */\n+static int\n+igb_add_del_ntuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter,\n+\t\t\tbool add)\n+{\n+\tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint ret;\n+\n+\tswitch (ntuple_filter->flags) {\n+\tcase RTE_5TUPLE_FLAGS:\n+\tcase (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):\n+\t\tif (hw->mac.type != e1000_82576)\n+\t\t\treturn -ENOTSUP;\n+\t\tif (add)\n+\t\t\tret = igb_add_5tuple_filter_82576(dev,\n+\t\t\t\t\t\t\t  ntuple_filter);\n+\t\telse\n+\t\t\tret = igb_remove_5tuple_filter_82576(dev,\n+\t\t\t\t\t\t\t     ntuple_filter);\n+\t\tbreak;\n+\tcase RTE_2TUPLE_FLAGS:\n+\tcase (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):\n+\t\tif (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350)\n+\t\t\treturn -ENOTSUP;\n+\t\tif (add)\n+\t\t\tret = igb_add_2tuple_filter(dev, ntuple_filter);\n+\t\telse\n+\t\t\tret = igb_remove_2tuple_filter(dev, ntuple_filter);\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/*\n+ * igb_get_ntuple_filter - get a ntuple filter\n+ *\n+ * @param\n+ * dev: Pointer to struct rte_eth_dev.\n+ * ntuple_filter: Pointer to struct rte_eth_ntuple_filter\n+ *\n+ * @return\n+ *    - On success, zero.\n+ *    - On failure, a negative value.\n+ */\n+static int\n+igb_get_ntuple_filter(struct rte_eth_dev *dev,\n+\t\t\tstruct rte_eth_ntuple_filter *ntuple_filter)\n+{\n+\tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct e1000_filter_info *filter_info =\n+\t\tE1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);\n+\tstruct e1000_5tuple_filter_info filter_5tuple;\n+\tstruct e1000_2tuple_filter_info filter_2tuple;\n+\tstruct e1000_5tuple_filter *p_5tuple_filter;\n+\tstruct e1000_2tuple_filter *p_2tuple_filter;\n+\tint ret;\n+\n+\tswitch (ntuple_filter->flags) {\n+\tcase RTE_5TUPLE_FLAGS:\n+\tcase (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):\n+\t\tif (hw->mac.type != e1000_82576)\n+\t\t\treturn -ENOTSUP;\n+\t\tmemset(&filter_5tuple,\n+\t\t\t0,\n+\t\t\tsizeof(struct e1000_5tuple_filter_info));\n+\t\tret = ntuple_filter_to_5tuple_82576(ntuple_filter,\n+\t\t\t\t\t\t    &filter_5tuple);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t\tp_5tuple_filter = igb_5tuple_filter_lookup_82576(\n+\t\t\t\t\t&filter_info->fivetuple_list,\n+\t\t\t\t\t&filter_5tuple);\n+\t\tif (p_5tuple_filter == NULL) {\n+\t\t\tPMD_DRV_LOG(ERR, \"filter doesn't exist.\");\n+\t\t\treturn -ENOENT;\n+\t\t}\n+\t\tntuple_filter->queue = p_5tuple_filter->queue;\n+\t\tbreak;\n+\tcase RTE_2TUPLE_FLAGS:\n+\tcase (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG):\n+\t\tif (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350)\n+\t\t\treturn -ENOTSUP;\n+\t\tmemset(&filter_2tuple,\n+\t\t\t0,\n+\t\t\tsizeof(struct e1000_2tuple_filter_info));\n+\t\tret = ntuple_filter_to_2tuple(ntuple_filter, &filter_2tuple);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t\tp_2tuple_filter = igb_2tuple_filter_lookup(\n+\t\t\t\t\t&filter_info->twotuple_list,\n+\t\t\t\t\t&filter_2tuple);\n+\t\tif (p_2tuple_filter == NULL) {\n+\t\t\tPMD_DRV_LOG(ERR, \"filter doesn't exist.\");\n+\t\t\treturn -ENOENT;\n+\t\t}\n+\t\tntuple_filter->queue = p_2tuple_filter->queue;\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * igb_ntuple_filter_handle - Handle operations for ntuple filter.\n+ * @dev: pointer to rte_eth_dev structure\n+ * @filter_op:operation will be taken.\n+ * @arg: a pointer to specific structure corresponding to the filter_op\n+ */\n+static int\n+igb_ntuple_filter_handle(struct rte_eth_dev *dev,\n+\t\t\t\tenum rte_filter_op filter_op,\n+\t\t\t\tvoid *arg)\n+{\n+\tstruct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint ret;\n+\n+\tMAC_TYPE_FILTER_SUP(hw->mac.type);\n+\n+\tif (filter_op == RTE_ETH_FILTER_NOP)\n+\t\treturn 0;\n+\n+\tif (arg == NULL) {\n+\t\tPMD_DRV_LOG(ERR, \"arg shouldn't be NULL for operation %u.\",\n+\t\t\t    filter_op);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tswitch (filter_op) {\n+\tcase RTE_ETH_FILTER_ADD:\n+\t\tret = igb_add_del_ntuple_filter(dev,\n+\t\t\t(struct rte_eth_ntuple_filter *)arg,\n+\t\t\tTRUE);\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_DELETE:\n+\t\tret = igb_add_del_ntuple_filter(dev,\n+\t\t\t(struct rte_eth_ntuple_filter *)arg,\n+\t\t\tFALSE);\n+\t\tbreak;\n+\tcase RTE_ETH_FILTER_GET:\n+\t\tret = igb_get_ntuple_filter(dev,\n+\t\t\t(struct rte_eth_ntuple_filter *)arg);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"unsupported operation %u.\", filter_op);\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\treturn ret;\n+}\n+\n static inline int\n igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info,\n \t\t\tuint16_t ethertype)\n@@ -3235,6 +3545,9 @@ eth_igb_filter_ctrl(struct rte_eth_dev *dev,\n \tint ret = -EINVAL;\n \n \tswitch (filter_type) {\n+\tcase RTE_ETH_FILTER_NTUPLE:\n+\t\tret = igb_ntuple_filter_handle(dev, filter_op, arg);\n+\t\tbreak;\n \tcase RTE_ETH_FILTER_ETHERTYPE:\n \t\tret = igb_ethertype_filter_handle(dev, filter_op, arg);\n \t\tbreak;\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "3/6"
    ]
}