From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from proxy.6wind.com (host.76.145.23.62.rev.coltfrance.com [62.23.145.76]) by dpdk.org (Postfix) with ESMTP id 8D301A499 for ; Thu, 25 Jan 2018 15:36:49 +0100 (CET) Received: from glumotte.dev.6wind.com. (unknown [10.16.0.195]) by proxy.6wind.com (Postfix) with ESMTP id C55E8127467; Thu, 25 Jan 2018 15:34:55 +0100 (CET) From: Olivier Matz To: dev@dpdk.org, Beilei Xing , Qi Zhang , Wenzhuo Lu Date: Thu, 25 Jan 2018 15:36:22 +0100 Message-Id: <20180125143622.904-1-olivier.matz@6wind.com> X-Mailer: git-send-email 2.11.0 Subject: [dpdk-dev] [PATCH] net/i40evf: add multicast MAC address filtering 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: , X-List-Received-Date: Thu, 25 Jan 2018 14:36:49 -0000 Add support the set_mc_addr_list device operation in the i40evf PMD. The configured addresses are stored in the device private area, so they can be flushed before adding new ones. Signed-off-by: Olivier Matz --- Target is v18.05. To reproduce the issue: guest (testpmd) +----------+ | | | port1 | | VF | | X | +------X---+ X +------X---+ +----------+ | X | | | | ens3f2+--------+ntfp2 | | PF | | | | | | | +----------+ +----------+ host tester (linux) node Start testpmd in guest in rx only mode: set fwd rxonly set verbose 1 start Send packets from the tester node: # broadcast packet is received arp = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(psrc='1.1.1.2', pdst='1.1.1.3') sendp(arp, iface="ntfp2") # unicast packet to the correct mac (VF) is received arp = Ether(dst='00:09:C0:38:6D:C2')/ARP(psrc='1.1.1.2', pdst='1.1.1.3') sendp(arp, iface="ntfp2") # multicast packet is not received arp = Ether(dst='33:33:00:01:00:02')/ARP(psrc='1.1.1.2', pdst='1.1.1.3') sendp(arp, iface="ntfp2") Try to add the multicast address in testpmd: mcast_addr add 1 33:33:00:01:00:02 Without the patch, it fails (ENOTSUP). With the patch, it is possible to add/remove several multicast addresses, and the multicast packets sent by the tester node are properly received. drivers/net/i40e/i40e_ethdev.h | 3 ++ drivers/net/i40e/i40e_ethdev_vf.c | 100 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 69ea6c189..83c9d3b19 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -995,6 +995,9 @@ struct i40e_vf { uint16_t promisc_flags; /* Promiscuous setting */ uint32_t vlan[I40E_VFTA_SIZE]; /* VLAN bit map */ + struct ether_addr mc_addrs[I40E_NUM_MACADDR_MAX]; /* Multicast addrs */ + uint16_t mc_addrs_num; /* Multicast mac addresses number */ + /* Event from pf */ bool dev_closed; bool link_up; diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index 6ac3f8c04..0d73c1b7f 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -130,6 +130,14 @@ static void i40evf_handle_pf_event(struct rte_eth_dev *dev, uint8_t *msg, uint16_t msglen); +static int +i40evf_add_del_mc_addr_list(struct rte_eth_dev *dev, + struct ether_addr *mc_addr_set, + uint32_t nb_mc_addr, bool add); +static int +i40evf_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, + uint32_t nb_mc_addr); + /* Default hash key buffer for RSS */ static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1]; @@ -195,6 +203,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = { .txq_info_get = i40e_txq_info_get, .mac_addr_add = i40evf_add_mac_addr, .mac_addr_remove = i40evf_del_mac_addr, + .set_mc_addr_list = i40evf_set_mc_addr_list, .reta_update = i40evf_dev_rss_reta_update, .reta_query = i40evf_dev_rss_reta_query, .rss_hash_update = i40evf_dev_rss_hash_update, @@ -2011,6 +2020,9 @@ i40evf_dev_start(struct rte_eth_dev *dev) /* Set all mac addrs */ i40evf_add_del_all_mac_addr(dev, TRUE); + /* Set all multicast addresses */ + i40evf_add_del_mc_addr_list(dev, vf->mc_addrs, vf->mc_addrs_num, + TRUE); if (i40evf_start_queues(dev) != 0) { PMD_DRV_LOG(ERR, "enable queues failed"); @@ -2035,6 +2047,8 @@ i40evf_dev_start(struct rte_eth_dev *dev) err_mac: i40evf_add_del_all_mac_addr(dev, FALSE); + i40evf_add_del_mc_addr_list(dev, vf->mc_addrs, vf->mc_addrs_num, + FALSE); err_queue: return -1; } @@ -2045,6 +2059,7 @@ i40evf_dev_stop(struct rte_eth_dev *dev) struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); @@ -2062,6 +2077,9 @@ i40evf_dev_stop(struct rte_eth_dev *dev) } /* remove all mac addrs */ i40evf_add_del_all_mac_addr(dev, FALSE); + /* remove all multicast addresses */ + i40evf_add_del_mc_addr_list(dev, vf->mc_addrs, vf->mc_addrs_num, + FALSE); hw->adapter_stopped = 1; } @@ -2676,3 +2694,85 @@ i40evf_set_default_mac_addr(struct rte_eth_dev *dev, ether_addr_copy(mac_addr, (struct ether_addr *)hw->mac.addr); } + +static int +i40evf_add_del_mc_addr_list(struct rte_eth_dev *dev, + struct ether_addr *mc_addrs, + uint32_t mc_addrs_num, bool add) +{ + struct virtchnl_ether_addr_list *list; + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + uint8_t cmd_buffer[sizeof(struct virtchnl_ether_addr_list) + + (I40E_NUM_MACADDR_MAX * sizeof(struct virtchnl_ether_addr))]; + uint32_t i; + int err; + struct vf_cmd_info args; + + if (mc_addrs == NULL || mc_addrs_num == 0) + return 0; + + if (mc_addrs_num > I40E_NUM_MACADDR_MAX) + return -EINVAL; + + list = (struct virtchnl_ether_addr_list *)cmd_buffer; + list->vsi_id = vf->vsi_res->vsi_id; + list->num_elements = mc_addrs_num; + + for (i = 0; i < mc_addrs_num; i++) { + if (!I40E_IS_MULTICAST(mc_addrs[i].addr_bytes)) { + PMD_DRV_LOG(ERR, "Invalid mac:%x:%x:%x:%x:%x:%x", + mc_addrs[i].addr_bytes[0], + mc_addrs[i].addr_bytes[1], + mc_addrs[i].addr_bytes[2], + mc_addrs[i].addr_bytes[3], + mc_addrs[i].addr_bytes[4], + mc_addrs[i].addr_bytes[5]); + return -EINVAL; + } + + memcpy(list->list[i].addr, mc_addrs[i].addr_bytes, + sizeof(list->list[i].addr)); + } + + args.ops = add ? VIRTCHNL_OP_ADD_ETH_ADDR : VIRTCHNL_OP_DEL_ETH_ADDR; + args.in_args = cmd_buffer; + args.in_args_size = sizeof(struct virtchnl_ether_addr_list) + + i * sizeof(struct virtchnl_ether_addr); + args.out_buffer = vf->aq_resp; + args.out_size = I40E_AQ_BUF_SZ; + err = i40evf_execute_vf_cmd(dev, &args); + if (err) { + PMD_DRV_LOG(ERR, "fail to execute command %s", + add ? "OP_ADD_ETH_ADDR" : "OP_DEL_ETH_ADDR"); + return err; + } + + return 0; +} + +static int +i40evf_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addrs, + uint32_t mc_addrs_num) +{ + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + int err; + + /* flush previous addresses */ + err = i40evf_add_del_mc_addr_list(dev, vf->mc_addrs, vf->mc_addrs_num, + FALSE); + if (err) + return err; + + vf->mc_addrs_num = 0; + + /* add new ones */ + err = i40evf_add_del_mc_addr_list(dev, mc_addrs, mc_addrs_num, + TRUE); + if (err) + return err; + + vf->mc_addrs_num = mc_addrs_num; + memcpy(vf->mc_addrs, mc_addrs, mc_addrs_num * sizeof(*mc_addrs)); + + return 0; +} -- 2.11.0