From: Robin Jarry <rjarry@redhat.com>
To: dev@dpdk.org, Stephen Hemminger <stephen@networkplumber.org>
Subject: [PATCH dpdk v2 1/3] net/tap: add netlink helpers
Date: Mon, 27 Oct 2025 19:19:28 +0100 [thread overview]
Message-ID: <20251027181926.489642-6-rjarry@redhat.com> (raw)
In-Reply-To: <20251027181926.489642-5-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..0682ba87e0da 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_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_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_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_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_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..b85be166245e 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_flags(int nlsk_fd, unsigned int ifindex, unsigned int *flags);
+int tap_nl_set_flags(int nlsk_fd, unsigned int ifindex, unsigned int flags, int set);
+int tap_nl_set_mtu(int nlsk_fd, unsigned int ifindex, unsigned int mtu);
+int tap_nl_set_mac(int nlsk_fd, unsigned int ifindex, const struct rte_ether_addr *mac);
+int tap_nl_get_mac(int nlsk_fd, unsigned int ifindex, struct rte_ether_addr *mac);
+
#endif /* _TAP_NETLINK_H_ */
--
2.51.0
next prev parent reply other threads:[~2025-10-27 18:19 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 ` [PATCH dpdk 1/4] net/tap: add netlink helpers Robin Jarry
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 ` Robin Jarry [this message]
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=20251027181926.489642-6-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).