DPDK patches and discussions
 help / color / mirror / Atom feed
From: Robin Jarry <rjarry@redhat.com>
To: dev@dpdk.org, Stephen Hemminger <stephen@networkplumber.org>
Subject: [PATCH dpdk 1/4] net/tap: add netlink helpers
Date: Mon, 27 Oct 2025 16:37:52 +0100	[thread overview]
Message-ID: <20251027153750.445275-7-rjarry@redhat.com> (raw)
In-Reply-To: <20251027153750.445275-6-rjarry@redhat.com>

Add functions to get/set link flags, MAC address, and MTU using netlink
RTM_GETLINK/RTM_SETLINK messages instead of ioctl.

These will be used in the next commits for a more robust solution that
does not rely on interface names.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 drivers/net/tap/tap_netlink.c | 291 ++++++++++++++++++++++++++++++++++
 drivers/net/tap/tap_netlink.h |  10 +-
 2 files changed, 299 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tap/tap_netlink.c b/drivers/net/tap/tap_netlink.c
index 5ff60f41d426..20bdbe5f7df8 100644
--- a/drivers/net/tap/tap_netlink.c
+++ b/drivers/net/tap/tap_netlink.c
@@ -6,6 +6,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <linux/netlink.h>
+#include <net/if.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <unistd.h>
@@ -411,3 +412,293 @@ tap_nlattr_nested_finish(struct tap_nlmsg *msg)
 
 	rte_free(tail);
 }
+
+/**
+ * Helper structure to pass data between netlink request and callback
+ */
+struct link_info_ctx {
+	struct ifinfomsg *info;
+	struct rte_ether_addr *mac;
+	unsigned int *flags;
+	unsigned int ifindex;
+	int found;
+};
+
+/**
+ * Callback to extract link information from RTM_GETLINK response
+ */
+static int
+tap_nl_link_cb(struct nlmsghdr *nh, void *arg)
+{
+	struct link_info_ctx *ctx = arg;
+	struct ifinfomsg *ifi = NLMSG_DATA(nh);
+	struct rtattr *rta;
+	int rta_len;
+
+	if (nh->nlmsg_type != RTM_NEWLINK)
+		return 0;
+
+	/* Check if this is the interface we're looking for */
+	if (ifi->ifi_index != (int)ctx->ifindex)
+		return 0;
+
+	ctx->found = 1;
+
+	/* Copy basic info if requested */
+	if (ctx->info)
+		*ctx->info = *ifi;
+
+	/* Extract flags if requested */
+	if (ctx->flags)
+		*ctx->flags = ifi->ifi_flags;
+
+	/* Parse attributes for MAC address if requested */
+	if (ctx->mac) {
+		rta = IFLA_RTA(ifi);
+		rta_len = IFLA_PAYLOAD(nh);
+
+		for (; RTA_OK(rta, rta_len); rta = RTA_NEXT(rta, rta_len)) {
+			if (rta->rta_type == IFLA_ADDRESS) {
+				if (RTA_PAYLOAD(rta) >= RTE_ETHER_ADDR_LEN)
+					memcpy(ctx->mac, RTA_DATA(rta),
+					       RTE_ETHER_ADDR_LEN);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Get interface flags by ifindex
+ *
+ * @param nlsk_fd
+ *   Netlink socket file descriptor
+ * @param ifindex
+ *   Interface index
+ * @param flags
+ *   Pointer to store interface flags
+ *
+ * @return
+ *   0 on success, -1 on error
+ */
+int
+tap_nl_get_link_flags(int nlsk_fd, unsigned int ifindex, unsigned int *flags)
+{
+	struct {
+		struct nlmsghdr nh;
+		struct ifinfomsg ifi;
+	} req = {
+		.nh = {
+			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_type = RTM_GETLINK,
+			.nlmsg_flags = NLM_F_REQUEST,
+		},
+		.ifi = {
+			.ifi_family = AF_UNSPEC,
+			.ifi_index = ifindex,
+		},
+	};
+	struct link_info_ctx ctx = {
+		.flags = flags,
+		.ifindex = ifindex,
+		.found = 0,
+	};
+
+	if (tap_nl_send(nlsk_fd, &req.nh) < 0)
+		return -1;
+
+	if (tap_nl_recv(nlsk_fd, tap_nl_link_cb, &ctx) < 0)
+		return -1;
+
+	if (!ctx.found) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Set interface flags by ifindex
+ *
+ * @param nlsk_fd
+ *   Netlink socket file descriptor
+ * @param ifindex
+ *   Interface index
+ * @param flags
+ *   Flags to set/unset
+ * @param set
+ *   1 to set flags, 0 to unset them
+ *
+ * @return
+ *   0 on success, -1 on error
+ */
+int
+tap_nl_set_link_flags(int nlsk_fd, unsigned int ifindex, unsigned int flags, int set)
+{
+	struct {
+		struct nlmsghdr nh;
+		struct ifinfomsg ifi;
+	} req = {
+		.nh = {
+			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_type = RTM_SETLINK,
+			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+		},
+		.ifi = {
+			.ifi_family = AF_UNSPEC,
+			.ifi_index = ifindex,
+			.ifi_flags = set ? flags : 0,
+			.ifi_change = flags,  /* mask of flags to change */
+		},
+	};
+
+	if (tap_nl_send(nlsk_fd, &req.nh) < 0)
+		return -1;
+
+	return tap_nl_recv_ack(nlsk_fd);
+}
+
+/**
+ * Set interface MTU by ifindex
+ *
+ * @param nlsk_fd
+ *   Netlink socket file descriptor
+ * @param ifindex
+ *   Interface index
+ * @param mtu
+ *   New MTU value
+ *
+ * @return
+ *   0 on success, -1 on error
+ */
+int
+tap_nl_set_link_mtu(int nlsk_fd, unsigned int ifindex, unsigned int mtu)
+{
+	struct {
+		struct nlmsghdr nh;
+		struct ifinfomsg ifi;
+		char buf[64];
+	} req = {
+		.nh = {
+			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_type = RTM_SETLINK,
+			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+		},
+		.ifi = {
+			.ifi_family = AF_UNSPEC,
+			.ifi_index = ifindex,
+		},
+	};
+	struct rtattr *rta;
+
+	/* Add MTU attribute */
+	rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.nh.nlmsg_len));
+	rta->rta_type = IFLA_MTU;
+	rta->rta_len = RTA_LENGTH(sizeof(mtu));
+	memcpy(RTA_DATA(rta), &mtu, sizeof(mtu));
+	req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + RTA_ALIGN(rta->rta_len);
+
+	if (tap_nl_send(nlsk_fd, &req.nh) < 0)
+		return -1;
+
+	return tap_nl_recv_ack(nlsk_fd);
+}
+
+/**
+ * Get interface MAC address by ifindex
+ *
+ * @param nlsk_fd
+ *   Netlink socket file descriptor
+ * @param ifindex
+ *   Interface index
+ * @param mac
+ *   Pointer to store MAC address
+ *
+ * @return
+ *   0 on success, -1 on error
+ */
+int
+tap_nl_get_link_mac(int nlsk_fd, unsigned int ifindex, struct rte_ether_addr *mac)
+{
+	struct {
+		struct nlmsghdr nh;
+		struct ifinfomsg ifi;
+	} req = {
+		.nh = {
+			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_type = RTM_GETLINK,
+			.nlmsg_flags = NLM_F_REQUEST,
+		},
+		.ifi = {
+			.ifi_family = AF_UNSPEC,
+			.ifi_index = ifindex,
+		},
+	};
+	struct link_info_ctx ctx = {
+		.mac = mac,
+		.ifindex = ifindex,
+		.found = 0,
+	};
+
+	if (tap_nl_send(nlsk_fd, &req.nh) < 0)
+		return -1;
+
+	if (tap_nl_recv(nlsk_fd, tap_nl_link_cb, &ctx) < 0)
+		return -1;
+
+	if (!ctx.found) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Set interface MAC address by ifindex
+ *
+ * @param nlsk_fd
+ *   Netlink socket file descriptor
+ * @param ifindex
+ *   Interface index
+ * @param mac
+ *   New MAC address
+ *
+ * @return
+ *   0 on success, -1 on error
+ */
+int
+tap_nl_set_link_mac(int nlsk_fd, unsigned int ifindex, const struct rte_ether_addr *mac)
+{
+	struct {
+		struct nlmsghdr nh;
+		struct ifinfomsg ifi;
+		char buf[64];
+	} req = {
+		.nh = {
+			.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlmsg_type = RTM_SETLINK,
+			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+		},
+		.ifi = {
+			.ifi_family = AF_UNSPEC,
+			.ifi_index = ifindex,
+		},
+	};
+	struct rtattr *rta;
+
+	/* Add MAC address attribute */
+	rta = (struct rtattr *)((char *)&req + NLMSG_ALIGN(req.nh.nlmsg_len));
+	rta->rta_type = IFLA_ADDRESS;
+	rta->rta_len = RTA_LENGTH(RTE_ETHER_ADDR_LEN);
+	memcpy(RTA_DATA(rta), mac, RTE_ETHER_ADDR_LEN);
+	req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + RTA_ALIGN(rta->rta_len);
+
+	if (tap_nl_send(nlsk_fd, &req.nh) < 0)
+		return -1;
+
+	return tap_nl_recv_ack(nlsk_fd);
+}
diff --git a/drivers/net/tap/tap_netlink.h b/drivers/net/tap/tap_netlink.h
index 5eff6edbb1cd..e9c9e5dce553 100644
--- a/drivers/net/tap/tap_netlink.h
+++ b/drivers/net/tap/tap_netlink.h
@@ -6,12 +6,11 @@
 #ifndef _TAP_NETLINK_H_
 #define _TAP_NETLINK_H_
 
-#include <ctype.h>
 #include <inttypes.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
-#include <stdio.h>
 
+#include <rte_ether.h>
 #include <rte_log.h>
 
 #define NLMSG_BUF 512
@@ -39,4 +38,11 @@ void tap_nlattr_add32(struct tap_nlmsg *msg, unsigned short type, uint32_t data)
 int tap_nlattr_nested_start(struct tap_nlmsg *msg, uint16_t type);
 void tap_nlattr_nested_finish(struct tap_nlmsg *msg);
 
+/* Link management functions using netlink */
+int tap_nl_get_link_flags(int nlsk_fd, unsigned int ifindex, unsigned int *flags);
+int tap_nl_set_link_flags(int nlsk_fd, unsigned int ifindex, unsigned int flags, int set);
+int tap_nl_set_link_mtu(int nlsk_fd, unsigned int ifindex, unsigned int mtu);
+int tap_nl_set_link_mac(int nlsk_fd, unsigned int ifindex, const struct rte_ether_addr *mac);
+int tap_nl_get_link_mac(int nlsk_fd, unsigned int ifindex, struct rte_ether_addr *mac);
+
 #endif /* _TAP_NETLINK_H_ */
-- 
2.51.0


  reply	other threads:[~2025-10-27 15:38 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-27 15:37 [PATCH dpdk 0/4] net/tap: add network namespace support Robin Jarry
2025-10-27 15:37 ` Robin Jarry [this message]
2025-10-27 15:37 ` [PATCH dpdk 2/4] net/tap: rename internal ioctl wrapper Robin Jarry
2025-10-27 15:37 ` [PATCH dpdk 3/4] net/tap: use netlink if possible Robin Jarry
2025-10-27 16:06   ` Stephen Hemminger
2025-10-27 16:10     ` Robin Jarry
2025-10-27 16:58       ` Stephen Hemminger
2025-10-27 15:37 ` [PATCH dpdk 4/4] net/tap: detect namespace change Robin Jarry
2025-10-27 18:19 ` [PATCH dpdk v2 0/3] net/tap: add network namespace support Robin Jarry
2025-10-27 18:19   ` [PATCH dpdk v2 1/3] net/tap: add netlink helpers Robin Jarry
2025-10-27 18:19   ` [PATCH dpdk v2 2/3] net/tap: replace ioctl with netlink Robin Jarry
2025-10-27 18:19   ` [PATCH dpdk v2 3/3] net/tap: detect namespace change Robin Jarry
2025-10-27 21:55   ` [PATCH dpdk v2 0/3] net/tap: add network namespace support Stephen Hemminger
2025-10-27 22:16 ` [PATCH dpdk v3 " Robin Jarry
2025-10-27 22:16   ` [PATCH dpdk v3 1/3] net/tap: add netlink helpers Robin Jarry
2025-10-27 22:16   ` [PATCH dpdk v3 2/3] net/tap: replace ioctl with netlink Robin Jarry
2025-10-27 22:16   ` [PATCH dpdk v3 3/3] net/tap: detect namespace change Robin Jarry

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=20251027153750.445275-7-rjarry@redhat.com \
    --to=rjarry@redhat.com \
    --cc=dev@dpdk.org \
    --cc=stephen@networkplumber.org \
    /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).