patches for DPDK stable branches
 help / color / mirror / Atom feed
From: Dmitry Kozlyuk <dkozlyuk@nvidia.com>
To: <stable@dpdk.org>
Cc: Christian Ehrhardt <christian.ehrhardt@canonical.com>,
	"Viacheslav Ovsiienko" <viacheslavo@nvidia.com>
Subject: [PATCH 19.11 1/3] common/mlx5: add Netlink event helpers
Date: Fri, 11 Mar 2022 10:06:25 +0200	[thread overview]
Message-ID: <20220311080627.1195847-2-dkozlyuk@nvidia.com> (raw)
In-Reply-To: <20220311080627.1195847-1-dkozlyuk@nvidia.com>

[ upstream commit be66461cba371c3138ce942eb9fe5657f9e9a446 ]

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>
---
 drivers/net/mlx5/mlx5.c    |   8 +--
 drivers/net/mlx5/mlx5.h    |   7 ++-
 drivers/net/mlx5/mlx5_nl.c | 107 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index d9db6aa398..27e04b5d9e 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -2433,8 +2433,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->nl_sn = 0;
 	priv->representor = !!switch_info->representor;
 	priv->master = !!switch_info->master;
@@ -3105,8 +3105,8 @@ mlx5_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) {
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index b2dc9e291b..b74f1bbc83 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -12,6 +12,7 @@
 #include <limits.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <netlink/netlink.h>
 #include <sys/queue.h>
 
 /* Verbs header. */
@@ -991,7 +992,9 @@ void mlx5_mp_uninit_secondary(void);
 
 /* mlx5_nl.c */
 
-int mlx5_nl_init(int protocol);
+typedef void (mlx5_nl_event_cb)(struct nlmsghdr *hdr, void *user_data);
+
+int mlx5_nl_init(int protocol, int groups);
 int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
 			 uint32_t index);
 int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
@@ -1006,6 +1009,8 @@ 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);
+int mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg);
+int mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex);
 
 struct mlx5_vlan_vmwa_context *mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
 						   uint32_t ifindex);
diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c
index 668affb0b1..2564e8779b 100644
--- a/drivers/net/mlx5/mlx5_nl.c
+++ b/drivers/net/mlx5/mlx5_nl.c
@@ -119,19 +119,22 @@ struct mlx5_nl_ifindex_data {
  *
  * @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 sndbuf_size = MLX5_SEND_BUF_SIZE;
 	int rcvbuf_size = MLX5_RECV_BUF_SIZE;
 	struct sockaddr_nl local = {
 		.nl_family = AF_NETLINK,
+		.nl_groups = groups,
 	};
 	int ret;
 
@@ -1400,7 +1403,7 @@ mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
 			" for VLAN workaround context");
 		return NULL;
 	}
-	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"
@@ -1431,3 +1434,103 @@ void mlx5_vlan_vmwa_exit(struct mlx5_vlan_vmwa_context *vmwa)
 		close(vmwa->nl_socket);
 	rte_free(vmwa);
 }
+
+/**
+ * Try to parse a Netlink message as a link status update.
+ *
+ * @param hdr
+ *  Netlink message header.
+ * @param[out] ifindex
+ *  Index of the updated interface.
+ * @param[out] flags
+ *  New interface flags.
+ *
+ * @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;
+}
-- 
2.25.1


  reply	other threads:[~2022-03-11  8:06 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-11  8:06 [PATCH 19.11 0/3] net/mlx5: fix link state detection Dmitry Kozlyuk
2022-03-11  8:06 ` Dmitry Kozlyuk [this message]
2022-03-11  8:06 ` [PATCH 19.11 2/3] net/mlx5: fix link status change detection Dmitry Kozlyuk
2022-03-11  8:06 ` [PATCH 19.11 3/3] net/mlx5: fix initial link status detection Dmitry Kozlyuk
2022-03-11 10:06 ` [PATCH 19.11 0/3] net/mlx5: fix link state detection Christian Ehrhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220311080627.1195847-2-dkozlyuk@nvidia.com \
    --to=dkozlyuk@nvidia.com \
    --cc=christian.ehrhardt@canonical.com \
    --cc=stable@dpdk.org \
    --cc=viacheslavo@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).