net/iavf: support multicast configuration
authorWei Zhao <wei.zhao1@intel.com>
Mon, 13 Jul 2020 07:48:11 +0000 (15:48 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 18 Sep 2020 16:55:06 +0000 (18:55 +0200)
This patch enable add multicast address for iavf.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
doc/guides/nics/features/iavf.ini
drivers/net/iavf/iavf.h
drivers/net/iavf/iavf_ethdev.c
drivers/net/iavf/iavf_vchnl.c

index 2e7cea3..17f7928 100644 (file)
@@ -15,6 +15,7 @@ TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
+Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
index 9be8a23..9ad331e 100644 (file)
@@ -129,6 +129,10 @@ struct iavf_info {
        bool link_up;
        uint32_t link_speed;
 
+       /* Multicast addrs */
+       struct rte_ether_addr mc_addrs[IAVF_NUM_MACADDR_MAX];
+       uint16_t mc_addrs_num;   /* Multicast mac addresses number */
+
        struct iavf_vsi vsi;
        bool vf_reset;
        uint64_t flags;
@@ -272,4 +276,7 @@ int iavf_fdir_check(struct iavf_adapter *adapter,
                struct iavf_fdir_conf *filter);
 int iavf_add_del_rss_cfg(struct iavf_adapter *adapter,
                         struct virtchnl_rss_cfg *rss_cfg, bool add);
+int iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num, bool add);
 #endif /* _IAVF_ETHDEV_H_ */
index c3aa4cd..ae1ed58 100644 (file)
@@ -73,6 +73,9 @@ static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
                     enum rte_filter_type filter_type,
                     enum rte_filter_op filter_op,
                     void *arg);
+static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num);
 
 static const struct rte_pci_id pci_id_iavf_map[] = {
        { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },
@@ -96,6 +99,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .allmulticast_disable       = iavf_dev_allmulticast_disable,
        .mac_addr_add               = iavf_dev_add_mac_addr,
        .mac_addr_remove            = iavf_dev_del_mac_addr,
+       .set_mc_addr_list                       = iavf_set_mc_addr_list,
        .vlan_filter_set            = iavf_dev_vlan_filter_set,
        .vlan_offload_set           = iavf_dev_vlan_offload_set,
        .rx_queue_start             = iavf_dev_rx_queue_start,
@@ -122,6 +126,35 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .filter_ctrl                = iavf_dev_filter_ctrl,
 };
 
+static int
+iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num)
+{
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+       struct iavf_adapter *adapter =
+               IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+       int err;
+
+       /* flush previous addresses */
+       err = iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                       false);
+       if (err)
+               return err;
+
+       vf->mc_addrs_num = 0;
+
+       /* add new ones */
+       err = iavf_add_del_mc_addr_list(adapter, 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;
+}
+
 static int
 iavf_init_rss(struct iavf_adapter *adapter)
 {
@@ -451,6 +484,10 @@ iavf_dev_start(struct rte_eth_dev *dev)
        /* Set all mac addrs */
        iavf_add_del_all_mac_addr(adapter, true);
 
+       /* Set all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 true);
+
        if (iavf_start_queues(dev) != 0) {
                PMD_DRV_LOG(ERR, "enable queues failed");
                goto err_mac;
@@ -467,6 +504,7 @@ err_queue:
 static void
 iavf_dev_stop(struct rte_eth_dev *dev)
 {
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct rte_intr_handle *intr_handle = dev->intr_handle;
@@ -488,6 +526,11 @@ iavf_dev_stop(struct rte_eth_dev *dev)
 
        /* remove all mac addrs */
        iavf_add_del_all_mac_addr(adapter, false);
+
+       /* remove all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 false);
+
        adapter->stopped = 1;
 }
 
index 33acea5..6b57ecb 100644 (file)
@@ -1075,3 +1075,59 @@ iavf_add_del_rss_cfg(struct iavf_adapter *adapter,
 
        return err;
 }
+
+int
+iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num, bool add)
+{
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+       uint8_t cmd_buffer[sizeof(struct virtchnl_ether_addr_list) +
+               (IAVF_NUM_MACADDR_MAX * sizeof(struct virtchnl_ether_addr))];
+       struct virtchnl_ether_addr_list *list;
+       struct iavf_cmd_info args;
+       uint32_t i;
+       int err;
+
+       if (mc_addrs == NULL || mc_addrs_num == 0)
+               return 0;
+
+       if (mc_addrs_num > IAVF_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 (!IAVF_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 = IAVF_AQ_BUF_SZ;
+       err = iavf_execute_vf_cmd(adapter, &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;
+}