When pasta starts without a template interface (-I), it creates the tap
device with the default name (tap0). Later, when late binding discovers
the actual template interface, we now rename the device to match it.
This ensures the namespace interface has the expected name, matching
the discovered host interface.
Key changes:
- Add nl_link_rename() function to rename network interfaces
- When late binding triggers with the default TAP name, bring it
down, rename it to match the discovered interface, then bring it up
Signed-off-by: Jon Maloy
---
netlink.c | 37 +++++++++++++++++++++++++++++++++++++
tap.c | 27 +++++++++++++++++++++++++++
tap.h | 1 +
3 files changed, 65 insertions(+)
diff --git a/netlink.c b/netlink.c
index de04fb7..71089ab 100644
--- a/netlink.c
+++ b/netlink.c
@@ -44,6 +44,8 @@
/* Default namespace interface name from conf.c */
extern const char *pasta_default_ifn;
+static int nl_link_rename(int s, unsigned int ifi, const char *name);
+
/* Same as RTA_NEXT() but for nexthops: RTNH_NEXT() doesn't take 'attrlen' */
#define RTNH_NEXT_AND_DEC(rtnh, attrlen) \
((attrlen) -= RTNH_ALIGN((rtnh)->rtnh_len), RTNH_NEXT(rtnh))
@@ -315,6 +317,14 @@ static void nl_linkaddr_host_msg_read(struct ctx *c, const struct nlmsghdr *nh)
}
late_binding = true;
+ /* Rename interface if it is still using default name */
+ if (is_default && strcmp(ifname, pasta_default_ifn)) {
+ nl_link_set_flags(nl_sock_ns, c->pasta_ifi,
+ 0, IFF_UP);
+ nl_link_rename(nl_sock_ns, c->pasta_ifi, ifname);
+ debug("Renamed tap: %s -> %s",
+ pasta_default_ifn, ifname);
+ }
if (is_default)
snprintf(c->pasta_ifn, sizeof(c->pasta_ifn),
"%s", ifname);
@@ -1943,6 +1953,33 @@ int nl_link_set_flags(int s, unsigned int ifi,
return nl_do(s, &req, RTM_NEWLINK, 0, sizeof(req));
}
+/**
+ * nl_link_rename() - Rename a network interface
+ * @s: Netlink socket
+ * @ifi: Interface index
+ * @name: New interface name
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int nl_link_rename(int s, unsigned int ifi, const char *name)
+{
+ struct req_t {
+ struct nlmsghdr nlh;
+ struct ifinfomsg ifm;
+ struct rtattr rta;
+ char name[IFNAMSIZ];
+ } req = {
+ .ifm.ifi_family = AF_UNSPEC,
+ .ifm.ifi_index = ifi,
+ .rta.rta_type = IFLA_IFNAME,
+ .rta.rta_len = RTA_LENGTH(IFNAMSIZ),
+ };
+
+ snprintf(req.name, IFNAMSIZ, "%s", name);
+
+ return nl_do(s, &req, RTM_NEWLINK, 0, sizeof(req));
+}
+
/**
* nl_neigh_msg_read() - Interpret a neighbour state message from netlink
* @c: Execution context
diff --git a/tap.c b/tap.c
index a2a4459..cd59160 100644
--- a/tap.c
+++ b/tap.c
@@ -1502,6 +1502,33 @@ static void tap_sock_tun_init(struct ctx *c)
tap_start_connection(c);
}
+/**
+ * tap_backend_init_late() - Create tap device for late binding
+ * @c: Execution context
+ *
+ * Called when late binding discovers the template interface name.
+ * Creates the TAP device with the discovered name.
+ */
+void tap_backend_init_late(struct ctx *c)
+{
+ if (c->mode != MODE_PASTA || c->fd_tap != -1)
+ return;
+
+ if (!*c->pasta_ifn) {
+ warn("%s called with empty pasta_ifn", __func__);
+ return;
+ }
+
+ NS_CALL(tap_ns_tun, c);
+ if (c->fd_tap == -1) {
+ err("Failed to set up tap device in namespace");
+ return;
+ }
+
+ tap_start_connection(c);
+ info("Created tap device %s for late binding", c->pasta_ifn);
+}
+
/**
* tap_sock_update_pool() - Set the buffer base and size for the pool of packets
* @base: Buffer base
diff --git a/tap.h b/tap.h
index ee22a9d..b41eae9 100644
--- a/tap.h
+++ b/tap.h
@@ -118,6 +118,7 @@ void tap_handler_passt(struct ctx *c, uint32_t events,
int tap_sock_unix_open(char *sock_path);
void tap_sock_reset(struct ctx *c);
void tap_backend_init(struct ctx *c);
+void tap_backend_init_late(struct ctx *c);
void tap_flush_pools(void);
void tap_handler(struct ctx *c, const struct timespec *now);
void tap_add_packet(struct ctx *c, struct iov_tail *data,
--
2.51.1