From 0d1d73170820aa2248d467628ef39f813c5189bb Mon Sep 17 00:00:00 2001 From: Raslan Darawsheh Date: Mon, 11 Nov 2019 11:40:20 +0000 Subject: [PATCH] net/mlx5: set VF MAC address from host 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 Signed-off-by: Raslan Darawsheh Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_mac.c | 20 ++++++++ drivers/net/mlx5/mlx5_nl.c | 98 ++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index feac5a39d0..511463a6c9 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -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); diff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c index 0ffef5c5db..7bdaa2a392 100644 --- a/drivers/net/mlx5/mlx5_mac.c +++ b/drivers/net/mlx5/mlx5_mac.c @@ -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); diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c index 3e073c6e29..e7ba03471d 100644 --- a/drivers/net/mlx5/mlx5_nl.c +++ b/drivers/net/mlx5/mlx5_nl.c @@ -42,7 +42,15 @@ #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 @@ mlx5_nl_mac_addr_modify(struct rte_eth_dev *dev, struct rte_ether_addr *mac, 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. *