From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 670A9A2EDB for ; Mon, 30 Sep 2019 15:48:21 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 367524CE4; Mon, 30 Sep 2019 15:48:21 +0200 (CEST) Received: from huawei.com (szxga06-in.huawei.com [45.249.212.32]) by dpdk.org (Postfix) with ESMTP id 897644CA6 for ; Mon, 30 Sep 2019 15:48:19 +0200 (CEST) Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id D2C02B618AD21A1095FA for ; Mon, 30 Sep 2019 21:48:17 +0800 (CST) Received: from tester.localdomain (10.175.119.39) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.439.0; Mon, 30 Sep 2019 21:48:07 +0800 From: Xiaoyun wang To: CC: , , , , , , , Xiaoyun wang Date: Mon, 30 Sep 2019 22:00:44 +0800 Message-ID: <9e7e0a9b186e756ac3099fd0c21dd33cc8a2ff02.1569850827.git.cloud.wangxiaoyun@huawei.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.175.119.39] X-CFilter-Loop: Reflected Subject: [dpdk-dev] [PATCH v3 06/19] net/hinic: add unicast and multicast MAC set X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds unicast and multicast set interfaces. Application can add or remove unicast MAC address, also can set multicast MAC address, tha maximum multicast list size is 2048. Signed-off-by: Xiaoyun wang --- doc/guides/nics/hinic.rst | 2 + drivers/net/hinic/base/hinic_pmd_niccfg.c | 55 +++++++ drivers/net/hinic/hinic_pmd_ethdev.c | 260 +++++++++++++++++++++++++++--- drivers/net/hinic/hinic_pmd_ethdev.h | 2 + 4 files changed, 298 insertions(+), 21 deletions(-) diff --git a/doc/guides/nics/hinic.rst b/doc/guides/nics/hinic.rst index 681519c..4df5f16 100644 --- a/doc/guides/nics/hinic.rst +++ b/doc/guides/nics/hinic.rst @@ -28,6 +28,8 @@ Features - VLAN filter and VLAN offload - Allmulticast mode - MTU update +- Unicast MAC filter +- Multicast MAC filter Prerequisites ------------- diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c index 8bd7ed6..054925c 100644 --- a/drivers/net/hinic/base/hinic_pmd_niccfg.c +++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c @@ -250,6 +250,61 @@ int hinic_get_default_mac(void *hwdev, u8 *mac_addr) } /** +* hinic_update_mac - Update mac address to hardware. +* +* @param hwdev +* The hardware interface of a nic device. +* @param old_mac +* Old mac address. +* @param new_mac +* New mac address. +* @param vlan_id +* Set 0 for mac_vlan table initialization. +* @param func_id +* Global function id of NIC. +* +* @return +* 0 on success. +* negative error value otherwise. +*/ +int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id, + u16 func_id) +{ + struct hinic_port_mac_update mac_info; + u16 out_size = sizeof(mac_info); + int err; + + if (!hwdev || !old_mac || !new_mac) { + PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL\n"); + return -EINVAL; + } + + memset(&mac_info, 0, sizeof(mac_info)); + mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; + mac_info.func_id = func_id; + mac_info.vlan_id = vlan_id; + memcpy(mac_info.old_mac, old_mac, ETH_ALEN); + memcpy(mac_info.new_mac, new_mac, ETH_ALEN); + + err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UPDATE_MAC, + &mac_info, sizeof(mac_info), + &mac_info, &out_size); + if (err || !out_size || + (mac_info.mgmt_msg_head.status && + mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) { + PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n", + err, mac_info.mgmt_msg_head.status, out_size); + return -EINVAL; + } + if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) { + PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation.\n"); + return HINIC_PF_SET_VF_ALREADY; + } + + return 0; +} + +/** * hinic_set_port_mtu - Set MTU to port. * * @param hwdev diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c index 96967a3..91b4f98 100644 --- a/drivers/net/hinic/hinic_pmd_ethdev.c +++ b/drivers/net/hinic/hinic_pmd_ethdev.c @@ -51,8 +51,8 @@ #define NR_MAX_COS 8 #define HINIC_MIN_RX_BUF_SIZE 1024 -#define HINIC_MAX_MAC_ADDRS 1 - +#define HINIC_MAX_UC_MAC_ADDRS 128 +#define HINIC_MAX_MC_MAC_ADDRS 2048 /* * vlan_id is a 12 bit number. * The VFTA array is actually a 4096 bit array, 128 of 32bit elements. @@ -716,7 +716,7 @@ static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa) info->max_tx_queues = nic_dev->nic_cap.max_sqs; info->min_rx_bufsize = HINIC_MIN_RX_BUF_SIZE; info->max_rx_pktlen = HINIC_MAX_JUMBO_FRAME_SIZE; - info->max_mac_addrs = HINIC_MAX_MAC_ADDRS; + info->max_mac_addrs = HINIC_MAX_UC_MAC_ADDRS; info->min_mtu = HINIC_MIN_MTU_SIZE; info->max_mtu = HINIC_MAX_MTU_SIZE; @@ -1342,21 +1342,41 @@ static int hinic_init_mac_addr(struct rte_eth_dev *eth_dev) if (rc) return rc; - memmove(eth_dev->data->mac_addrs->addr_bytes, - addr_bytes, RTE_ETHER_ADDR_LEN); - - if (rte_is_zero_ether_addr(eth_dev->data->mac_addrs)) - hinic_gen_random_mac_addr(eth_dev->data->mac_addrs); + rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes, + ð_dev->data->mac_addrs[0]); + if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[0])) + hinic_gen_random_mac_addr(ð_dev->data->mac_addrs[0]); func_id = hinic_global_func_id(nic_dev->hwdev); - rc = hinic_set_mac(nic_dev->hwdev, eth_dev->data->mac_addrs->addr_bytes, - 0, func_id); + rc = hinic_set_mac(nic_dev->hwdev, + eth_dev->data->mac_addrs[0].addr_bytes, + 0, func_id); if (rc && rc != HINIC_PF_SET_VF_ALREADY) return rc; + rte_ether_addr_copy(ð_dev->data->mac_addrs[0], + &nic_dev->default_addr); + return 0; } +static void hinic_delete_mc_addr_list(struct hinic_nic_dev *nic_dev) +{ + u16 func_id; + u32 i; + + func_id = hinic_global_func_id(nic_dev->hwdev); + + for (i = 0; i < HINIC_MAX_MC_MAC_ADDRS; i++) { + if (rte_is_zero_ether_addr(&nic_dev->mc_list[i])) + break; + + hinic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes, + 0, func_id); + memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr)); + } +} + /** * Deinit mac_vlan table in NIC. * @@ -1371,19 +1391,29 @@ static void hinic_deinit_mac_addr(struct rte_eth_dev *eth_dev) { struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); - int rc; u16 func_id = 0; - - if (rte_is_zero_ether_addr(eth_dev->data->mac_addrs)) - return; + int rc; + int i; func_id = hinic_global_func_id(nic_dev->hwdev); - rc = hinic_del_mac(nic_dev->hwdev, - eth_dev->data->mac_addrs->addr_bytes, - 0, func_id); - if (rc && rc != HINIC_PF_SET_VF_ALREADY) - PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s", - eth_dev->data->name); + + for (i = 0; i < HINIC_MAX_UC_MAC_ADDRS; i++) { + if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[i])) + continue; + + rc = hinic_del_mac(nic_dev->hwdev, + eth_dev->data->mac_addrs[i].addr_bytes, + 0, func_id); + if (rc && rc != HINIC_PF_SET_VF_ALREADY) + PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s", + eth_dev->data->name); + + memset(ð_dev->data->mac_addrs[i], 0, + sizeof(struct rte_ether_addr)); + } + + /* delete multicast mac addrs */ + hinic_delete_mc_addr_list(nic_dev); } static int hinic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) @@ -2091,6 +2121,169 @@ static int hinic_dev_xstats_get_names(struct rte_eth_dev *dev, return count; } +/** + * DPDK callback to set mac address + * + * @param dev + * Pointer to Ethernet device structure. + * @param addr + * Pointer to mac address + * @return + * 0 on success, negative error value otherwise. + */ +static int hinic_set_mac_addr(struct rte_eth_dev *dev, + struct rte_ether_addr *addr) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + u16 func_id; + int err; + + func_id = hinic_global_func_id(nic_dev->hwdev); + err = hinic_update_mac(nic_dev->hwdev, nic_dev->default_addr.addr_bytes, + addr->addr_bytes, 0, func_id); + if (err) + return err; + + rte_ether_addr_copy(addr, &nic_dev->default_addr); + + PMD_DRV_LOG(INFO, "Set new mac address %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->addr_bytes[0], addr->addr_bytes[1], + addr->addr_bytes[2], addr->addr_bytes[3], + addr->addr_bytes[4], addr->addr_bytes[5]); + + return 0; +} + +/** + * DPDK callback to remove a MAC address. + * + * @param dev + * Pointer to Ethernet device structure. + * @param index + * MAC address index. + */ +static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + u16 func_id; + int ret; + + if (index >= HINIC_MAX_UC_MAC_ADDRS) { + PMD_DRV_LOG(INFO, "Remove mac index(%u) is out of range", + index); + return; + } + + func_id = hinic_global_func_id(nic_dev->hwdev); + ret = hinic_del_mac(nic_dev->hwdev, + dev->data->mac_addrs[index].addr_bytes, 0, func_id); + if (ret) + return; + + memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr)); +} + +/** + * DPDK callback to add a MAC address. + * + * @param dev + * Pointer to Ethernet device structure. + * @param mac_addr + * MAC address to register. + * @param index + * MAC address index. + * @param vmdq + * VMDq pool index to associate address with (ignored). + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ + +static int hinic_mac_addr_add(struct rte_eth_dev *dev, + struct rte_ether_addr *mac_addr, uint32_t index, + __rte_unused uint32_t vmdq) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + unsigned int i; + u16 func_id; + int ret; + + if (index >= HINIC_MAX_UC_MAC_ADDRS) { + PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range,", index); + return -EINVAL; + } + + /* First, make sure this address isn't already configured. */ + for (i = 0; (i != HINIC_MAX_UC_MAC_ADDRS); ++i) { + /* Skip this index, it's going to be reconfigured. */ + if (i == index) + continue; + + if (memcmp(&dev->data->mac_addrs[i], + mac_addr, sizeof(*mac_addr))) + continue; + + PMD_DRV_LOG(INFO, "MAC address already configured"); + return -EADDRINUSE; + } + + func_id = hinic_global_func_id(nic_dev->hwdev); + ret = hinic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id); + if (ret) + return ret; + + dev->data->mac_addrs[index] = *mac_addr; + return 0; +} + +/** + * DPDK callback to set multicast mac address + * + * @param dev + * Pointer to Ethernet device structure. + * @param mc_addr_set + * Pointer to multicast mac address + * @param nb_mc_addr + * mc addr count + * @return + * 0 on success, negative error value otherwise. + */ +static int hinic_set_mc_addr_list(struct rte_eth_dev *dev, + struct rte_ether_addr *mc_addr_set, + uint32_t nb_mc_addr) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + u16 func_id; + int ret; + u32 i; + + func_id = hinic_global_func_id(nic_dev->hwdev); + + /* delete old multi_cast addrs firstly */ + hinic_delete_mc_addr_list(nic_dev); + + if (nb_mc_addr > HINIC_MAX_MC_MAC_ADDRS) + goto allmulti; + + for (i = 0; i < nb_mc_addr; i++) { + ret = hinic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes, + 0, func_id); + /* if add mc addr failed, set all multi_cast */ + if (ret) { + hinic_delete_mc_addr_list(nic_dev); + goto allmulti; + } + + rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]); + } + + return 0; + +allmulti: + hinic_dev_allmulticast_enable(dev); + + return 0; +} static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev) { @@ -2539,6 +2732,10 @@ static void hinic_dev_close(struct rte_eth_dev *dev) .xstats_get = hinic_dev_xstats_get, .xstats_reset = hinic_dev_xstats_reset, .xstats_get_names = hinic_dev_xstats_get_names, + .mac_addr_set = hinic_set_mac_addr, + .mac_addr_remove = hinic_mac_addr_remove, + .mac_addr_add = hinic_mac_addr_add, + .set_mc_addr_list = hinic_set_mc_addr_list, }; static const struct eth_dev_ops hinic_pmd_vf_ops = { @@ -2566,6 +2763,10 @@ static void hinic_dev_close(struct rte_eth_dev *dev) .xstats_get = hinic_dev_xstats_get, .xstats_reset = hinic_dev_xstats_reset, .xstats_get_names = hinic_dev_xstats_get_names, + .mac_addr_set = hinic_set_mac_addr, + .mac_addr_remove = hinic_mac_addr_remove, + .mac_addr_add = hinic_mac_addr_add, + .set_mc_addr_list = hinic_set_mc_addr_list, }; static int hinic_func_init(struct rte_eth_dev *eth_dev) @@ -2573,6 +2774,7 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) struct rte_pci_device *pci_dev; struct rte_ether_addr *eth_addr; struct hinic_nic_dev *nic_dev; + u32 mac_size; int rc; pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); @@ -2599,7 +2801,8 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) pci_dev->addr.devid, pci_dev->addr.function); /* alloc mac_addrs */ - eth_addr = rte_zmalloc("hinic_mac", sizeof(*eth_addr), 0); + mac_size = HINIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr); + eth_addr = rte_zmalloc("hinic_mac", mac_size, 0); if (!eth_addr) { PMD_DRV_LOG(ERR, "Allocate ethernet addresses' memory failed, dev_name: %s", eth_dev->data->name); @@ -2608,6 +2811,15 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mac_addrs = eth_addr; + mac_size = HINIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr); + nic_dev->mc_list = rte_zmalloc("hinic_mc", mac_size, 0); + if (!nic_dev->mc_list) { + PMD_DRV_LOG(ERR, "Allocate mcast address' memory failed, dev_name: %s", + eth_dev->data->name); + rc = -ENOMEM; + goto mc_addr_fail; + } + /* * Pass the information to the rte_eth_dev_close() that it should also * release the private port resources. @@ -2672,6 +2884,10 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) hinic_nic_dev_destroy(eth_dev); create_nic_dev_fail: + rte_free(nic_dev->mc_list); + nic_dev->mc_list = NULL; + +mc_addr_fail: rte_free(eth_addr); eth_dev->data->mac_addrs = NULL; @@ -2716,6 +2932,8 @@ static int hinic_dev_uninit(struct rte_eth_dev *dev) dev->rx_pkt_burst = NULL; dev->tx_pkt_burst = NULL; + rte_free(nic_dev->mc_list); + rte_free(dev->data->mac_addrs); dev->data->mac_addrs = NULL; diff --git a/drivers/net/hinic/hinic_pmd_ethdev.h b/drivers/net/hinic/hinic_pmd_ethdev.h index f7a1167..b4f93ad 100644 --- a/drivers/net/hinic/hinic_pmd_ethdev.h +++ b/drivers/net/hinic/hinic_pmd_ethdev.h @@ -56,6 +56,8 @@ struct hinic_nic_dev { u32 vfta[HINIC_VFTA_SIZE]; /* VLAN bitmap */ + struct rte_ether_addr default_addr; + struct rte_ether_addr *mc_list; /* info */ unsigned int flags; struct nic_service_cap nic_cap; -- 1.8.3.1