rdma/rdma_netlink.h \
enum RDMA_NLDEV_ATTR_NDEV_INDEX \
$(AUTOCONF_OUTPUT)
+ $Q sh -- '$<' '$@' \
+ HAVE_IFLA_NUM_VF \
+ linux/if_link.h \
+ enum IFLA_NUM_VF \
+ $(AUTOCONF_OUTPUT)
+ $Q sh -- '$<' '$@' \
+ HAVE_IFLA_EXT_MASK \
+ linux/if_link.h \
+ enum IFLA_EXT_MASK \
+ $(AUTOCONF_OUTPUT)
$Q sh -- '$<' '$@' \
HAVE_IFLA_PHYS_SWITCH_ID \
linux/if_link.h \
'ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT' ],
[ 'HAVE_ETHTOOL_LINK_MODE_100G', 'linux/ethtool.h',
'ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT' ],
+ [ 'HAVE_IFLA_NUM_VF', 'linux/if_link.h',
+ 'IFLA_NUM_VF' ],
+ [ 'HAVE_IFLA_EXT_MASK', 'linux/if_link.h',
+ 'IFLA_EXT_MASK' ],
[ 'HAVE_IFLA_PHYS_SWITCH_ID', 'linux/if_link.h',
'IFLA_PHYS_SWITCH_ID' ],
[ 'HAVE_IFLA_PHYS_PORT_NAME', 'linux/if_link.h',
#include <errno.h>
#include <net/if.h>
#include <sys/mman.h>
-#include <linux/netlink.h>
#include <linux/rtnetlink.h>
/* Verbs header. */
priv->nl_socket_route = mlx5_nl_init(NETLINK_ROUTE);
priv->nl_sn = 0;
priv->representor = !!switch_info->representor;
+ priv->master = !!switch_info->master;
priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
- priv->representor_id =
- switch_info->representor ? switch_info->port_name : -1;
+ /*
+ * Currently we support single E-Switch per PF configurations
+ * only and vport_id field contains the vport index for
+ * associated VF, which is deduced from representor port name.
+ * For exapmple, let's have the IB device port 10, it has
+ * attached network device eth0, which has port name attribute
+ * pf0vf2, we can deduce the VF number as 2, and set vport index
+ * as 3 (2+1). This assigning schema should be changed if the
+ * multiple E-Switch instances per PF configurations or/and PCI
+ * subfunctions are added.
+ */
+ priv->vport_id = switch_info->representor ?
+ switch_info->port_name + 1 : -1;
+ /* representor_id field keeps the unmodified port/VF index. */
+ priv->representor_id = switch_info->representor ?
+ switch_info->port_name : -1;
/*
* Look for sibling devices in order to reuse their switch domain
* if any, otherwise allocate one.
uint16_t mtu; /* Configured MTU. */
unsigned int isolated:1; /* Whether isolated mode is enabled. */
unsigned int representor:1; /* Device is a port representor. */
+ unsigned int master:1; /* Device is a E-Switch master. */
uint16_t domain_id; /* Switch domain identifier. */
+ uint16_t vport_id; /* Associated VF vport index (if any). */
int32_t representor_id; /* Port representor identifier. */
/* RX/TX queues. */
unsigned int rxqs_n; /* RX queues array size. */
.port_name = 0,
.switch_id = 0,
};
+ DIR *dir;
bool port_name_set = false;
bool port_switch_id_set = false;
+ bool device_dir = false;
char c;
int ret;
ifname);
MKSTR(phys_switch_id, "/sys/class/net/%s/phys_switch_id",
ifname);
+ MKSTR(pci_device, "/sys/class/net/%s/device",
+ ifname);
file = fopen(phys_port_name, "rb");
if (file != NULL) {
fscanf(file, "%" SCNx64 "%c", &data.switch_id, &c) == 2 &&
c == '\n';
fclose(file);
- data.master = port_switch_id_set && !port_name_set;
- data.representor = port_switch_id_set && port_name_set;
+ dir = opendir(pci_device);
+ if (dir != NULL) {
+ closedir(dir);
+ device_dir = true;
+ }
+ data.master = port_switch_id_set && (!port_name_set || device_dir);
+ data.representor = port_switch_id_set && port_name_set && !device_dir;
*info = data;
+ assert(!(data.master && data.representor));
+ if (data.master && data.representor) {
+ DRV_LOG(ERR, "ifindex %u device is recognized as master"
+ " and as representor", ifindex);
+ rte_errno = ENODEV;
+ return -rte_errno;
+ }
return 0;
}
#endif
/* These are normally found in linux/if_link.h. */
+#ifndef HAVE_IFLA_NUM_VF
+#define IFLA_NUM_VF 21
+#endif
+#ifndef HAVE_IFLA_EXT_MASK
+#define IFLA_EXT_MASK 29
+#endif
#ifndef HAVE_IFLA_PHYS_SWITCH_ID
#define IFLA_PHYS_SWITCH_ID 36
#endif
size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));
bool port_name_set = false;
bool switch_id_set = false;
+ bool num_vf_set = false;
if (nh->nlmsg_type != RTM_NEWLINK)
goto error;
if (ra->rta_len > nh->nlmsg_len - off)
goto error;
switch (ra->rta_type) {
+ case IFLA_NUM_VF:
+ num_vf_set = true;
+ break;
case IFLA_PHYS_PORT_NAME:
port_name_set =
mlx5_translate_port_name((char *)payload,
}
off += RTA_ALIGN(ra->rta_len);
}
- info.master = switch_id_set && !port_name_set;
- info.representor = switch_id_set && port_name_set;
+ if (switch_id_set) {
+ if (info.port_name_new) {
+ /* New representors naming schema. */
+ if (port_name_set) {
+ info.master = (info.port_name == -1);
+ info.representor = (info.port_name != -1);
+ }
+ } else {
+ /* Legacy representors naming schema. */
+ info.master = (!port_name_set || num_vf_set);
+ info.representor = port_name_set && !num_vf_set;
+ }
+ }
+ assert(!(info.master && info.representor));
memcpy(arg, &info, sizeof(info));
return 0;
error:
struct {
struct nlmsghdr nh;
struct ifinfomsg info;
+ struct rtattr rta;
+ uint32_t extmask;
} req = {
.nh = {
- .nlmsg_len = NLMSG_LENGTH(sizeof(req.info)),
+ .nlmsg_len = NLMSG_LENGTH
+ (sizeof(req.info) +
+ RTA_LENGTH(sizeof(uint32_t))),
.nlmsg_type = RTM_GETLINK,
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
},
.ifi_family = AF_UNSPEC,
.ifi_index = ifindex,
},
+ .rta = {
+ .rta_type = IFLA_EXT_MASK,
+ .rta_len = RTA_LENGTH(sizeof(int32_t)),
+ },
+ .extmask = RTE_LE32(1),
};
int ret;
ret = mlx5_nl_send(nl, &req.nh, seq);
if (ret >= 0)
ret = mlx5_nl_recv(nl, seq, mlx5_nl_switch_info_cb, info);
+ if (info->master && info->representor) {
+ DRV_LOG(ERR, "ifindex %u device is recognized as master"
+ " and as representor", ifindex);
+ rte_errno = ENODEV;
+ ret = -rte_errno;
+ }
return ret;
}