get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 450,
    "url": "https://patches.dpdk.org/api/patches/450/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1411442991-15386-4-git-send-email-jijiang.liu@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": "<1411442991-15386-4-git-send-email-jijiang.liu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1411442991-15386-4-git-send-email-jijiang.liu@intel.com",
    "date": "2014-09-23T03:29:49",
    "name": "[dpdk-dev,3/5] i40e:optimize MACVLAN filter implementation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "14a9682f98bcd434ebb15ddfbc86a69665506763",
    "submitter": {
        "id": 52,
        "url": "https://patches.dpdk.org/api/people/52/?format=api",
        "name": "Jijiang Liu",
        "email": "jijiang.liu@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1411442991-15386-4-git-send-email-jijiang.liu@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/450/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/450/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 2AD34B349;\n\tTue, 23 Sep 2014 05:24:03 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 3C6B9AFCA\n\tfor <dev@dpdk.org>; Tue, 23 Sep 2014 05:24:00 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby orsmga102.jf.intel.com with ESMTP; 22 Sep 2014 20:23:52 -0700",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga001.jf.intel.com with ESMTP; 22 Sep 2014 20:30:04 -0700",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id s8N3U1e8010963;\n\tTue, 23 Sep 2014 11:30:02 +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 s8N3TxwL015442; Tue, 23 Sep 2014 11:30:01 +0800",
            "(from jijiangl@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s8N3TxnQ015438; \n\tTue, 23 Sep 2014 11:29:59 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.04,577,1406617200\"; d=\"scan'208\";a=\"577289842\"",
        "From": "Jijiang Liu <jijiang.liu@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue, 23 Sep 2014 11:29:49 +0800",
        "Message-Id": "<1411442991-15386-4-git-send-email-jijiang.liu@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1411442991-15386-1-git-send-email-jijiang.liu@intel.com>",
        "References": "<1411442991-15386-1-git-send-email-jijiang.liu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 3/5]i40e:optimize MACVLAN filter implementation",
        "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 mainly optimizes i40e_add_macvlan_filters() and i40e_remove_macvlan_filters() functions in order that\nwe can provide a flexible configuration interface. And another relevant MACVLAN filter codes are changed based on new data structures \n\nSigned-off-by: Jijiang Liu <jijiang.liu@intel.com>\nAcked-by: Helin Zhang <helin.zhang@intel.com>\nAcked-by: Jingjing Wu <jingjing.wu@intel.com>\nAcked-by: Changchun Ouyang <changchun.ouyang@intel.com>\n\n---\n lib/librte_pmd_i40e/i40e_ethdev.c |  209 ++++++++++++++++++++++++++++++-------\n lib/librte_pmd_i40e/i40e_ethdev.h |   18 +++-\n lib/librte_pmd_i40e/i40e_pf.c     |    7 +-\n 3 files changed, 193 insertions(+), 41 deletions(-)",
    "diff": "diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c\nindex a00d6ca..9cc2ece 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.c\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.c\n@@ -205,6 +205,9 @@ static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev,\n \t\t\t\t    struct rte_eth_rss_conf *rss_conf);\n static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev,\n \t\t\t\t      struct rte_eth_rss_conf *rss_conf);\n+static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n+\t\t\t\tenum rte_filter_type filter_type,\n+\t\t\t\tenum rte_filter_op filter_op, void *arg);\n \n /* Default hash key buffer for RSS */\n static uint32_t rss_key_default[I40E_PFQF_HKEY_MAX_INDEX + 1];\n@@ -256,6 +259,7 @@ static struct eth_dev_ops i40e_eth_dev_ops = {\n \t.reta_query                   = i40e_dev_rss_reta_query,\n \t.rss_hash_update              = i40e_dev_rss_hash_update,\n \t.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,\n+\t.filter_ctrl                  = i40e_dev_filter_ctrl,\n };\n \n static struct eth_driver rte_i40e_pmd = {\n@@ -1514,6 +1518,7 @@ i40e_macaddr_add(struct rte_eth_dev *dev,\n {\n \tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n \tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct i40e_mac_filter_info mac_filter;\n \tstruct i40e_vsi *vsi = pf->main_vsi;\n \tstruct ether_addr old_mac;\n \tint ret;\n@@ -1539,8 +1544,10 @@ i40e_macaddr_add(struct rte_eth_dev *dev,\n \t(void)rte_memcpy(&old_mac, hw->mac.addr, ETHER_ADDR_LEN);\n \t(void)rte_memcpy(hw->mac.addr, mac_addr->addr_bytes,\n \t\t\tETHER_ADDR_LEN);\n+\t(void)rte_memcpy(&mac_filter.mac_addr, mac_addr, ETHER_ADDR_LEN);\n+\tmac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;\n \n-\tret = i40e_vsi_add_mac(vsi, mac_addr);\n+\tret = i40e_vsi_add_mac(vsi, &mac_filter);\n \tif (ret != I40E_SUCCESS) {\n \t\tPMD_DRV_LOG(ERR, \"Failed to add MACVLAN filter\");\n \t\treturn;\n@@ -2457,6 +2464,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi)\n {\n \tstruct i40e_hw *hw = I40E_VSI_TO_HW(vsi);\n \tstruct i40e_aqc_remove_macvlan_element_data def_filter;\n+\tstruct i40e_mac_filter_info filter;\n \tint ret;\n \n \tif (vsi->type != I40E_VSI_MAIN)\n@@ -2470,6 +2478,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi)\n \tret = i40e_aq_remove_macvlan(hw, vsi->seid, &def_filter, 1, NULL);\n \tif (ret != I40E_SUCCESS) {\n \t\tstruct i40e_mac_filter *f;\n+\t\tstruct ether_addr *mac;\n \n \t\tPMD_DRV_LOG(WARNING, \"Cannot remove the default \"\n \t\t\t    \"macvlan filter\");\n@@ -2479,15 +2488,18 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi)\n \t\t\tPMD_DRV_LOG(ERR, \"failed to allocate memory\");\n \t\t\treturn I40E_ERR_NO_MEMORY;\n \t\t}\n-\t\t(void)rte_memcpy(&f->macaddr.addr_bytes, hw->mac.perm_addr,\n+\t\tmac = &f->mac_info.mac_addr;\n+\t\t(void)rte_memcpy(&mac->addr_bytes, hw->mac.perm_addr,\n \t\t\t\tETH_ADDR_LEN);\n \t\tTAILQ_INSERT_TAIL(&vsi->mac_list, f, next);\n \t\tvsi->mac_num++;\n \n \t\treturn ret;\n \t}\n-\n-\treturn i40e_vsi_add_mac(vsi, (struct ether_addr *)(hw->mac.perm_addr));\n+\t(void)rte_memcpy(&filter.mac_addr,\n+\t\t(struct ether_addr *)(hw->mac.perm_addr), ETH_ADDR_LEN);\n+\tfilter.filter_type = RTE_MACVLAN_PERFECT_MATCH;\n+\treturn i40e_vsi_add_mac(vsi, &filter);\n }\n \n static int\n@@ -2541,6 +2553,7 @@ i40e_vsi_setup(struct i40e_pf *pf,\n {\n \tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n \tstruct i40e_vsi *vsi;\n+\tstruct i40e_mac_filter_info filter;\n \tint ret;\n \tstruct i40e_vsi_context ctxt;\n \tstruct ether_addr broadcast =\n@@ -2751,7 +2764,10 @@ i40e_vsi_setup(struct i40e_pf *pf,\n \t}\n \n \t/* MAC/VLAN configuration */\n-\tret = i40e_vsi_add_mac(vsi, &broadcast);\n+\t(void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);\n+\tfilter.filter_type = RTE_MACVLAN_PERFECT_MATCH;\n+\n+\tret = i40e_vsi_add_mac(vsi, &filter);\n \tif (ret != I40E_SUCCESS) {\n \t\tPMD_DRV_LOG(ERR, \"Failed to add MACVLAN filter\");\n \t\tgoto fail_msix_alloc;\n@@ -3454,6 +3470,7 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi,\n {\n \tint ele_num, ele_buff_size;\n \tint num, actual_num, i;\n+\tuint16_t flags;\n \tint ret = I40E_SUCCESS;\n \tstruct i40e_hw *hw = I40E_VSI_TO_HW(vsi);\n \tstruct i40e_aqc_add_macvlan_element_data *req_list;\n@@ -3479,9 +3496,38 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi,\n \t\t\t\t&filter[num + i].macaddr, ETH_ADDR_LEN);\n \t\t\treq_list[i].vlan_tag =\n \t\t\t\trte_cpu_to_le_16(filter[num + i].vlan_id);\n-\t\t\treq_list[i].flags = rte_cpu_to_le_16(\\\n-\t\t\t\tI40E_AQC_MACVLAN_ADD_PERFECT_MATCH);\n-\t\t\treq_list[i].queue_number = 0;\n+\n+\t\t\tswitch (filter[num + i].filter_type &\n+\t\t\t\tRTE_MACVLAN_FILTER_MASK) {\n+\t\t\tcase RTE_MAC_PERFECT_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH |\n+\t\t\t\t\tI40E_AQC_MACVLAN_ADD_IGNORE_VLAN;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MACVLAN_PERFECT_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MAC_HASH_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |\n+\t\t\t\t\tI40E_AQC_MACVLAN_ADD_IGNORE_VLAN;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MACVLAN_HASH_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_ADD_HASH_MATCH;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tPMD_DRV_LOG(ERR, \"Invalid MAC match type\\n\");\n+\t\t\t\tret = I40E_ERR_PARAM;\n+\t\t\t\tgoto DONE;\n+\t\t\t}\n+\n+\t\t\tif (filter[num + i].filter_type &\n+\t\t\t\tRTE_MACVLAN_TO_QUEUE) {\n+\t\t\t\tflags |= I40E_AQC_MACVLAN_ADD_TO_QUEUE;\n+\t\t\t\treq_list[i].queue_number =\n+\t\t\t\t\trte_cpu_to_le_16(filter[num + i].queue_id);\n+\t\t\t} else\n+\t\t\t\treq_list[i].queue_number = 0;\n+\n+\t\t\treq_list[i].flags = rte_cpu_to_le_16(flags);\n \t\t}\n \n \t\tret = i40e_aq_add_macvlan(hw, vsi->seid, req_list,\n@@ -3505,6 +3551,7 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi,\n {\n \tint ele_num, ele_buff_size;\n \tint num, actual_num, i;\n+\tuint16_t flags;\n \tint ret = I40E_SUCCESS;\n \tstruct i40e_hw *hw = I40E_VSI_TO_HW(vsi);\n \tstruct i40e_aqc_remove_macvlan_element_data *req_list;\n@@ -3531,7 +3578,29 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi,\n \t\t\t\t&filter[num + i].macaddr, ETH_ADDR_LEN);\n \t\t\treq_list[i].vlan_tag =\n \t\t\t\trte_cpu_to_le_16(filter[num + i].vlan_id);\n-\t\t\treq_list[i].flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n+\n+\t\t\tswitch (filter[num + i].filter_type &\n+\t\t\t\t\tRTE_MACVLAN_FILTER_MASK) {\n+\t\t\tcase RTE_MAC_PERFECT_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |\n+\t\t\t\t\tI40E_AQC_MACVLAN_DEL_IGNORE_VLAN;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MACVLAN_PERFECT_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MAC_HASH_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |\n+\t\t\t\t\tI40E_AQC_MACVLAN_DEL_IGNORE_VLAN;\n+\t\t\t\tbreak;\n+\t\t\tcase RTE_MACVLAN_HASH_MATCH:\n+\t\t\t\tflags = I40E_AQC_MACVLAN_DEL_HASH_MATCH;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tPMD_DRV_LOG(ERR, \"Invalid MAC filter type\\n\");\n+\t\t\t\tret = I40E_ERR_PARAM;\n+\t\t\t\tgoto DONE;\n+\t\t\t}\n+\t\t\treq_list[i].flags = rte_cpu_to_le_16(flags);\n \t\t}\n \n \t\tret = i40e_aq_remove_macvlan(hw, vsi->seid, req_list,\n@@ -3556,7 +3625,7 @@ i40e_find_mac_filter(struct i40e_vsi *vsi,\n \tstruct i40e_mac_filter *f;\n \n \tTAILQ_FOREACH(f, &vsi->mac_list, next) {\n-\t\tif (is_same_ether_addr(macaddr, &(f->macaddr)))\n+\t\tif (is_same_ether_addr(macaddr, &f->mac_info.mac_addr))\n \t\t\treturn f;\n \t}\n \n@@ -3657,8 +3726,11 @@ i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi,\n \t\t\tPMD_DRV_LOG(ERR, \"buffer number not match\");\n \t\t\treturn I40E_ERR_PARAM;\n \t\t}\n-\t\t(void)rte_memcpy(&mv_f[i].macaddr, &f->macaddr, ETH_ADDR_LEN);\n+\t\t(void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr,\n+\t\t\t\tETH_ADDR_LEN);\n \t\tmv_f[i].vlan_id = vlan;\n+\t\tmv_f[i].queue_id = f->mac_info.queue_id;\n+\t\tmv_f[i].filter_type = f->mac_info.filter_type;\n \t\ti++;\n \t}\n \n@@ -3692,14 +3764,14 @@ i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi)\n \tif (vsi->vlan_num == 0) {\n \t\tTAILQ_FOREACH(f, &vsi->mac_list, next) {\n \t\t\t(void)rte_memcpy(&mv_f[i].macaddr,\n-\t\t\t\t&f->macaddr, ETH_ADDR_LEN);\n+\t\t\t\t&f->mac_info.mac_addr, ETH_ADDR_LEN);\n \t\t\tmv_f[i].vlan_id = 0;\n \t\t\ti++;\n \t\t}\n \t} else {\n \t\tTAILQ_FOREACH(f, &vsi->mac_list, next) {\n \t\t\tret = i40e_find_all_vlan_for_mac(vsi,&mv_f[i],\n-\t\t\t\t\tvsi->vlan_num, &f->macaddr);\n+\t\t\t\t\tvsi->vlan_num, &f->mac_info.mac_addr);\n \t\t\tif (ret != I40E_SUCCESS)\n \t\t\t\tgoto DONE;\n \t\t\ti += vsi->vlan_num;\n@@ -3823,28 +3895,32 @@ DONE:\n }\n \n int\n-i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr)\n+i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter)\n {\n \tstruct i40e_mac_filter *f;\n \tstruct i40e_macvlan_filter *mv_f;\n-\tint vlan_num;\n+\tint i, vlan_num = 0;\n \tint ret = I40E_SUCCESS;\n \n \t/* If it's add and we've config it, return */\n-\tf = i40e_find_mac_filter(vsi, addr);\n+\tf = i40e_find_mac_filter(vsi, &mac_filter->mac_addr);\n \tif (f != NULL)\n \t\treturn I40E_SUCCESS;\n+\tif ((mac_filter->filter_type & RTE_MACVLAN_PERFECT_MATCH) ||\n+\t\t(mac_filter->filter_type & RTE_MACVLAN_HASH_MATCH)) {\n \n-\t/**\n-\t * If vlan_num is 0, that's the first time to add mac,\n-\t * set mask for vlan_id 0.\n-\t */\n-\tif (vsi->vlan_num == 0) {\n-\t\ti40e_set_vlan_filter(vsi, 0, 1);\n-\t\tvsi->vlan_num = 1;\n-\t}\n-\n-\tvlan_num = vsi->vlan_num;\n+\t\t/**\n+\t\t * If vlan_num is 0, that's the first time to add mac,\n+\t\t * set mask for vlan_id 0.\n+\t\t */\n+\t\tif (vsi->vlan_num == 0) {\n+\t\t\ti40e_set_vlan_filter(vsi, 0, 1);\n+\t\t\tvsi->vlan_num = 1;\n+\t\t}\n+\t\tvlan_num = vsi->vlan_num;\n+\t} else if ((mac_filter->filter_type & RTE_MAC_PERFECT_MATCH) ||\n+\t\t\t(mac_filter->filter_type & RTE_MAC_HASH_MATCH))\n+\t\tvlan_num = 1;\n \n \tmv_f = rte_zmalloc(\"macvlan_data\", vlan_num * sizeof(*mv_f), 0);\n \tif (mv_f == NULL) {\n@@ -3852,9 +3928,20 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr)\n \t\treturn I40E_ERR_NO_MEMORY;\n \t}\n \n-\tret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr);\n-\tif (ret != I40E_SUCCESS)\n-\t\tgoto DONE;\n+\tfor (i = 0; i < vlan_num; i++) {\n+\t\tmv_f[i].filter_type = mac_filter->filter_type;\n+\t\tmv_f[i].queue_id = mac_filter->queue_id;\n+\t\t(void)rte_memcpy(&mv_f[i].macaddr, &mac_filter->mac_addr,\n+\t\t\t\tETH_ADDR_LEN);\n+\t}\n+\n+\tif (mac_filter->filter_type & RTE_MACVLAN_PERFECT_MATCH ||\n+\t\tmac_filter->filter_type & RTE_MACVLAN_HASH_MATCH) {\n+\t\tret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,\n+\t\t\t\t\t&mac_filter->mac_addr);\n+\t\tif (ret != I40E_SUCCESS)\n+\t\t\tgoto DONE;\n+\t}\n \n \tret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);\n \tif (ret != I40E_SUCCESS)\n@@ -3867,7 +3954,10 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr)\n \t\tret = I40E_ERR_NO_MEMORY;\n \t\tgoto DONE;\n \t}\n-\t(void)rte_memcpy(&f->macaddr, addr, ETH_ADDR_LEN);\n+\t(void)rte_memcpy(&f->mac_info.mac_addr, &mac_filter->mac_addr,\n+\t\t\tETH_ADDR_LEN);\n+\tf->mac_info.filter_type = mac_filter->filter_type;\n+\tf->mac_info.queue_id = mac_filter->queue_id;\n \tTAILQ_INSERT_TAIL(&vsi->mac_list, f, next);\n \tvsi->mac_num++;\n \n@@ -3883,7 +3973,8 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr)\n {\n \tstruct i40e_mac_filter *f;\n \tstruct i40e_macvlan_filter *mv_f;\n-\tint vlan_num;\n+\tint i, vlan_num;\n+\tuint16_t filter_type;\n \tint ret = I40E_SUCCESS;\n \n \t/* Can't find it, return an error */\n@@ -3892,19 +3983,34 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr)\n \t\treturn I40E_ERR_PARAM;\n \n \tvlan_num = vsi->vlan_num;\n-\tif (vlan_num == 0) {\n-\t\tPMD_DRV_LOG(ERR, \"VLAN number shouldn't be 0\");\n-\t\treturn I40E_ERR_PARAM;\n-\t}\n+\tfilter_type = f->mac_info.filter_type;\n+\tif (filter_type & RTE_MACVLAN_PERFECT_MATCH ||\n+\t\tfilter_type & RTE_MACVLAN_HASH_MATCH) {\n+\t\tif (vlan_num == 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"VLAN number shouldn't be 0\\n\");\n+\t\t\treturn I40E_ERR_PARAM;\n+\t\t}\n+\t} else if (filter_type & RTE_MAC_PERFECT_MATCH ||\n+\t\t\tfilter_type & RTE_MAC_HASH_MATCH)\n+\t\tvlan_num = 1;\n+\n \tmv_f = rte_zmalloc(\"macvlan_data\", vlan_num * sizeof(*mv_f), 0);\n \tif (mv_f == NULL) {\n \t\tPMD_DRV_LOG(ERR, \"failed to allocate memory\");\n \t\treturn I40E_ERR_NO_MEMORY;\n \t}\n \n-\tret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr);\n-\tif (ret != I40E_SUCCESS)\n-\t\tgoto DONE;\n+\tfor (i = 0; i < vlan_num; i++) {\n+\t\tmv_f[i].filter_type = filter_type;\n+\t\t(void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr,\n+\t\t\t\tETH_ADDR_LEN);\n+\t}\n+\tif (filter_type & RTE_MACVLAN_PERFECT_MATCH ||\n+\t\t\tfilter_type & RTE_MACVLAN_HASH_MATCH) {\n+\t\tret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr);\n+\t\tif (ret != I40E_SUCCESS)\n+\t\t\tgoto DONE;\n+\t}\n \n \tret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);\n \tif (ret != I40E_SUCCESS)\n@@ -4115,6 +4221,33 @@ i40e_pf_config_rss(struct i40e_pf *pf)\n \treturn i40e_hw_rss_hash_set(hw, &rss_conf);\n }\n \n+/*\n+ * Take operations to assigned filter type on NIC.\n+ */\n+static int\n+i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,\n+\t\t     enum rte_filter_op filter_op, void *arg) {\n+\n+\tint ret = 0;\n+\n+\tif (dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\tif (arg == NULL && filter_op != RTE_ETH_FILTER_OP_NONE)\n+\t\treturn -EINVAL;\n+\n+\tswitch (filter_type) {\n+\tcase RTE_ETH_FILTER_MACVLAN:\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"unsupported filter type %u\\n\", filter_type);\n+\t\tret = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n static int\n i40e_pf_config_mq_rx(struct i40e_pf *pf)\n {\ndiff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h\nindex 64deef2..4bbc606 100644\n--- a/lib/librte_pmd_i40e/i40e_ethdev.h\n+++ b/lib/librte_pmd_i40e/i40e_ethdev.h\n@@ -34,6 +34,8 @@\n #ifndef _I40E_ETHDEV_H_\n #define _I40E_ETHDEV_H_\n \n+#include <rte_eth_ctrl.h>\n+\n #define I40E_AQ_LEN               32\n #define I40E_AQ_BUF_SZ            4096\n /* Number of queues per TC should be one of 1, 2, 4, 8, 16, 32, 64 */\n@@ -70,12 +72,21 @@\n \n struct i40e_adapter;\n \n+/**\n+ * MAC filter structure\n+ */\n+struct i40e_mac_filter_info {\n+\tuint16_t filter_type;\n+\tuint16_t queue_id;\n+\tstruct ether_addr mac_addr;\n+};\n+\n TAILQ_HEAD(i40e_mac_filter_list, i40e_mac_filter);\n \n /* MAC filter list structure */\n struct i40e_mac_filter {\n \tTAILQ_ENTRY(i40e_mac_filter) next;\n-\tstruct ether_addr macaddr;\n+\tstruct i40e_mac_filter_info mac_info;\n };\n \n TAILQ_HEAD(i40e_vsi_list_head, i40e_vsi_list);\n@@ -104,8 +115,11 @@ struct i40e_veb {\n /* MACVLAN filter structure */\n struct i40e_macvlan_filter {\n \tstruct ether_addr macaddr;\n+\tuint16_t filter_type;\n+\tuint16_t queue_id;\n \tuint16_t vlan_id;\n };\n+\n /*\n  * Structure that defines a VSI, associated with a adapter.\n  */\n@@ -300,7 +314,7 @@ int i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on);\n int i40e_switch_tx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on);\n int i40e_vsi_add_vlan(struct i40e_vsi *vsi, uint16_t vlan);\n int i40e_vsi_delete_vlan(struct i40e_vsi *vsi, uint16_t vlan);\n-int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr);\n+int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *filter);\n int i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr);\n void i40e_update_vsi_stats(struct i40e_vsi *vsi);\n void i40e_pf_disable_irq0(struct i40e_hw *hw);\ndiff --git a/lib/librte_pmd_i40e/i40e_pf.c b/lib/librte_pmd_i40e/i40e_pf.c\nindex 682ff44..f9049e1 100644\n--- a/lib/librte_pmd_i40e/i40e_pf.c\n+++ b/lib/librte_pmd_i40e/i40e_pf.c\n@@ -597,9 +597,12 @@ i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,\n \tint ret = I40E_SUCCESS;\n \tstruct i40e_virtchnl_ether_addr_list *addr_list =\n \t\t\t(struct i40e_virtchnl_ether_addr_list *)msg;\n+\tstruct i40e_mac_filter_info filter;\n \tint i;\n \tstruct ether_addr *mac;\n \n+\tmemset(&filter, 0 , sizeof(struct i40e_mac_filter_info));\n+\n \tif (msg == NULL || msglen <= sizeof(*addr_list)) {\n \t\tPMD_DRV_LOG(ERR, \"add_ether_address argument too short\");\n \t\tret = I40E_ERR_PARAM;\n@@ -608,8 +611,10 @@ i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,\n \n \tfor (i = 0; i < addr_list->num_elements; i++) {\n \t\tmac = (struct ether_addr *)(addr_list->list[i].addr);\n+\t\t(void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);\n+\t\tfilter.filter_type = RTE_MACVLAN_PERFECT_MATCH;\n \t\tif(!is_valid_assigned_ether_addr(mac) ||\n-\t\t\ti40e_vsi_add_mac(vf->vsi, mac)) {\n+\t\t\ti40e_vsi_add_mac(vf->vsi, &filter)) {\n \t\t\tret = I40E_ERR_INVALID_MAC_ADDR;\n \t\t\tgoto send_msg;\n \t\t}\n",
    "prefixes": [
        "dpdk-dev",
        "3/5"
    ]
}