Skip to content

Commit

Permalink
common/mlx5: add Netlink event helpers
Browse files Browse the repository at this point in the history
[ upstream commit be66461 ]

Introduce mlx5_nl_read_events() to read Netlink events
(technically, messages) from a socket that was configured
to listen for them via a new mlx5_nl_init() parameter.
Add mlx5_nl_parse_link_status_update() helper
to extract information from link-related events.
This patch is a shared base for later fixes.

Signed-off-by: Dmitry Kozlyuk <dkozlyuk@nvidia.com>
Reviewed-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
  • Loading branch information
dkozlyuk authored and bluca committed Mar 9, 2022
1 parent 63030f8 commit cd135f6
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 8 deletions.
102 changes: 101 additions & 1 deletion drivers/common/mlx5/linux/mlx5_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,19 +180,22 @@ uint32_t atomic_sn;
*
* @param protocol
* Netlink protocol (e.g. NETLINK_ROUTE, NETLINK_RDMA).
* @param groups
* Groups to listen (e.g. RTMGRP_LINK), can be 0.
*
* @return
* A file descriptor on success, a negative errno value otherwise and
* rte_errno is set.
*/
int
mlx5_nl_init(int protocol)
mlx5_nl_init(int protocol, int groups)
{
int fd;
int buf_size;
socklen_t opt_size;
struct sockaddr_nl local = {
.nl_family = AF_NETLINK,
.nl_groups = groups,
};
int ret;

Expand Down Expand Up @@ -1798,3 +1801,100 @@ mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,
/* Now, need to reload the driver. */
return mlx5_nl_driver_reload(nlsk_fd, family_id, pci_addr);
}

/**
* Try to parse a Netlink message as a link status update.
*
* @param hdr
* Netlink message header.
* @param[out] ifindex
* Index of the updated interface.
*
* @return
* 0 on success, negative on failure.
*/
int
mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex)
{
struct ifinfomsg *info;

switch (hdr->nlmsg_type) {
case RTM_NEWLINK:
case RTM_DELLINK:
case RTM_GETLINK:
case RTM_SETLINK:
info = NLMSG_DATA(hdr);
*ifindex = info->ifi_index;
return 0;
}
return -1;
}

/**
* Read pending events from a Netlink socket.
*
* @param nlsk_fd
* Netlink socket.
* @param cb
* Callback invoked for each of the events.
* @param cb_arg
* User data for the callback.
*
* @return
* 0 on success, including the case when there are no events.
* Negative on failure and rte_errno is set.
*/
int
mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg)
{
char buf[8192];
struct sockaddr_nl addr;
struct iovec iov = {
.iov_base = buf,
.iov_len = sizeof(buf),
};
struct msghdr msg = {
.msg_name = &addr,
.msg_namelen = sizeof(addr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
struct nlmsghdr *hdr;
ssize_t size;

while (1) {
size = recvmsg(nlsk_fd, &msg, MSG_DONTWAIT);
if (size < 0) {
if (errno == EAGAIN)
return 0;
if (errno == EINTR)
continue;
DRV_LOG(DEBUG, "Failed to receive netlink message: %s",
strerror(errno));
rte_errno = errno;
return -rte_errno;
}
hdr = (struct nlmsghdr *)buf;
while (size >= (ssize_t)sizeof(*hdr)) {
ssize_t msg_len = hdr->nlmsg_len;
ssize_t data_len = msg_len - sizeof(*hdr);
ssize_t aligned_len;

if (data_len < 0) {
DRV_LOG(DEBUG, "Netlink message too short");
rte_errno = EINVAL;
return -rte_errno;
}
aligned_len = NLMSG_ALIGN(msg_len);
if (aligned_len > size) {
DRV_LOG(DEBUG, "Netlink message too long");
rte_errno = EINVAL;
return -rte_errno;
}
cb(hdr, cb_arg);
hdr = RTE_PTR_ADD(hdr, aligned_len);
size -= aligned_len;
}
}
return 0;
}
8 changes: 7 additions & 1 deletion drivers/common/mlx5/linux/mlx5_nl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "mlx5_common.h"

typedef void (mlx5_nl_event_cb)(struct nlmsghdr *hdr, void *user_data);

/* VLAN netdev for VLAN workaround. */
struct mlx5_nl_vlan_dev {
Expand All @@ -30,7 +31,7 @@ struct mlx5_nl_vlan_vmwa_context {
};

__rte_internal
int mlx5_nl_init(int protocol);
int mlx5_nl_init(int protocol, int groups);
__rte_internal
int mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,
struct rte_ether_addr *mac, uint32_t index);
Expand Down Expand Up @@ -77,4 +78,9 @@ __rte_internal
int mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,
int enable);

__rte_internal
int mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg);
__rte_internal
int mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex);

#endif /* RTE_PMD_MLX5_NL_H_ */
2 changes: 2 additions & 0 deletions drivers/common/mlx5/version.map
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ INTERNAL {
mlx5_nl_mac_addr_flush;
mlx5_nl_mac_addr_remove;
mlx5_nl_mac_addr_sync;
mlx5_nl_parse_link_status_update;
mlx5_nl_portnum;
mlx5_nl_promisc;
mlx5_nl_read_events;
mlx5_nl_switch_info;
mlx5_nl_vf_mac_addr_modify;
mlx5_nl_vlan_vmwa_create;
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/mlx5/linux/mlx5_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
priv->pci_dev = spawn->pci_dev;
priv->mtu = RTE_ETHER_MTU;
/* Some internal functions rely on Netlink sockets, open them now. */
priv->nl_socket_rdma = mlx5_nl_init(NETLINK_RDMA);
priv->nl_socket_route = mlx5_nl_init(NETLINK_ROUTE);
priv->nl_socket_rdma = mlx5_nl_init(NETLINK_RDMA, 0);
priv->nl_socket_route = mlx5_nl_init(NETLINK_ROUTE, 0);
priv->representor = !!switch_info->representor;
priv->master = !!switch_info->master;
priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
Expand Down Expand Up @@ -1877,8 +1877,8 @@ mlx5_os_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
* matching ones, gathering into the list.
*/
struct ibv_device *ibv_match[ret + 1];
int nl_route = mlx5_nl_init(NETLINK_ROUTE);
int nl_rdma = mlx5_nl_init(NETLINK_RDMA);
int nl_route = mlx5_nl_init(NETLINK_ROUTE, 0);
int nl_rdma = mlx5_nl_init(NETLINK_RDMA, 0);
unsigned int i;

while (ret-- > 0) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/mlx5/linux/mlx5_vlan_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ mlx5_vlan_vmwa_init(struct rte_eth_dev *dev, uint32_t ifindex)
return NULL;
}
rte_spinlock_init(&vmwa->sl);
vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE);
vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE, 0);
if (vmwa->nl_socket < 0) {
DRV_LOG(WARNING,
"Can not create Netlink socket"
Expand Down
2 changes: 1 addition & 1 deletion drivers/vdpa/mlx5/mlx5_vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ mlx5_vdpa_get_ib_device_match(struct rte_pci_addr *addr)
static int
mlx5_vdpa_nl_roce_disable(const char *addr)
{
int nlsk_fd = mlx5_nl_init(NETLINK_GENERIC);
int nlsk_fd = mlx5_nl_init(NETLINK_GENERIC, 0);
int devlink_id;
int enable;
int ret;
Expand Down

0 comments on commit cd135f6

Please sign in to comment.