[dpdk-dev] [PATCH] net/i40evf: add multicast MAC address filtering

Zhang, Qi Z qi.z.zhang at intel.com
Tue Mar 27 15:51:46 CEST 2018



> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Olivier Matz
> Sent: Thursday, January 25, 2018 10:36 PM
> To: dev at dpdk.org; Xing, Beilei <beilei.xing at intel.com>; Zhang, Qi Z
> <qi.z.zhang at intel.com>; Lu, Wenzhuo <wenzhuo.lu at intel.com>
> Subject: [dpdk-dev] [PATCH] net/i40evf: add multicast MAC address filtering
> 
> 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 <olivier.matz at 6wind.com>

Acked-by: Qi Zhang <qi.z.zhang at intel.com>

Thanks for enable this!

> ---
> 
> 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



More information about the dev mailing list