From: Yu Watanabe Date: Thu, 7 Nov 2024 00:16:06 +0000 (+0900) Subject: network/dhcp-pd: do not remove unreachable route when reconfiguring non-upstream... X-Git-Tag: v257-rc2~41^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4e76c57c7f86c46ef2ec3d3f7c25e049cf357214;p=thirdparty%2Fsystemd.git network/dhcp-pd: do not remove unreachable route when reconfiguring non-upstream interface Unreachable routes are not owned by any interfaces, and its ifindex is zero. Previously, if a non-upstream interface is reconfigured, all routes including unreachable routes configured by the upstream interface are removed. This makes unreachable routes are always handled by the upstream interface, and only removed when the delegated prefixes are changed or lost. --- diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 0819ed54f13..7a5d0e04150 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -613,8 +613,49 @@ static int dhcp_pd_finalize(Link *link) { return 0; } -void dhcp_pd_prefix_lost(Link *uplink) { +static void dhcp_pd_mark_unreachable_route(Manager *manager, NetworkConfigSource source) { + assert(manager); + + Route *route; + SET_FOREACH(route, manager->routes) { + if (route->source != source) + continue; + if (route->family != AF_INET6) + continue; + if (route->nexthop.ifindex != 0) /* IPv6 unreachable has 0 ifindex. */ + continue; + if (!route_type_is_reject(route->type)) + continue; + + route_mark(route); + } +} + +static int dhcp_pd_remove_unreachable_route(Manager *manager, NetworkConfigSource source, bool only_marked) { + int ret = 0; + + assert(manager); + Route *route; + SET_FOREACH(route, manager->routes) { + if (route->source != source) + continue; + if (route->family != AF_INET6) + continue; + if (route->nexthop.ifindex != 0) /* IPv6 unreachable has 0 ifindex. */ + continue; + if (!route_type_is_reject(route->type)) + continue; + if (only_marked && !route_is_marked(route)) + continue; + + RET_GATHER(ret, route_remove_and_cancel(route, manager)); + } + + return ret; +} + +static void dhcp_pd_prefix_lost(Link *uplink, NetworkConfigSource source) { Link *link; int r; @@ -630,22 +671,7 @@ void dhcp_pd_prefix_lost(Link *uplink) { link_enter_failed(link); } - SET_FOREACH(route, uplink->manager->routes) { - if (!IN_SET(route->source, NETWORK_CONFIG_SOURCE_DHCP4, NETWORK_CONFIG_SOURCE_DHCP6)) - continue; - if (route->family != AF_INET6) - continue; - if (route->type != RTN_UNREACHABLE) - continue; - if (!set_contains(uplink->dhcp_pd_prefixes, - &(struct in_addr_prefix) { - .family = AF_INET6, - .prefixlen = route->dst_prefixlen, - .address = route->dst })) - continue; - - (void) route_remove_and_cancel(route, uplink->manager); - } + (void) dhcp_pd_remove_unreachable_route(uplink->manager, source, /* only_marked = */ false); set_clear(uplink->dhcp_pd_prefixes); } @@ -653,13 +679,20 @@ void dhcp_pd_prefix_lost(Link *uplink) { void dhcp4_pd_prefix_lost(Link *uplink) { Link *tunnel; - dhcp_pd_prefix_lost(uplink); + assert(uplink); + assert(uplink->manager); + + dhcp_pd_prefix_lost(uplink, NETWORK_CONFIG_SOURCE_DHCP4); if (uplink->dhcp4_6rd_tunnel_name && link_get_by_name(uplink->manager, uplink->dhcp4_6rd_tunnel_name, &tunnel) >= 0) (void) link_remove(tunnel); } +void dhcp6_pd_prefix_lost(Link *uplink) { + dhcp_pd_prefix_lost(uplink, NETWORK_CONFIG_SOURCE_DHCP6); +} + static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) { int r; @@ -1005,9 +1038,11 @@ int dhcp4_pd_prefix_acquired(Link *uplink) { return r; /* Request unreachable route */ + dhcp_pd_mark_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP4); r = dhcp4_request_unreachable_route(uplink, &pd_prefix, pd_prefixlen, lifetime_usec, &server_address); if (r < 0) return r; + (void) dhcp_pd_remove_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP4, /* only_marked = */ true); /* Create or update 6rd SIT tunnel device. */ r = dhcp4_pd_create_6rd_tunnel(uplink, dhcp4_pd_6rd_tunnel_create_handler); @@ -1085,11 +1120,14 @@ int dhcp6_pd_prefix_acquired(Link *uplink) { assert(uplink); assert(uplink->dhcp6_lease); + assert(uplink->manager); r = sd_dhcp6_lease_get_server_address(uplink->dhcp6_lease, &server_address.in6); if (r < 0) return log_link_warning_errno(uplink, r, "Failed to get server address of DHCPv6 lease: %m"); + dhcp_pd_mark_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP6); + /* First, logs acquired prefixes and request unreachable routes. */ FOREACH_DHCP6_PD_PREFIX(uplink->dhcp6_lease) { usec_t lifetime_valid_usec; @@ -1120,6 +1158,8 @@ int dhcp6_pd_prefix_acquired(Link *uplink) { return r; } + (void) dhcp_pd_remove_unreachable_route(uplink->manager, NETWORK_CONFIG_SOURCE_DHCP6, /* only_marked = */ true); + /* Then, assign subnet prefixes. */ HASHMAP_FOREACH(link, uplink->manager->links_by_index) { if (!dhcp_pd_is_uplink(link, uplink, /* accept_auto = */ true)) diff --git a/src/network/networkd-dhcp-prefix-delegation.h b/src/network/networkd-dhcp-prefix-delegation.h index 099e1444a54..27e920e1cf0 100644 --- a/src/network/networkd-dhcp-prefix-delegation.h +++ b/src/network/networkd-dhcp-prefix-delegation.h @@ -20,8 +20,8 @@ int dhcp_request_prefix_delegation(Link *link); int link_drop_dhcp_pd_config(Link *link, Network *network); int dhcp4_pd_prefix_acquired(Link *uplink); int dhcp6_pd_prefix_acquired(Link *uplink); -void dhcp_pd_prefix_lost(Link *uplink); void dhcp4_pd_prefix_lost(Link *uplink); +void dhcp6_pd_prefix_lost(Link *uplink); int dhcp_pd_reconfigure_address(Address *address, Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_pd_subnet_id); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index ca4e2a59261..dae1a7b7f4e 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -247,7 +247,7 @@ static int dhcp4_remove_address_and_routes(Link *link, bool only_marked) { SET_FOREACH(route, link->manager->routes) { if (route->source != NETWORK_CONFIG_SOURCE_DHCP4) continue; - if (route->nexthop.ifindex != 0 && route->nexthop.ifindex != link->ifindex) + if (route->nexthop.ifindex != link->ifindex) continue; if (only_marked && !route_is_marked(route)) continue; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 88e7c0a263d..a6808fdb757 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -307,7 +307,6 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) { int r; link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP6); - manager_mark_routes(link->manager, NULL, NETWORK_CONFIG_SOURCE_DHCP6); r = sd_dhcp6_client_get_lease(client, &lease); if (r < 0) @@ -330,7 +329,7 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) { return r; } else if (sd_dhcp6_lease_has_pd_prefix(lease_old)) /* When we had PD prefixes but not now, we need to remove them. */ - dhcp_pd_prefix_lost(link); + dhcp6_pd_prefix_lost(link); if (link->dhcp6_messages == 0) { link->dhcp6_configured = true; @@ -377,7 +376,7 @@ static int dhcp6_lease_lost(Link *link) { log_link_info(link, "DHCPv6 lease lost"); if (sd_dhcp6_lease_has_pd_prefix(link->dhcp6_lease)) - dhcp_pd_prefix_lost(link); + dhcp6_pd_prefix_lost(link); link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);