From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 3C6B9AFCA for ; Tue, 23 Sep 2014 05:24:00 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 22 Sep 2014 20:23:52 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,577,1406617200"; d="scan'208";a="577289842" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga001.jf.intel.com with ESMTP; 22 Sep 2014 20:30:04 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id s8N3U1e8010963; Tue, 23 Sep 2014 11:30:02 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id s8N3TxwL015442; Tue, 23 Sep 2014 11:30:01 +0800 Received: (from jijiangl@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id s8N3TxnQ015438; Tue, 23 Sep 2014 11:29:59 +0800 From: Jijiang Liu 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Sep 2014 03:24:01 -0000 This patch mainly optimizes i40e_add_macvlan_filters() and i40e_remove_macvlan_filters() functions in order that we can provide a flexible configuration interface. And another relevant MACVLAN filter codes are changed based on new data structures Signed-off-by: Jijiang Liu Acked-by: Helin Zhang Acked-by: Jingjing Wu Acked-by: Changchun Ouyang --- lib/librte_pmd_i40e/i40e_ethdev.c | 209 ++++++++++++++++++++++++++++++------- lib/librte_pmd_i40e/i40e_ethdev.h | 18 +++- lib/librte_pmd_i40e/i40e_pf.c | 7 +- 3 files changed, 193 insertions(+), 41 deletions(-) diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index a00d6ca..9cc2ece 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -205,6 +205,9 @@ static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); +static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, void *arg); /* Default hash key buffer for RSS */ static uint32_t rss_key_default[I40E_PFQF_HKEY_MAX_INDEX + 1]; @@ -256,6 +259,7 @@ static struct eth_dev_ops i40e_eth_dev_ops = { .reta_query = i40e_dev_rss_reta_query, .rss_hash_update = i40e_dev_rss_hash_update, .rss_hash_conf_get = i40e_dev_rss_hash_conf_get, + .filter_ctrl = i40e_dev_filter_ctrl, }; static struct eth_driver rte_i40e_pmd = { @@ -1514,6 +1518,7 @@ i40e_macaddr_add(struct rte_eth_dev *dev, { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_mac_filter_info mac_filter; struct i40e_vsi *vsi = pf->main_vsi; struct ether_addr old_mac; int ret; @@ -1539,8 +1544,10 @@ i40e_macaddr_add(struct rte_eth_dev *dev, (void)rte_memcpy(&old_mac, hw->mac.addr, ETHER_ADDR_LEN); (void)rte_memcpy(hw->mac.addr, mac_addr->addr_bytes, ETHER_ADDR_LEN); + (void)rte_memcpy(&mac_filter.mac_addr, mac_addr, ETHER_ADDR_LEN); + mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; - ret = i40e_vsi_add_mac(vsi, mac_addr); + ret = i40e_vsi_add_mac(vsi, &mac_filter); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter"); return; @@ -2457,6 +2464,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_remove_macvlan_element_data def_filter; + struct i40e_mac_filter_info filter; int ret; if (vsi->type != I40E_VSI_MAIN) @@ -2470,6 +2478,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi) ret = i40e_aq_remove_macvlan(hw, vsi->seid, &def_filter, 1, NULL); if (ret != I40E_SUCCESS) { struct i40e_mac_filter *f; + struct ether_addr *mac; PMD_DRV_LOG(WARNING, "Cannot remove the default " "macvlan filter"); @@ -2479,15 +2488,18 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi) PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } - (void)rte_memcpy(&f->macaddr.addr_bytes, hw->mac.perm_addr, + mac = &f->mac_info.mac_addr; + (void)rte_memcpy(&mac->addr_bytes, hw->mac.perm_addr, ETH_ADDR_LEN); TAILQ_INSERT_TAIL(&vsi->mac_list, f, next); vsi->mac_num++; return ret; } - - return i40e_vsi_add_mac(vsi, (struct ether_addr *)(hw->mac.perm_addr)); + (void)rte_memcpy(&filter.mac_addr, + (struct ether_addr *)(hw->mac.perm_addr), ETH_ADDR_LEN); + filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; + return i40e_vsi_add_mac(vsi, &filter); } static int @@ -2541,6 +2553,7 @@ i40e_vsi_setup(struct i40e_pf *pf, { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_vsi *vsi; + struct i40e_mac_filter_info filter; int ret; struct i40e_vsi_context ctxt; struct ether_addr broadcast = @@ -2751,7 +2764,10 @@ i40e_vsi_setup(struct i40e_pf *pf, } /* MAC/VLAN configuration */ - ret = i40e_vsi_add_mac(vsi, &broadcast); + (void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN); + filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; + + ret = i40e_vsi_add_mac(vsi, &filter); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter"); goto fail_msix_alloc; @@ -3454,6 +3470,7 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi, { int ele_num, ele_buff_size; int num, actual_num, i; + uint16_t flags; int ret = I40E_SUCCESS; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_add_macvlan_element_data *req_list; @@ -3479,9 +3496,38 @@ i40e_add_macvlan_filters(struct i40e_vsi *vsi, &filter[num + i].macaddr, ETH_ADDR_LEN); req_list[i].vlan_tag = rte_cpu_to_le_16(filter[num + i].vlan_id); - req_list[i].flags = rte_cpu_to_le_16(\ - I40E_AQC_MACVLAN_ADD_PERFECT_MATCH); - req_list[i].queue_number = 0; + + switch (filter[num + i].filter_type & + RTE_MACVLAN_FILTER_MASK) { + case RTE_MAC_PERFECT_MATCH: + flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH | + I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; + break; + case RTE_MACVLAN_PERFECT_MATCH: + flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; + break; + case RTE_MAC_HASH_MATCH: + flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH | + I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; + break; + case RTE_MACVLAN_HASH_MATCH: + flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH; + break; + default: + PMD_DRV_LOG(ERR, "Invalid MAC match type\n"); + ret = I40E_ERR_PARAM; + goto DONE; + } + + if (filter[num + i].filter_type & + RTE_MACVLAN_TO_QUEUE) { + flags |= I40E_AQC_MACVLAN_ADD_TO_QUEUE; + req_list[i].queue_number = + rte_cpu_to_le_16(filter[num + i].queue_id); + } else + req_list[i].queue_number = 0; + + req_list[i].flags = rte_cpu_to_le_16(flags); } ret = i40e_aq_add_macvlan(hw, vsi->seid, req_list, @@ -3505,6 +3551,7 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi, { int ele_num, ele_buff_size; int num, actual_num, i; + uint16_t flags; int ret = I40E_SUCCESS; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_remove_macvlan_element_data *req_list; @@ -3531,7 +3578,29 @@ i40e_remove_macvlan_filters(struct i40e_vsi *vsi, &filter[num + i].macaddr, ETH_ADDR_LEN); req_list[i].vlan_tag = rte_cpu_to_le_16(filter[num + i].vlan_id); - req_list[i].flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; + + switch (filter[num + i].filter_type & + RTE_MACVLAN_FILTER_MASK) { + case RTE_MAC_PERFECT_MATCH: + flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | + I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; + break; + case RTE_MACVLAN_PERFECT_MATCH: + flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; + break; + case RTE_MAC_HASH_MATCH: + flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH | + I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; + break; + case RTE_MACVLAN_HASH_MATCH: + flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH; + break; + default: + PMD_DRV_LOG(ERR, "Invalid MAC filter type\n"); + ret = I40E_ERR_PARAM; + goto DONE; + } + req_list[i].flags = rte_cpu_to_le_16(flags); } ret = i40e_aq_remove_macvlan(hw, vsi->seid, req_list, @@ -3556,7 +3625,7 @@ i40e_find_mac_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f; TAILQ_FOREACH(f, &vsi->mac_list, next) { - if (is_same_ether_addr(macaddr, &(f->macaddr))) + if (is_same_ether_addr(macaddr, &f->mac_info.mac_addr)) return f; } @@ -3657,8 +3726,11 @@ i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi, PMD_DRV_LOG(ERR, "buffer number not match"); return I40E_ERR_PARAM; } - (void)rte_memcpy(&mv_f[i].macaddr, &f->macaddr, ETH_ADDR_LEN); + (void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, + ETH_ADDR_LEN); mv_f[i].vlan_id = vlan; + mv_f[i].queue_id = f->mac_info.queue_id; + mv_f[i].filter_type = f->mac_info.filter_type; i++; } @@ -3692,14 +3764,14 @@ i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi) if (vsi->vlan_num == 0) { TAILQ_FOREACH(f, &vsi->mac_list, next) { (void)rte_memcpy(&mv_f[i].macaddr, - &f->macaddr, ETH_ADDR_LEN); + &f->mac_info.mac_addr, ETH_ADDR_LEN); mv_f[i].vlan_id = 0; i++; } } else { TAILQ_FOREACH(f, &vsi->mac_list, next) { ret = i40e_find_all_vlan_for_mac(vsi,&mv_f[i], - vsi->vlan_num, &f->macaddr); + vsi->vlan_num, &f->mac_info.mac_addr); if (ret != I40E_SUCCESS) goto DONE; i += vsi->vlan_num; @@ -3823,28 +3895,32 @@ DONE: } int -i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr) +i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter) { struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; - int vlan_num; + int i, vlan_num = 0; int ret = I40E_SUCCESS; /* If it's add and we've config it, return */ - f = i40e_find_mac_filter(vsi, addr); + f = i40e_find_mac_filter(vsi, &mac_filter->mac_addr); if (f != NULL) return I40E_SUCCESS; + if ((mac_filter->filter_type & RTE_MACVLAN_PERFECT_MATCH) || + (mac_filter->filter_type & RTE_MACVLAN_HASH_MATCH)) { - /** - * If vlan_num is 0, that's the first time to add mac, - * set mask for vlan_id 0. - */ - if (vsi->vlan_num == 0) { - i40e_set_vlan_filter(vsi, 0, 1); - vsi->vlan_num = 1; - } - - vlan_num = vsi->vlan_num; + /** + * If vlan_num is 0, that's the first time to add mac, + * set mask for vlan_id 0. + */ + if (vsi->vlan_num == 0) { + i40e_set_vlan_filter(vsi, 0, 1); + vsi->vlan_num = 1; + } + vlan_num = vsi->vlan_num; + } else if ((mac_filter->filter_type & RTE_MAC_PERFECT_MATCH) || + (mac_filter->filter_type & RTE_MAC_HASH_MATCH)) + vlan_num = 1; mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); if (mv_f == NULL) { @@ -3852,9 +3928,20 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr) return I40E_ERR_NO_MEMORY; } - ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr); - if (ret != I40E_SUCCESS) - goto DONE; + for (i = 0; i < vlan_num; i++) { + mv_f[i].filter_type = mac_filter->filter_type; + mv_f[i].queue_id = mac_filter->queue_id; + (void)rte_memcpy(&mv_f[i].macaddr, &mac_filter->mac_addr, + ETH_ADDR_LEN); + } + + if (mac_filter->filter_type & RTE_MACVLAN_PERFECT_MATCH || + mac_filter->filter_type & RTE_MACVLAN_HASH_MATCH) { + ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, + &mac_filter->mac_addr); + if (ret != I40E_SUCCESS) + goto DONE; + } ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num); if (ret != I40E_SUCCESS) @@ -3867,7 +3954,10 @@ i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr) ret = I40E_ERR_NO_MEMORY; goto DONE; } - (void)rte_memcpy(&f->macaddr, addr, ETH_ADDR_LEN); + (void)rte_memcpy(&f->mac_info.mac_addr, &mac_filter->mac_addr, + ETH_ADDR_LEN); + f->mac_info.filter_type = mac_filter->filter_type; + f->mac_info.queue_id = mac_filter->queue_id; TAILQ_INSERT_TAIL(&vsi->mac_list, f, next); vsi->mac_num++; @@ -3883,7 +3973,8 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr) { struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; - int vlan_num; + int i, vlan_num; + uint16_t filter_type; int ret = I40E_SUCCESS; /* Can't find it, return an error */ @@ -3892,19 +3983,34 @@ i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr) return I40E_ERR_PARAM; vlan_num = vsi->vlan_num; - if (vlan_num == 0) { - PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0"); - return I40E_ERR_PARAM; - } + filter_type = f->mac_info.filter_type; + if (filter_type & RTE_MACVLAN_PERFECT_MATCH || + filter_type & RTE_MACVLAN_HASH_MATCH) { + if (vlan_num == 0) { + PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0\n"); + return I40E_ERR_PARAM; + } + } else if (filter_type & RTE_MAC_PERFECT_MATCH || + filter_type & RTE_MAC_HASH_MATCH) + vlan_num = 1; + mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } - ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr); - if (ret != I40E_SUCCESS) - goto DONE; + for (i = 0; i < vlan_num; i++) { + mv_f[i].filter_type = filter_type; + (void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, + ETH_ADDR_LEN); + } + if (filter_type & RTE_MACVLAN_PERFECT_MATCH || + filter_type & RTE_MACVLAN_HASH_MATCH) { + ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr); + if (ret != I40E_SUCCESS) + goto DONE; + } ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num); if (ret != I40E_SUCCESS) @@ -4115,6 +4221,33 @@ i40e_pf_config_rss(struct i40e_pf *pf) return i40e_hw_rss_hash_set(hw, &rss_conf); } +/* + * Take operations to assigned filter type on NIC. + */ +static int +i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, + enum rte_filter_op filter_op, void *arg) { + + int ret = 0; + + if (dev == NULL) + return -EINVAL; + + if (arg == NULL && filter_op != RTE_ETH_FILTER_OP_NONE) + return -EINVAL; + + switch (filter_type) { + case RTE_ETH_FILTER_MACVLAN: + break; + default: + PMD_DRV_LOG(ERR, "unsupported filter type %u\n", filter_type); + ret = -EINVAL; + break; + } + + return ret; +} + static int i40e_pf_config_mq_rx(struct i40e_pf *pf) { diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h index 64deef2..4bbc606 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.h +++ b/lib/librte_pmd_i40e/i40e_ethdev.h @@ -34,6 +34,8 @@ #ifndef _I40E_ETHDEV_H_ #define _I40E_ETHDEV_H_ +#include + #define I40E_AQ_LEN 32 #define I40E_AQ_BUF_SZ 4096 /* Number of queues per TC should be one of 1, 2, 4, 8, 16, 32, 64 */ @@ -70,12 +72,21 @@ struct i40e_adapter; +/** + * MAC filter structure + */ +struct i40e_mac_filter_info { + uint16_t filter_type; + uint16_t queue_id; + struct ether_addr mac_addr; +}; + TAILQ_HEAD(i40e_mac_filter_list, i40e_mac_filter); /* MAC filter list structure */ struct i40e_mac_filter { TAILQ_ENTRY(i40e_mac_filter) next; - struct ether_addr macaddr; + struct i40e_mac_filter_info mac_info; }; TAILQ_HEAD(i40e_vsi_list_head, i40e_vsi_list); @@ -104,8 +115,11 @@ struct i40e_veb { /* MACVLAN filter structure */ struct i40e_macvlan_filter { struct ether_addr macaddr; + uint16_t filter_type; + uint16_t queue_id; uint16_t vlan_id; }; + /* * Structure that defines a VSI, associated with a adapter. */ @@ -300,7 +314,7 @@ int i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on); int i40e_switch_tx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, uint16_t vlan); int i40e_vsi_delete_vlan(struct i40e_vsi *vsi, uint16_t vlan); -int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct ether_addr *addr); +int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *filter); int i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr); void i40e_update_vsi_stats(struct i40e_vsi *vsi); void i40e_pf_disable_irq0(struct i40e_hw *hw); diff --git a/lib/librte_pmd_i40e/i40e_pf.c b/lib/librte_pmd_i40e/i40e_pf.c index 682ff44..f9049e1 100644 --- a/lib/librte_pmd_i40e/i40e_pf.c +++ b/lib/librte_pmd_i40e/i40e_pf.c @@ -597,9 +597,12 @@ i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf, int ret = I40E_SUCCESS; struct i40e_virtchnl_ether_addr_list *addr_list = (struct i40e_virtchnl_ether_addr_list *)msg; + struct i40e_mac_filter_info filter; int i; struct ether_addr *mac; + memset(&filter, 0 , sizeof(struct i40e_mac_filter_info)); + if (msg == NULL || msglen <= sizeof(*addr_list)) { PMD_DRV_LOG(ERR, "add_ether_address argument too short"); ret = I40E_ERR_PARAM; @@ -608,8 +611,10 @@ i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf, for (i = 0; i < addr_list->num_elements; i++) { mac = (struct ether_addr *)(addr_list->list[i].addr); + (void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN); + filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; if(!is_valid_assigned_ether_addr(mac) || - i40e_vsi_add_mac(vf->vsi, mac)) { + i40e_vsi_add_mac(vf->vsi, &filter)) { ret = I40E_ERR_INVALID_MAC_ADDR; goto send_msg; } -- 1.7.7.6