net/mlx5: set VF MAC address from host
authorRaslan Darawsheh <rasland@mellanox.com>
Mon, 11 Nov 2019 11:40:20 +0000 (11:40 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 11 Nov 2019 15:47:17 +0000 (16:47 +0100)
Allow to configure the default MAC address of a VF
via its representor port in the host.

An API was proposed to specify explicitly the VF as a
target: https://patches.dpdk.org/patch/62176/

It has been rejected by the technical board in order to
keep compatibility with behavior in Intel PMDs.
http://mails.dpdk.org/archives/dev/2019-November/150588.html

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Signed-off-by: Raslan Darawsheh <rasland@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
drivers/net/mlx5/mlx5.h
drivers/net/mlx5/mlx5_mac.c
drivers/net/mlx5/mlx5_nl.c

index feac5a3..511463a 100644 (file)
@@ -995,6 +995,8 @@ int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
 int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
 unsigned int mlx5_nl_portnum(int nl, const char *name);
 unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);
+int mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
+                              struct rte_ether_addr *mac, int vf_index);
 int mlx5_nl_switch_info(int nl, unsigned int ifindex,
                        struct mlx5_switch_info *info);
 
index 0ffef5c..7bdaa2a 100644 (file)
@@ -197,6 +197,26 @@ mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
 int
 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 {
+       uint16_t port_id;
+       struct mlx5_priv *priv = dev->data->dev_private;
+
+       /* Configuring the VF instead of its representor. */
+       if (priv->representor) {
+               DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address",
+                       dev->data->port_id);
+               RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) {
+                       priv = rte_eth_devices[port_id].data->dev_private;
+                       if (priv->master == 1) {
+                               priv = dev->data->dev_private;
+                               return mlx5_nl_vf_mac_addr_modify
+                                       (&rte_eth_devices[port_id],
+                                        mac_addr, priv->representor_id);
+                       }
+               }
+               rte_errno = -ENOTSUP;
+               return rte_errno;
+       }
+
        DRV_LOG(DEBUG, "port %u setting primary MAC address",
                dev->data->port_id);
        return mlx5_mac_addr_add(dev, mac_addr, 0, 0);
index 3e073c6..e7ba034 100644 (file)
 #define MLX5_NDA_RTA(r) \
        ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
 #endif
-
+/*
+ * Define NLMSG_TAIL as defined in iproute2 sources.
+ *
+ * see in iproute2 sources file include/libnetlink.h
+ */
+#ifndef NLMSG_TAIL
+#define NLMSG_TAIL(nmsg) \
+       ((struct rtattr *)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+#endif
 /*
  * The following definitions are normally found in rdma/rdma_netlink.h,
  * however they are so recent that most systems do not expose them yet.
@@ -493,6 +501,94 @@ error:
        return -rte_errno;
 }
 
+/**
+ * Modify the VF MAC address neighbour table with Netlink.
+ *
+ * @param dev
+ *    Pointer to Ethernet device.
+ * @param mac
+ *    MAC address to consider.
+ * @param vf_index
+ *    VF index.
+ *
+ * @return
+ *    0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
+                          struct rte_ether_addr *mac, int vf_index)
+{
+       int fd, ret;
+       struct mlx5_priv *priv = dev->data->dev_private;
+       unsigned int iface_idx = mlx5_ifindex(dev);
+       struct {
+               struct nlmsghdr hdr;
+               struct ifinfomsg ifm;
+               struct rtattr vf_list_rta;
+               struct rtattr vf_info_rta;
+               struct rtattr vf_mac_rta;
+               struct ifla_vf_mac ivm;
+       } req = {
+               .hdr = {
+                       .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+                       .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+                       .nlmsg_type = RTM_BASE,
+               },
+               .ifm = {
+                       .ifi_index = iface_idx,
+               },
+               .vf_list_rta = {
+                       .rta_type = IFLA_VFINFO_LIST,
+                       .rta_len = RTA_ALIGN(RTA_LENGTH(0)),
+               },
+               .vf_info_rta = {
+                       .rta_type = IFLA_VF_INFO,
+                       .rta_len = RTA_ALIGN(RTA_LENGTH(0)),
+               },
+               .vf_mac_rta = {
+                       .rta_type = IFLA_VF_MAC,
+               },
+       };
+       uint32_t sn = priv->nl_sn++;
+       struct ifla_vf_mac ivm = {
+               .vf = vf_index,
+       };
+
+       memcpy(&ivm.mac, mac, RTE_ETHER_ADDR_LEN);
+       memcpy(RTA_DATA(&req.vf_mac_rta), &ivm, sizeof(ivm));
+
+       req.vf_mac_rta.rta_len = RTA_LENGTH(sizeof(ivm));
+       req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
+               RTA_ALIGN(req.vf_list_rta.rta_len) +
+               RTA_ALIGN(req.vf_info_rta.rta_len) +
+               RTA_ALIGN(req.vf_mac_rta.rta_len);
+       req.vf_list_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),
+                                              &req.vf_list_rta);
+       req.vf_info_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),
+                                              &req.vf_info_rta);
+
+       fd = priv->nl_socket_route;
+       if (fd < 0)
+               return -1;
+       ret = mlx5_nl_send(fd, &req.hdr, sn);
+       if (ret < 0)
+               goto error;
+       ret = mlx5_nl_recv(fd, sn, NULL, NULL);
+       if (ret < 0)
+               goto error;
+       return 0;
+error:
+       DRV_LOG(ERR,
+               "representor %u cannot set VF MAC address "
+               "%02X:%02X:%02X:%02X:%02X:%02X : %s",
+               vf_index,
+               mac->addr_bytes[0], mac->addr_bytes[1],
+               mac->addr_bytes[2], mac->addr_bytes[3],
+               mac->addr_bytes[4], mac->addr_bytes[5],
+               strerror(rte_errno));
+       return -rte_errno;
+}
+
 /**
  * Add a MAC address.
  *