summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-11-07 01:16:06 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-11-11 03:53:24 +0100
commit4e76c57c7f86c46ef2ec3d3f7c25e049cf357214 (patch)
treeb855ddd9381a37e06d5a6daf18eedb9aca9a8c53 /src/network
parentnetwork: reorder dropping dynamic configuration (diff)
downloadsystemd-4e76c57c7f86c46ef2ec3d3f7c25e049cf357214.tar.xz
systemd-4e76c57c7f86c46ef2ec3d3f7c25e049cf357214.zip
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.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-dhcp-prefix-delegation.c76
-rw-r--r--src/network/networkd-dhcp-prefix-delegation.h2
-rw-r--r--src/network/networkd-dhcp4.c2
-rw-r--r--src/network/networkd-dhcp6.c5
4 files changed, 62 insertions, 23 deletions
diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c
index 0819ed54f1..7a5d0e0415 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 099e1444a5..27e920e1cf 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 ca4e2a5926..dae1a7b7f4 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 88e7c0a263..a6808fdb75 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);