Merge pull request #22319 from yuwata/network-use-reconfigure
network: also use link_reconfigure_impl() to initially assign .network file
This commit is contained in:
@@ -121,6 +121,19 @@ int in_addr_is_localhost(int family, const union in_addr_union *u) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
int in_addr_is_localhost_one(int family, const union in_addr_union *u) {
|
||||
assert(u);
|
||||
|
||||
if (family == AF_INET)
|
||||
/* 127.0.0.1 */
|
||||
return be32toh(u->in.s_addr) == UINT32_C(0x7F000001);
|
||||
|
||||
if (family == AF_INET6)
|
||||
return IN6_IS_ADDR_LOOPBACK(&u->in6); /* lgtm [cpp/potentially-dangerous-function] */
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a) {
|
||||
return a->s6_addr32[0] == 0 &&
|
||||
a->s6_addr32[1] == 0 &&
|
||||
|
||||
@@ -49,6 +49,7 @@ bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
|
||||
|
||||
bool in4_addr_is_localhost(const struct in_addr *a);
|
||||
int in_addr_is_localhost(int family, const union in_addr_union *u);
|
||||
int in_addr_is_localhost_one(int family, const union in_addr_union *u);
|
||||
|
||||
bool in4_addr_is_local_multicast(const struct in_addr *a);
|
||||
bool in4_addr_is_non_local(const struct in_addr *a);
|
||||
|
||||
@@ -854,6 +854,10 @@ int link_drop_foreign_addresses(Link *link) {
|
||||
if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6))
|
||||
continue;
|
||||
|
||||
/* Do not remove localhost address (127.0.0.1 and ::1) */
|
||||
if (link->flags & IFF_LOOPBACK && in_addr_is_localhost_one(address->family, &address->in_addr) > 0)
|
||||
continue;
|
||||
|
||||
/* Ignore addresses we configured. */
|
||||
if (address->source != NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
@@ -891,22 +895,19 @@ int link_drop_foreign_addresses(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_drop_addresses(Link *link) {
|
||||
int link_drop_managed_addresses(Link *link) {
|
||||
Address *address;
|
||||
int k, r = 0;
|
||||
|
||||
assert(link);
|
||||
|
||||
SET_FOREACH(address, link->addresses) {
|
||||
/* Ignore addresses not assigned yet or already removing. */
|
||||
if (!address_exists(address))
|
||||
/* Do not touch addresses managed by kernel or other tools. */
|
||||
if (address->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
/* Do not drop IPv6LL addresses assigned by the kernel here. They will be dropped in
|
||||
* link_drop_ipv6ll_addresses() if IPv6LL addressing is disabled. */
|
||||
if (address->source == NETWORK_CONFIG_SOURCE_FOREIGN &&
|
||||
address->family == AF_INET6 &&
|
||||
in6_addr_is_link_local(&address->in_addr.in6))
|
||||
/* Ignore addresses not assigned yet or already removing. */
|
||||
if (!address_exists(address))
|
||||
continue;
|
||||
|
||||
k = address_remove(address);
|
||||
|
||||
@@ -74,7 +74,7 @@ void address_set_broadcast(Address *a);
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(Address, address_free);
|
||||
|
||||
int link_drop_addresses(Link *link);
|
||||
int link_drop_managed_addresses(Link *link);
|
||||
int link_drop_foreign_addresses(Link *link);
|
||||
int link_drop_ipv6ll_addresses(Link *link);
|
||||
void link_foreignize_addresses(Link *link);
|
||||
|
||||
+41
-78
@@ -430,6 +430,8 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
|
||||
|
||||
ndisc_flush(link);
|
||||
|
||||
k = sd_radv_stop(link->radv);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
|
||||
@@ -892,24 +894,6 @@ static int link_new_bound_to_list(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_new_carrier_maps(Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_new_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_new_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return link_handle_bound_to_list(link);
|
||||
}
|
||||
|
||||
static void link_free_bound_to_list(Link *link) {
|
||||
bool updated = false;
|
||||
Link *bound_to;
|
||||
@@ -946,13 +930,6 @@ static void link_free_bound_by_list(Link *link) {
|
||||
link_dirty(link);
|
||||
}
|
||||
|
||||
static void link_free_carrier_maps(Link *link) {
|
||||
assert(link);
|
||||
|
||||
link_free_bound_to_list(link);
|
||||
link_free_bound_by_list(link);
|
||||
}
|
||||
|
||||
static int link_append_to_master(Link *link) {
|
||||
Link *master;
|
||||
int r;
|
||||
@@ -1012,7 +989,8 @@ static Link *link_drop(Link *link) {
|
||||
|
||||
link_drop_requests(link);
|
||||
|
||||
link_free_carrier_maps(link);
|
||||
link_free_bound_to_list(link);
|
||||
link_free_bound_by_list(link);
|
||||
|
||||
link_drop_from_master(link);
|
||||
|
||||
@@ -1070,32 +1048,30 @@ static int link_drop_foreign_config(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int link_drop_config(Link *link) {
|
||||
static int link_drop_managed_config(Link *link) {
|
||||
int k, r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
r = link_drop_routes(link);
|
||||
r = link_drop_managed_routes(link);
|
||||
|
||||
k = link_drop_nexthops(link);
|
||||
k = link_drop_managed_nexthops(link);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
k = link_drop_addresses(link);
|
||||
k = link_drop_managed_addresses(link);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
k = link_drop_neighbors(link);
|
||||
k = link_drop_managed_neighbors(link);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
k = link_drop_routing_policy_rules(link);
|
||||
k = link_drop_managed_routing_policy_rules(link);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
ndisc_flush(link);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1119,6 +1095,10 @@ static int link_configure(Link *link) {
|
||||
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
|
||||
r = link_new_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_configure_traffic_control(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1293,17 +1273,28 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
|
||||
return 0;
|
||||
|
||||
r = link_get_network(link, &network);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (link->state != LINK_STATE_UNMANAGED && !network)
|
||||
/* If link is in initialized state, then link->network is also NULL. */
|
||||
force = true;
|
||||
|
||||
if (link->network == network && !force)
|
||||
return 0;
|
||||
|
||||
if (network)
|
||||
log_link_info(link, "Reconfiguring with %s.", network->filename);
|
||||
else
|
||||
log_link_info(link, "Unmanaging interface.");
|
||||
if (network) {
|
||||
if (link->state == LINK_STATE_INITIALIZED)
|
||||
log_link_info(link, "Configuring with %s.", network->filename);
|
||||
else
|
||||
log_link_info(link, "Reconfiguring with %s.", network->filename);
|
||||
} else
|
||||
log_link_full(link, link->state == LINK_STATE_INITIALIZED ? LOG_DEBUG : LOG_INFO,
|
||||
"Unmanaging interface.");
|
||||
|
||||
/* Dropping old .network file */
|
||||
r = link_stop_engines(link, false);
|
||||
@@ -1318,12 +1309,19 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
* link_drop_foreign_config() in link_configure(). */
|
||||
link_foreignize_config(link);
|
||||
else {
|
||||
r = link_drop_config(link);
|
||||
/* Remove all managed configs. Note, foreign configs are removed in later by
|
||||
* link_configure() -> link_drop_foreign_config() if the link is managed by us. */
|
||||
r = link_drop_managed_config(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
link_free_carrier_maps(link);
|
||||
/* The bound_to map depends on .network file, hence it needs to be freed. But, do not free the
|
||||
* bound_by map. Otherwise, if a link enters unmanaged state below, then its carrier state will
|
||||
* not propagated to other interfaces anymore. Moreover, it is not necessary to recreate the
|
||||
* map here, as it depends on .network files assigned to other links. */
|
||||
link_free_bound_to_list(link);
|
||||
|
||||
link_free_engines(link);
|
||||
link->network = network_unref(link->network);
|
||||
|
||||
@@ -1337,10 +1335,6 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
link_update_operstate(link, true);
|
||||
link_dirty(link);
|
||||
|
||||
r = link_new_carrier_maps(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
link->activated = false;
|
||||
|
||||
@@ -1440,11 +1434,9 @@ int link_reconfigure_after_sleep(Link *link) {
|
||||
}
|
||||
|
||||
static int link_initialized_and_synced(Link *link) {
|
||||
Network *network;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->ifname);
|
||||
assert(link->manager);
|
||||
|
||||
if (link->manager->test_mode) {
|
||||
@@ -1453,7 +1445,7 @@ static int link_initialized_and_synced(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We may get called either from the asynchronous netlink callback,
|
||||
/* This may get called either from the asynchronous netlink callback,
|
||||
* or directly from link_check_initialized() if running in a container. */
|
||||
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
|
||||
return 0;
|
||||
@@ -1469,36 +1461,7 @@ static int link_initialized_and_synced(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!link->network) {
|
||||
r = link_get_network(link, &network);
|
||||
if (r == -ENOENT) {
|
||||
link_set_state(link, LINK_STATE_UNMANAGED);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->flags & IFF_LOOPBACK) {
|
||||
if (network->link_local != ADDRESS_FAMILY_NO)
|
||||
log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
|
||||
|
||||
if (network->dhcp != ADDRESS_FAMILY_NO)
|
||||
log_link_debug(link, "Ignoring DHCP clients for loopback link");
|
||||
|
||||
if (network->dhcp_server)
|
||||
log_link_debug(link, "Ignoring DHCP server for loopback link");
|
||||
}
|
||||
|
||||
link->network = network_ref(network);
|
||||
link_update_operstate(link, false);
|
||||
link_dirty(link);
|
||||
}
|
||||
|
||||
r = link_new_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return link_configure(link);
|
||||
return link_reconfigure_impl(link, /* force = */ false);
|
||||
}
|
||||
|
||||
static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
@@ -1706,7 +1669,7 @@ static int link_carrier_lost_impl(Link *link) {
|
||||
if (r < 0)
|
||||
ret = r;
|
||||
|
||||
r = link_drop_config(link);
|
||||
r = link_drop_managed_config(link);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
|
||||
|
||||
@@ -416,13 +416,17 @@ int link_drop_foreign_neighbors(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_drop_neighbors(Link *link) {
|
||||
int link_drop_managed_neighbors(Link *link) {
|
||||
Neighbor *neighbor;
|
||||
int k, r = 0;
|
||||
|
||||
assert(link);
|
||||
|
||||
SET_FOREACH(neighbor, link->neighbors) {
|
||||
/* Do not touch nexthops managed by kernel or other tools. */
|
||||
if (neighbor->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
/* Ignore neighbors not assigned yet or already removing. */
|
||||
if (!neighbor_exists(neighbor))
|
||||
continue;
|
||||
|
||||
@@ -34,7 +34,7 @@ int neighbor_compare_func(const Neighbor *a, const Neighbor *b);
|
||||
|
||||
void network_drop_invalid_neighbors(Network *network);
|
||||
|
||||
int link_drop_neighbors(Link *link);
|
||||
int link_drop_managed_neighbors(Link *link);
|
||||
int link_drop_foreign_neighbors(Link *link);
|
||||
void link_foreignize_neighbors(Link *link);
|
||||
|
||||
|
||||
@@ -613,8 +613,8 @@ static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *ex
|
||||
if (nexthop->protocol == RTPROT_KERNEL)
|
||||
continue;
|
||||
|
||||
/* When 'foreign' is true, do not remove nexthops we configured. */
|
||||
if (foreign && nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
/* When 'foreign' is true, mark only foreign nexthops, and vice versa. */
|
||||
if (foreign != (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN))
|
||||
continue;
|
||||
|
||||
/* Ignore nexthops not assigned yet or already removed. */
|
||||
@@ -641,7 +641,7 @@ static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *ex
|
||||
}
|
||||
}
|
||||
|
||||
static int manager_drop_nexthops(Manager *manager) {
|
||||
static int manager_drop_marked_nexthops(Manager *manager) {
|
||||
NextHop *nexthop;
|
||||
int k, r = 0;
|
||||
|
||||
@@ -704,14 +704,14 @@ int link_drop_foreign_nexthops(Link *link) {
|
||||
|
||||
manager_mark_nexthops(link->manager, /* foreign = */ true, NULL);
|
||||
|
||||
k = manager_drop_nexthops(link->manager);
|
||||
k = manager_drop_marked_nexthops(link->manager);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_drop_nexthops(Link *link) {
|
||||
int link_drop_managed_nexthops(Link *link) {
|
||||
NextHop *nexthop;
|
||||
int k, r = 0;
|
||||
|
||||
@@ -723,6 +723,10 @@ int link_drop_nexthops(Link *link) {
|
||||
if (nexthop->protocol == RTPROT_KERNEL)
|
||||
continue;
|
||||
|
||||
/* Do not touch addresses managed by kernel or other tools. */
|
||||
if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
/* Ignore nexthops not assigned yet or already removing. */
|
||||
if (!nexthop_exists(nexthop))
|
||||
continue;
|
||||
@@ -734,7 +738,7 @@ int link_drop_nexthops(Link *link) {
|
||||
|
||||
manager_mark_nexthops(link->manager, /* foreign = */ false, link);
|
||||
|
||||
k = manager_drop_nexthops(link->manager);
|
||||
k = manager_drop_marked_nexthops(link->manager);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ int nexthop_compare_func(const NextHop *a, const NextHop *b);
|
||||
|
||||
void network_drop_invalid_nexthops(Network *network);
|
||||
|
||||
int link_drop_nexthops(Link *link);
|
||||
int link_drop_managed_nexthops(Link *link);
|
||||
int link_drop_foreign_nexthops(Link *link);
|
||||
void link_foreignize_nexthops(Link *link);
|
||||
|
||||
|
||||
@@ -788,8 +788,8 @@ static void manager_mark_routes(Manager *manager, bool foreign, const Link *exce
|
||||
if (route->protocol == RTPROT_KERNEL)
|
||||
continue;
|
||||
|
||||
/* When 'foreign' is true, do not remove routes we configured. */
|
||||
if (foreign && route->source != NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
/* When 'foreign' is true, mark only foreign routes, and vice versa. */
|
||||
if (foreign != (route->source == NETWORK_CONFIG_SOURCE_FOREIGN))
|
||||
continue;
|
||||
|
||||
/* Do not touch dynamic routes. They will removed by dhcp_pd_prefix_lost() */
|
||||
@@ -834,7 +834,7 @@ static void manager_mark_routes(Manager *manager, bool foreign, const Link *exce
|
||||
}
|
||||
}
|
||||
|
||||
static int manager_drop_routes(Manager *manager) {
|
||||
static int manager_drop_marked_routes(Manager *manager) {
|
||||
Route *route;
|
||||
int k, r = 0;
|
||||
|
||||
@@ -955,14 +955,14 @@ int link_drop_foreign_routes(Link *link) {
|
||||
|
||||
manager_mark_routes(link->manager, /* foreign = */ true, NULL);
|
||||
|
||||
k = manager_drop_routes(link->manager);
|
||||
k = manager_drop_marked_routes(link->manager);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_drop_routes(Link *link) {
|
||||
int link_drop_managed_routes(Link *link) {
|
||||
Route *route;
|
||||
int k, r = 0;
|
||||
|
||||
@@ -973,6 +973,10 @@ int link_drop_routes(Link *link) {
|
||||
if (route_by_kernel(route))
|
||||
continue;
|
||||
|
||||
/* Do not touch routes managed by kernel or other tools. */
|
||||
if (route->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
if (!route_exists(route))
|
||||
continue;
|
||||
|
||||
@@ -983,7 +987,7 @@ int link_drop_routes(Link *link) {
|
||||
|
||||
manager_mark_routes(link->manager, /* foreign = */ false, link);
|
||||
|
||||
k = manager_drop_routes(link->manager);
|
||||
k = manager_drop_marked_routes(link->manager);
|
||||
if (k < 0 && r >= 0)
|
||||
r = k;
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ int route_remove(Route *route);
|
||||
|
||||
int route_get(Manager *manager, Link *link, const Route *in, Route **ret);
|
||||
|
||||
int link_drop_routes(Link *link);
|
||||
int link_drop_managed_routes(Link *link);
|
||||
int link_drop_foreign_routes(Link *link);
|
||||
void link_foreignize_routes(Link *link);
|
||||
|
||||
|
||||
@@ -653,8 +653,8 @@ static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Li
|
||||
if (rule->protocol == RTPROT_KERNEL)
|
||||
continue;
|
||||
|
||||
/* When 'foreign' is true, do not remove rules we configured. */
|
||||
if (foreign && rule->source != NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
/* When 'foreign' is true, mark only foreign rules, and vice versa. */
|
||||
if (foreign != (rule->source == NETWORK_CONFIG_SOURCE_FOREIGN))
|
||||
continue;
|
||||
|
||||
/* Ignore rules not assigned yet or already removing. */
|
||||
|
||||
@@ -71,7 +71,7 @@ int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const L
|
||||
static inline int manager_drop_foreign_routing_policy_rules(Manager *m) {
|
||||
return manager_drop_routing_policy_rules_internal(m, true, NULL);
|
||||
}
|
||||
static inline int link_drop_routing_policy_rules(Link *link) {
|
||||
static inline int link_drop_managed_routing_policy_rules(Link *link) {
|
||||
assert(link);
|
||||
return manager_drop_routing_policy_rules_internal(link->manager, false, link);
|
||||
}
|
||||
|
||||
@@ -3893,7 +3893,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, 'NO-CARRIER')
|
||||
self.assertNotRegex(output, '192.168.0.15/24')
|
||||
self.assertNotRegex(output, '192.168.0.16/24')
|
||||
self.assertRegex(output, '192.168.0.16/24') # foreign address is kept
|
||||
|
||||
print('### ip -6 route list table all dev bridge99')
|
||||
output = check_output('ip -6 route list table all dev bridge99')
|
||||
|
||||
Reference in New Issue
Block a user