On Sun, Dec 14, 2025 at 08:54:40PM -0500, Jon Maloy wrote:
We add a new context flag 'guest_gw_from_ns' to track if the gateway was configured from the guest side, something that might have happened either via the -g option or by a namespace-side netlink event. When set, host side route events will not be permitted to overwrite the guest's gateway configuration.
If -g is set, I don't think we should even subscribe to the routing updates in the first place. If --config-net is *not* set, we shouldn't be touching the guest config anyway. If --config-net *is* set, that's essentially saying that we own the guest's network configuration. We don't need to go to these lengths to stop it from shooting itself by making conflicting config updates.
This gives any gateway setting from the guest side precedence over any ditto coming from the host side.
Signed-off-by: Jon Maloy
--- conf.c | 2 ++ netlink.c | 15 +++++++++++++-- passt.h | 4 ++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/conf.c b/conf.c index 0a4a28a..f26637c 100644 --- a/conf.c +++ b/conf.c @@ -1891,6 +1891,7 @@ void conf(struct ctx *c, int argc, char **argv) !IN6_IS_ADDR_LOOPBACK(&c->ip6.guest_gw)) { if (c->mode == MODE_PASTA) c->ip6.no_copy_routes = true; + c->ip6.guest_gw_from_ns = true; break; }
@@ -1900,6 +1901,7 @@ void conf(struct ctx *c, int argc, char **argv) !IN4_IS_ADDR_LOOPBACK(&c->ip4.guest_gw)) { if (c->mode == MODE_PASTA) c->ip4.no_copy_routes = true; + c->ip4.guest_gw_from_ns = true; break; }
diff --git a/netlink.c b/netlink.c index d049239..de04fb7 100644 --- a/netlink.c +++ b/netlink.c @@ -490,6 +490,9 @@ static void nl_linkaddr_host_msg_read(struct ctx *c, const struct nlmsghdr *nh) if (rtm->rtm_family == AF_INET) { char buf[INET_ADDRSTRLEN];
+ if (c->ip4.guest_gw_from_ns) + return; + if (!is_new) { c->ip4.guest_gw = (struct in_addr){ 0 }; c->ip4.our_tap_addr = (struct in_addr){ 0 }; @@ -503,6 +506,9 @@ static void nl_linkaddr_host_msg_read(struct ctx *c, const struct nlmsghdr *nh) } else if (rtm->rtm_family == AF_INET6) { char buf[INET6_ADDRSTRLEN];
+ if (c->ip6.guest_gw_from_ns) + return; + if (!is_new) { c->ip6.guest_gw = (struct in6_addr){ 0 }; return; @@ -658,15 +664,20 @@ static void nl_linkaddr_msg_read(struct ctx *c, const struct nlmsghdr *nh) if (is_new) { c->ip4.guest_gw = *(struct in_addr *)gw; c->ip4.our_tap_addr = c->ip4.guest_gw; + c->ip4.guest_gw_from_ns = true; } else { c->ip4.guest_gw = (struct in_addr){ 0 }; c->ip4.our_tap_addr = (struct in_addr){ 0 }; + c->ip4.guest_gw_from_ns = false; } } else if (rtm->rtm_family == AF_INET6) { - if (is_new) + if (is_new) { c->ip6.guest_gw = *(struct in6_addr *)gw; - else + c->ip6.guest_gw_from_ns = true; + } else { c->ip6.guest_gw = (struct in6_addr){ 0 }; + c->ip6.guest_gw_from_ns = false; + } } } } diff --git a/passt.h b/passt.h index 70ccaf1..5e7bc99 100644 --- a/passt.h +++ b/passt.h @@ -82,6 +82,7 @@ enum passt_modes { * @ifname_out: Optional interface name to bind outbound sockets to * @no_copy_routes: Don't copy all routes when configuring target namespace * @no_copy_addrs: Don't copy all addresses when configuring namespace + * @guest_gw_from_ns: Gateway was set from namespace (config or ns event) */ struct ip4_ctx { /* PIF_TAP addresses */ @@ -104,6 +105,7 @@ struct ip4_ctx {
bool no_copy_routes; bool no_copy_addrs; + bool guest_gw_from_ns; };
/** @@ -125,6 +127,7 @@ struct ip4_ctx { * @ifname_out: Optional interface name to bind outbound sockets to * @no_copy_routes: Don't copy all routes when configuring target namespace * @no_copy_addrs: Don't copy all addresses when configuring namespace + * @guest_gw_from_ns: Gateway was set from namespace (config or ns event) */ struct ip6_ctx { /* PIF_TAP addresses */ @@ -148,6 +151,7 @@ struct ip6_ctx {
bool no_copy_routes; bool no_copy_addrs; + bool guest_gw_from_ns; };
#include
-- 2.51.1
-- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson