diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 1f356907fe..e49d21f804 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -457,43 +457,6 @@ int address_equal(const Address *a1, const Address *a2) { return address_compare_func(a1, a2) == 0; } -static int address_equalify(Address *address, const Address *src) { - bool src_is_null; - int r; - - assert(address); - assert(src); - - src_is_null = address_is_static_null(src); - - if (src_is_null) { - /* When the source address has an null address, then we cannot compare the two objects with - * address_kernel_compare_func(). Let's do minimal check here. */ - if (address->family != src->family) - return -EINVAL; - if (address->prefixlen != src->prefixlen) - return -EINVAL; - - } else if (address_kernel_compare_func(address, src) != 0) - return -EINVAL; - - if (address->family == AF_INET) { - /* When the source is null, then the broadcast address will be determined based on the - * acquired address. Hence, do not copy it here. */ - if (!src_is_null) - address->broadcast = src->broadcast; - - r = free_and_strdup(&address->label, src->label); - if (r < 0) - return r; - } else { - address->prefixlen = src->prefixlen; - address->in_addr_peer = src->in_addr_peer; - } - - return 0; -} - int address_dup(const Address *src, Address **ret) { _cleanup_(address_freep) Address *dest = NULL; int r; @@ -626,8 +589,7 @@ static int address_drop(Address *address) { address_del_netlabel(address); - if (address->state == 0) - address_free(address); + address_free(address); link_update_operstate(link, /* also_update_master = */ true); link_check_ready(link); @@ -655,6 +617,47 @@ static bool address_match_null(const Address *a, const Address *null_address) { return true; } +static int address_get_request(Link *link, const Address *address, Request **ret) { + Request *req; + + assert(link); + assert(link->manager); + assert(address); + + req = ordered_set_get( + link->manager->request_queue, + &(Request) { + .link = link, + .type = REQUEST_TYPE_ADDRESS, + .userdata = (void*) address, + .hash_func = (hash_func_t) address_kernel_hash_func, + .compare_func = (compare_func_t) address_kernel_compare_func, + }); + if (req) { + if (ret) + *ret = req; + return 0; + } + + if (address_is_static_null(address)) + ORDERED_SET_FOREACH(req, link->manager->request_queue) { + if (req->link != link) + continue; + if (req->type != REQUEST_TYPE_ADDRESS) + continue; + + if (!address_match_null(req->userdata, address)) + continue; + + if (ret) + *ret = req; + + return 0; + } + + return -ENOENT; +} + int address_get(Link *link, const Address *in, Address **ret) { Address *a; @@ -682,6 +685,26 @@ int address_get(Link *link, const Address *in, Address **ret) { return -ENOENT; } +int address_get_harder(Link *link, const Address *in, Address **ret) { + Request *req; + int r; + + assert(link); + assert(in); + + if (address_get(link, in, ret) >= 0) + return 0; + + r = address_get_request(link, in, &req); + if (r < 0) + return r; + + if (ret) + *ret = ASSERT_PTR(req->userdata); + + return 0; +} + int link_get_address(Link *link, int family, const union in_addr_union *address, unsigned char prefixlen, Address **ret) { Address *a; int r; @@ -874,6 +897,7 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link int address_remove(Address *address) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + Request *req; Link *link; int r; @@ -906,6 +930,8 @@ int address_remove(Address *address) { link_ref(link); address_enter_removing(address); + if (address_get_request(link, address, &req) >= 0) + address_enter_removing(req->userdata); /* The operational state is determined by address state and carrier state. Hence, if we remove * an address, the operational state may be changed. */ @@ -1275,6 +1301,7 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { } static int address_process_request(Request *req, Link *link, Address *address) { + struct Address *existing; struct ifa_cacheinfo c; int r; @@ -1290,7 +1317,10 @@ static int address_process_request(Request *req, Link *link, Address *address) { log_link_debug(link, "Refuse to configure %s address %s, as its valid lifetime is zero.", network_config_source_to_string(address->source), IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); + address_cancel_requesting(address); + if (address_get(link, address, &existing) >= 0) + address_enter_configuring(existing); return 1; } @@ -1299,6 +1329,9 @@ static int address_process_request(Request *req, Link *link, Address *address) { return log_link_warning_errno(link, r, "Failed to configure address: %m"); address_enter_configuring(address); + if (address_get(link, address, &existing) >= 0) + address_enter_configuring(existing); + return 1; } @@ -1309,59 +1342,52 @@ int link_request_address( address_netlink_handler_t netlink_handler, Request **ret) { - Address *existing; + _cleanup_(address_freep) Address *tmp = NULL; + Address *existing = NULL; int r; assert(link); assert(address); assert(address->source != NETWORK_CONFIG_SOURCE_FOREIGN); - if (address_get(link, address, &existing) < 0) { - _cleanup_(address_freep) Address *tmp = NULL; + if (address->lifetime_valid_usec == 0) + /* The requested address is outdated. Let's ignore the request. */ + return 0; - if (address->lifetime_valid_usec == 0) - /* The requested address is outdated. Let's ignore the request. */ - return 0; + if (address_get(link, address, &existing) < 0) { + if (address_get_request(link, address, NULL) >= 0) + return 0; /* already requested, skipping. */ r = address_acquire(link, address, &tmp); if (r < 0) return log_link_warning_errno(link, r, "Failed to acquire an address from pool: %m"); - address_set_broadcast(tmp, link); - /* Consider address tentative until we get the real flags from the kernel */ tmp->flags |= IFA_F_TENTATIVE; - r = address_add(link, tmp); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to save requested address: %m"); - - existing = TAKE_PTR(tmp); } else { - if (address->lifetime_valid_usec == 0) - /* The requested address is outdated. Let's remove it. */ - return address_remove_and_drop(existing); - - r = address_equalify(existing, address); + r = address_dup(address, &tmp); if (r < 0) - return log_link_warning_errno(link, r, "Failed to equalify saved address with the requested one: %m"); + return log_oom(); - address_set_broadcast(existing, link); + /* Copy already assigned address when it is requested as a null address. */ + if (address_is_static_null(address)) + tmp->in_addr = existing->in_addr; - existing->source = address->source; - existing->provider = address->provider; - existing->duplicate_address_detection = address->duplicate_address_detection; - existing->lifetime_valid_usec = address->lifetime_valid_usec; - existing->lifetime_preferred_usec = address->lifetime_preferred_usec; + /* Copy state for logging below. */ + tmp->state = existing->state; } - r = ipv4acd_configure(link, existing); + address_set_broadcast(tmp, link); + + r = ipv4acd_configure(link, tmp); if (r < 0) return r; - log_address_debug(existing, "Requesting", link); + log_address_debug(tmp, "Requesting", link); r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS, - existing, NULL, + tmp, + address_free, address_kernel_hash_func, address_kernel_compare_func, address_process_request, @@ -1371,8 +1397,11 @@ int link_request_address( if (r == 0) return 0; - address_enter_requesting(existing); + address_enter_requesting(tmp); + if (existing) + address_enter_requesting(existing); + TAKE_PTR(tmp); return 1; } @@ -1464,6 +1493,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Link *link; uint16_t type; Address *address = NULL; + Request *req = NULL; + bool is_new = false; int ifindex, r; assert(rtnl); @@ -1509,6 +1540,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, if (r < 0) return log_oom(); + /* First, read minimal information to make address_get() work below. */ + r = sd_rtnl_message_addr_get_family(message, &tmp->family); if (r < 0) { log_link_warning(link, "rtnl: received address message without family, ignoring."); @@ -1524,26 +1557,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, return 0; } - r = sd_rtnl_message_addr_get_scope(message, &tmp->scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without scope, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, IFA_FLAGS, &tmp->flags); - if (r == -ENODATA) { - unsigned char flags; - - /* For old kernels. */ - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r >= 0) - tmp->flags = flags; - } - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without flags, ignoring: %m"); - return 0; - } - switch (tmp->family) { case AF_INET: r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &tmp->in_addr.in); @@ -1561,19 +1574,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, tmp->in_addr_peer = IN_ADDR_NULL; } - r = sd_netlink_message_read_in_addr(message, IFA_BROADCAST, &tmp->broadcast); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: could not get broadcast from address message, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_string_strdup(message, IFA_LABEL, &tmp->label); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: could not get label from address message, ignoring: %m"); - return 0; - } else if (r >= 0 && streq_ptr(tmp->label, link->ifname)) - tmp->label = mfree(tmp->label); - break; case AF_INET6: @@ -1603,65 +1603,105 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, assert_not_reached(); } - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); - return 0; - } - + /* Then, find the managed Address and Request objects corresponding to the received address. */ (void) address_get(link, tmp, &address); + (void) address_get_request(link, tmp, &req); - switch (type) { - case RTM_NEWADDR: - if (address) { - /* update flags and etc. */ - r = address_equalify(address, tmp); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to update properties of address %s, ignoring: %m", - IN_ADDR_PREFIX_TO_STRING(address->family, &address->in_addr, address->prefixlen)); - return 0; - } - address->flags = tmp->flags; - address->scope = tmp->scope; - address_set_lifetime(m, address, &cinfo); - address_enter_configured(address); - log_address_debug(address, "Received updated", link); - } else { - address_set_lifetime(m, tmp, &cinfo); - address_enter_configured(tmp); - log_address_debug(tmp, "Received new", link); - - r = address_add(link, tmp); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to remember foreign address %s, ignoring: %m", - IN_ADDR_PREFIX_TO_STRING(tmp->family, &tmp->in_addr, tmp->prefixlen)); - return 0; - } - - address = TAKE_PTR(tmp); - } - - /* address_update() logs internally, so we don't need to here. */ - r = address_update(address); - if (r < 0) - link_enter_failed(link); - - break; - - case RTM_DELADDR: + if (type == RTM_DELADDR) { if (address) { address_enter_removed(address); - log_address_debug(address, address->state == 0 ? "Forgetting" : "Removed", link); + log_address_debug(address, "Forgetting removed", link); (void) address_drop(address); } else log_address_debug(tmp, "Kernel removed unknown", link); - break; + if (req) + address_enter_removed(req->userdata); - default: - assert_not_reached(); + return 0; } + if (!address) { + /* If we did not know the address, then save it. */ + r = address_add(link, tmp); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign address %s, ignoring: %m", + IN_ADDR_PREFIX_TO_STRING(tmp->family, &tmp->in_addr, tmp->prefixlen)); + return 0; + } + address = TAKE_PTR(tmp); + + is_new = true; + + } else { + /* Otherwise, update the managed Address object with the netlink notification. */ + address->prefixlen = tmp->prefixlen; + address->in_addr_peer = tmp->in_addr_peer; + } + + /* Also update information that cannot be obtained through netlink notification. */ + if (req && req->waiting_reply) { + Address *a = ASSERT_PTR(req->userdata); + + address->source = a->source; + address->provider = a->provider; + (void) free_and_strdup_warn(&address->netlabel, a->netlabel); + address->requested_as_null = a->requested_as_null; + address->callback = a->callback; + } + + /* Then, update miscellaneous info. */ + r = sd_rtnl_message_addr_get_scope(message, &address->scope); + if (r < 0) + log_link_debug_errno(link, r, "rtnl: received address message without scope, ignoring: %m"); + + if (address->family == AF_INET) { + _cleanup_free_ char *label = NULL; + + r = sd_netlink_message_read_string_strdup(message, IFA_LABEL, &label); + if (r >= 0) { + if (!streq_ptr(label, link->ifname)) + free_and_replace(address->label, label); + } else if (r != -ENODATA) + log_link_debug_errno(link, r, "rtnl: could not get label from address message, ignoring: %m"); + + r = sd_netlink_message_read_in_addr(message, IFA_BROADCAST, &address->broadcast); + if (r < 0 && r != -ENODATA) + log_link_debug_errno(link, r, "rtnl: could not get broadcast from address message, ignoring: %m"); + } + + r = sd_netlink_message_read_u32(message, IFA_FLAGS, &address->flags); + if (r == -ENODATA) { + unsigned char flags; + + /* For old kernels. */ + r = sd_rtnl_message_addr_get_flags(message, &flags); + if (r >= 0) + address->flags = flags; + } else if (r < 0) + log_link_debug_errno(link, r, "rtnl: failed to read IFA_FLAGS attribute, ignoring: %m"); + + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); + if (r >= 0) + address_set_lifetime(m, address, &cinfo); + else if (r != -ENODATA) + log_link_debug_errno(link, r, "rtnl: failed to read IFA_CACHEINFO attribute, ignoring: %m"); + + r = sd_netlink_message_read_u32(message, IFA_RT_PRIORITY, &address->route_metric); + if (r < 0 && r != -ENODATA) + log_link_debug_errno(link, r, "rtnl: failed to read IFA_RT_PRIORITY attribute, ignoring: %m"); + + address_enter_configured(address); + if (req) + address_enter_configured(req->userdata); + + log_address_debug(address, is_new ? "Received new": "Received updated", link); + + /* address_update() logs internally, so we don't need to here. */ + r = address_update(address); + if (r < 0) + link_enter_failed(link); + return 1; } diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 9b418af414..bdb5b5b5e5 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -73,6 +73,7 @@ int address_flags_to_string_alloc(uint32_t flags, int family, char **ret); int address_new(Address **ret); Address* address_free(Address *address); int address_get(Link *link, const Address *in, Address **ret); +int address_get_harder(Link *link, const Address *in, Address **ret); int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg); int address_remove(Address *address); int address_remove_and_drop(Address *address); diff --git a/src/network/networkd-dhcp-prefix-delegation.c b/src/network/networkd-dhcp-prefix-delegation.c index 8d50da042c..169f1b3b5e 100644 --- a/src/network/networkd-dhcp-prefix-delegation.c +++ b/src/network/networkd-dhcp-prefix-delegation.c @@ -359,7 +359,7 @@ static void log_dhcp_pd_address(Link *link, const Address *address) { assert(address); assert(address->family == AF_INET6); - int log_level = address_get(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO; + int log_level = address_get_harder(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO; if (log_level < log_get_max_level()) return; diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 50d84893c6..8221fd92db 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -108,8 +108,8 @@ int link_request_dhcp_server_address(Link *link) { address->prefixlen = link->network->dhcp_server_address_prefixlen; address_set_broadcast(address, link); - if (address_get(link, address, &existing) >= 0 && - address_exists(existing) && + if (address_get_harder(link, address, &existing) >= 0 && + (address_exists(existing) || address_is_requesting(existing)) && existing->source == NETWORK_CONFIG_SOURCE_STATIC) /* The same address seems explicitly configured in [Address] or [Network] section. * Configure the DHCP server address only when it is not. */ diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 755957f5b1..00c767e1fb 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -161,7 +161,7 @@ static int verify_dhcp6_address(Link *link, const Address *address) { const char *pretty = IN6_ADDR_TO_STRING(&address->in_addr.in6); - if (address_get(link, address, &existing) < 0) { + if (address_get_harder(link, address, &existing) < 0) { /* New address. */ log_level = LOG_INFO; goto simple_log; diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network index 6d2baa3972..2a96491b52 100644 --- a/test/test-network/conf/25-address-static.network +++ b/test/test-network/conf/25-address-static.network @@ -55,6 +55,10 @@ Address=2001:db8:0:f102::16/64 Address=2001:db8:0:f103::20/128 Peer=2001:db8:0:f103::10/128 +[Address] +Address=2001:db8:0:f104::16/64 +RouteMetric=128 + [Address] Address=::/64 @@ -105,263 +109,6 @@ RouteMetric=128 Address=10.9.0.1/16 RouteMetric=hoge -# test for ENOBUFS issue #17012 -[Network] -Address=10.3.3.1/16 -Address=10.3.3.2/16 -Address=10.3.3.3/16 -Address=10.3.3.4/16 -Address=10.3.3.5/16 -Address=10.3.3.6/16 -Address=10.3.3.7/16 -Address=10.3.3.8/16 -Address=10.3.3.9/16 -Address=10.3.3.10/16 -Address=10.3.3.11/16 -Address=10.3.3.12/16 -Address=10.3.3.13/16 -Address=10.3.3.14/16 -Address=10.3.3.15/16 -Address=10.3.3.16/16 -Address=10.3.3.17/16 -Address=10.3.3.18/16 -Address=10.3.3.19/16 -Address=10.3.3.20/16 -Address=10.3.3.21/16 -Address=10.3.3.22/16 -Address=10.3.3.23/16 -Address=10.3.3.24/16 -Address=10.3.3.25/16 -Address=10.3.3.26/16 -Address=10.3.3.27/16 -Address=10.3.3.28/16 -Address=10.3.3.29/16 -Address=10.3.3.30/16 -Address=10.3.3.31/16 -Address=10.3.3.32/16 -Address=10.3.3.33/16 -Address=10.3.3.34/16 -Address=10.3.3.35/16 -Address=10.3.3.36/16 -Address=10.3.3.37/16 -Address=10.3.3.38/16 -Address=10.3.3.39/16 -Address=10.3.3.40/16 -Address=10.3.3.41/16 -Address=10.3.3.42/16 -Address=10.3.3.43/16 -Address=10.3.3.44/16 -Address=10.3.3.45/16 -Address=10.3.3.46/16 -Address=10.3.3.47/16 -Address=10.3.3.48/16 -Address=10.3.3.49/16 -Address=10.3.3.50/16 -Address=10.3.3.51/16 -Address=10.3.3.52/16 -Address=10.3.3.53/16 -Address=10.3.3.54/16 -Address=10.3.3.55/16 -Address=10.3.3.56/16 -Address=10.3.3.57/16 -Address=10.3.3.58/16 -Address=10.3.3.59/16 -Address=10.3.3.60/16 -Address=10.3.3.61/16 -Address=10.3.3.62/16 -Address=10.3.3.63/16 -Address=10.3.3.64/16 -Address=10.3.3.65/16 -Address=10.3.3.66/16 -Address=10.3.3.67/16 -Address=10.3.3.68/16 -Address=10.3.3.69/16 -Address=10.3.3.70/16 -Address=10.3.3.71/16 -Address=10.3.3.72/16 -Address=10.3.3.73/16 -Address=10.3.3.74/16 -Address=10.3.3.75/16 -Address=10.3.3.76/16 -Address=10.3.3.77/16 -Address=10.3.3.78/16 -Address=10.3.3.79/16 -Address=10.3.3.80/16 -Address=10.3.3.81/16 -Address=10.3.3.82/16 -Address=10.3.3.83/16 -Address=10.3.3.84/16 -Address=10.3.3.85/16 -Address=10.3.3.86/16 -Address=10.3.3.87/16 -Address=10.3.3.88/16 -Address=10.3.3.89/16 -Address=10.3.3.90/16 -Address=10.3.3.91/16 -Address=10.3.3.92/16 -Address=10.3.3.93/16 -Address=10.3.3.94/16 -Address=10.3.3.95/16 -Address=10.3.3.96/16 -Address=10.3.3.97/16 -Address=10.3.3.98/16 -Address=10.3.3.99/16 -Address=10.3.3.100/16 -Address=10.3.3.101/16 -Address=10.3.3.102/16 -Address=10.3.3.103/16 -Address=10.3.3.104/16 -Address=10.3.3.105/16 -Address=10.3.3.106/16 -Address=10.3.3.107/16 -Address=10.3.3.108/16 -Address=10.3.3.109/16 -Address=10.3.3.110/16 -Address=10.3.3.111/16 -Address=10.3.3.112/16 -Address=10.3.3.113/16 -Address=10.3.3.114/16 -Address=10.3.3.115/16 -Address=10.3.3.116/16 -Address=10.3.3.117/16 -Address=10.3.3.118/16 -Address=10.3.3.119/16 -Address=10.3.3.120/16 -Address=10.3.3.121/16 -Address=10.3.3.122/16 -Address=10.3.3.123/16 -Address=10.3.3.124/16 -Address=10.3.3.125/16 -Address=10.3.3.126/16 -Address=10.3.3.127/16 -Address=10.3.3.128/16 -Address=10.3.3.129/16 -Address=10.3.3.130/16 -Address=10.3.3.131/16 -Address=10.3.3.132/16 -Address=10.3.3.133/16 -Address=10.3.3.134/16 -Address=10.3.3.135/16 -Address=10.3.3.136/16 -Address=10.3.3.137/16 -Address=10.3.3.138/16 -Address=10.3.3.139/16 -Address=10.3.3.140/16 -Address=10.3.3.141/16 -Address=10.3.3.142/16 -Address=10.3.3.143/16 -Address=10.3.3.144/16 -Address=10.3.3.145/16 -Address=10.3.3.146/16 -Address=10.3.3.147/16 -Address=10.3.3.148/16 -Address=10.3.3.149/16 -Address=10.3.3.150/16 -Address=10.3.3.151/16 -Address=10.3.3.152/16 -Address=10.3.3.153/16 -Address=10.3.3.154/16 -Address=10.3.3.155/16 -Address=10.3.3.156/16 -Address=10.3.3.157/16 -Address=10.3.3.158/16 -Address=10.3.3.159/16 -Address=10.3.3.160/16 -Address=10.3.3.161/16 -Address=10.3.3.162/16 -Address=10.3.3.163/16 -Address=10.3.3.164/16 -Address=10.3.3.165/16 -Address=10.3.3.166/16 -Address=10.3.3.167/16 -Address=10.3.3.168/16 -Address=10.3.3.169/16 -Address=10.3.3.170/16 -Address=10.3.3.171/16 -Address=10.3.3.172/16 -Address=10.3.3.173/16 -Address=10.3.3.174/16 -Address=10.3.3.175/16 -Address=10.3.3.176/16 -Address=10.3.3.177/16 -Address=10.3.3.178/16 -Address=10.3.3.179/16 -Address=10.3.3.180/16 -Address=10.3.3.181/16 -Address=10.3.3.182/16 -Address=10.3.3.183/16 -Address=10.3.3.184/16 -Address=10.3.3.185/16 -Address=10.3.3.186/16 -Address=10.3.3.187/16 -Address=10.3.3.188/16 -Address=10.3.3.189/16 -Address=10.3.3.190/16 -Address=10.3.3.191/16 -Address=10.3.3.192/16 -Address=10.3.3.193/16 -Address=10.3.3.194/16 -Address=10.3.3.195/16 -Address=10.3.3.196/16 -Address=10.3.3.197/16 -Address=10.3.3.198/16 -Address=10.3.3.199/16 -Address=10.3.3.200/16 -Address=10.3.3.201/16 -Address=10.3.3.202/16 -Address=10.3.3.203/16 -Address=10.3.3.204/16 -Address=10.3.3.205/16 -Address=10.3.3.206/16 -Address=10.3.3.207/16 -Address=10.3.3.208/16 -Address=10.3.3.209/16 -Address=10.3.3.210/16 -Address=10.3.3.211/16 -Address=10.3.3.212/16 -Address=10.3.3.213/16 -Address=10.3.3.214/16 -Address=10.3.3.215/16 -Address=10.3.3.216/16 -Address=10.3.3.217/16 -Address=10.3.3.218/16 -Address=10.3.3.219/16 -Address=10.3.3.220/16 -Address=10.3.3.221/16 -Address=10.3.3.222/16 -Address=10.3.3.223/16 -Address=10.3.3.224/16 -Address=10.3.3.225/16 -Address=10.3.3.226/16 -Address=10.3.3.227/16 -Address=10.3.3.228/16 -Address=10.3.3.229/16 -Address=10.3.3.230/16 -Address=10.3.3.231/16 -Address=10.3.3.232/16 -Address=10.3.3.233/16 -Address=10.3.3.234/16 -Address=10.3.3.235/16 -Address=10.3.3.236/16 -Address=10.3.3.237/16 -Address=10.3.3.238/16 -Address=10.3.3.239/16 -Address=10.3.3.240/16 -Address=10.3.3.241/16 -Address=10.3.3.242/16 -Address=10.3.3.243/16 -Address=10.3.3.244/16 -Address=10.3.3.245/16 -Address=10.3.3.246/16 -Address=10.3.3.247/16 -Address=10.3.3.248/16 -Address=10.3.3.249/16 -Address=10.3.3.250/16 -Address=10.3.3.251/16 -Address=10.3.3.252/16 -Address=10.3.3.253/16 -Address=10.3.3.254/16 - [Address] Address=10.4.3.2/24 # just a random label which should exist diff --git a/test/test-network/conf/25-address-static.network.d/10-many-address.conf b/test/test-network/conf/25-address-static.network.d/10-many-address.conf new file mode 100644 index 0000000000..73c64c6ae8 --- /dev/null +++ b/test/test-network/conf/25-address-static.network.d/10-many-address.conf @@ -0,0 +1,258 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +[Network] +# test for ENOBUFS issue #17012 +Address=10.3.3.1/16 +Address=10.3.3.2/16 +Address=10.3.3.3/16 +Address=10.3.3.4/16 +Address=10.3.3.5/16 +Address=10.3.3.6/16 +Address=10.3.3.7/16 +Address=10.3.3.8/16 +Address=10.3.3.9/16 +Address=10.3.3.10/16 +Address=10.3.3.11/16 +Address=10.3.3.12/16 +Address=10.3.3.13/16 +Address=10.3.3.14/16 +Address=10.3.3.15/16 +Address=10.3.3.16/16 +Address=10.3.3.17/16 +Address=10.3.3.18/16 +Address=10.3.3.19/16 +Address=10.3.3.20/16 +Address=10.3.3.21/16 +Address=10.3.3.22/16 +Address=10.3.3.23/16 +Address=10.3.3.24/16 +Address=10.3.3.25/16 +Address=10.3.3.26/16 +Address=10.3.3.27/16 +Address=10.3.3.28/16 +Address=10.3.3.29/16 +Address=10.3.3.30/16 +Address=10.3.3.31/16 +Address=10.3.3.32/16 +Address=10.3.3.33/16 +Address=10.3.3.34/16 +Address=10.3.3.35/16 +Address=10.3.3.36/16 +Address=10.3.3.37/16 +Address=10.3.3.38/16 +Address=10.3.3.39/16 +Address=10.3.3.40/16 +Address=10.3.3.41/16 +Address=10.3.3.42/16 +Address=10.3.3.43/16 +Address=10.3.3.44/16 +Address=10.3.3.45/16 +Address=10.3.3.46/16 +Address=10.3.3.47/16 +Address=10.3.3.48/16 +Address=10.3.3.49/16 +Address=10.3.3.50/16 +Address=10.3.3.51/16 +Address=10.3.3.52/16 +Address=10.3.3.53/16 +Address=10.3.3.54/16 +Address=10.3.3.55/16 +Address=10.3.3.56/16 +Address=10.3.3.57/16 +Address=10.3.3.58/16 +Address=10.3.3.59/16 +Address=10.3.3.60/16 +Address=10.3.3.61/16 +Address=10.3.3.62/16 +Address=10.3.3.63/16 +Address=10.3.3.64/16 +Address=10.3.3.65/16 +Address=10.3.3.66/16 +Address=10.3.3.67/16 +Address=10.3.3.68/16 +Address=10.3.3.69/16 +Address=10.3.3.70/16 +Address=10.3.3.71/16 +Address=10.3.3.72/16 +Address=10.3.3.73/16 +Address=10.3.3.74/16 +Address=10.3.3.75/16 +Address=10.3.3.76/16 +Address=10.3.3.77/16 +Address=10.3.3.78/16 +Address=10.3.3.79/16 +Address=10.3.3.80/16 +Address=10.3.3.81/16 +Address=10.3.3.82/16 +Address=10.3.3.83/16 +Address=10.3.3.84/16 +Address=10.3.3.85/16 +Address=10.3.3.86/16 +Address=10.3.3.87/16 +Address=10.3.3.88/16 +Address=10.3.3.89/16 +Address=10.3.3.90/16 +Address=10.3.3.91/16 +Address=10.3.3.92/16 +Address=10.3.3.93/16 +Address=10.3.3.94/16 +Address=10.3.3.95/16 +Address=10.3.3.96/16 +Address=10.3.3.97/16 +Address=10.3.3.98/16 +Address=10.3.3.99/16 +Address=10.3.3.100/16 +Address=10.3.3.101/16 +Address=10.3.3.102/16 +Address=10.3.3.103/16 +Address=10.3.3.104/16 +Address=10.3.3.105/16 +Address=10.3.3.106/16 +Address=10.3.3.107/16 +Address=10.3.3.108/16 +Address=10.3.3.109/16 +Address=10.3.3.110/16 +Address=10.3.3.111/16 +Address=10.3.3.112/16 +Address=10.3.3.113/16 +Address=10.3.3.114/16 +Address=10.3.3.115/16 +Address=10.3.3.116/16 +Address=10.3.3.117/16 +Address=10.3.3.118/16 +Address=10.3.3.119/16 +Address=10.3.3.120/16 +Address=10.3.3.121/16 +Address=10.3.3.122/16 +Address=10.3.3.123/16 +Address=10.3.3.124/16 +Address=10.3.3.125/16 +Address=10.3.3.126/16 +Address=10.3.3.127/16 +Address=10.3.3.128/16 +Address=10.3.3.129/16 +Address=10.3.3.130/16 +Address=10.3.3.131/16 +Address=10.3.3.132/16 +Address=10.3.3.133/16 +Address=10.3.3.134/16 +Address=10.3.3.135/16 +Address=10.3.3.136/16 +Address=10.3.3.137/16 +Address=10.3.3.138/16 +Address=10.3.3.139/16 +Address=10.3.3.140/16 +Address=10.3.3.141/16 +Address=10.3.3.142/16 +Address=10.3.3.143/16 +Address=10.3.3.144/16 +Address=10.3.3.145/16 +Address=10.3.3.146/16 +Address=10.3.3.147/16 +Address=10.3.3.148/16 +Address=10.3.3.149/16 +Address=10.3.3.150/16 +Address=10.3.3.151/16 +Address=10.3.3.152/16 +Address=10.3.3.153/16 +Address=10.3.3.154/16 +Address=10.3.3.155/16 +Address=10.3.3.156/16 +Address=10.3.3.157/16 +Address=10.3.3.158/16 +Address=10.3.3.159/16 +Address=10.3.3.160/16 +Address=10.3.3.161/16 +Address=10.3.3.162/16 +Address=10.3.3.163/16 +Address=10.3.3.164/16 +Address=10.3.3.165/16 +Address=10.3.3.166/16 +Address=10.3.3.167/16 +Address=10.3.3.168/16 +Address=10.3.3.169/16 +Address=10.3.3.170/16 +Address=10.3.3.171/16 +Address=10.3.3.172/16 +Address=10.3.3.173/16 +Address=10.3.3.174/16 +Address=10.3.3.175/16 +Address=10.3.3.176/16 +Address=10.3.3.177/16 +Address=10.3.3.178/16 +Address=10.3.3.179/16 +Address=10.3.3.180/16 +Address=10.3.3.181/16 +Address=10.3.3.182/16 +Address=10.3.3.183/16 +Address=10.3.3.184/16 +Address=10.3.3.185/16 +Address=10.3.3.186/16 +Address=10.3.3.187/16 +Address=10.3.3.188/16 +Address=10.3.3.189/16 +Address=10.3.3.190/16 +Address=10.3.3.191/16 +Address=10.3.3.192/16 +Address=10.3.3.193/16 +Address=10.3.3.194/16 +Address=10.3.3.195/16 +Address=10.3.3.196/16 +Address=10.3.3.197/16 +Address=10.3.3.198/16 +Address=10.3.3.199/16 +Address=10.3.3.200/16 +Address=10.3.3.201/16 +Address=10.3.3.202/16 +Address=10.3.3.203/16 +Address=10.3.3.204/16 +Address=10.3.3.205/16 +Address=10.3.3.206/16 +Address=10.3.3.207/16 +Address=10.3.3.208/16 +Address=10.3.3.209/16 +Address=10.3.3.210/16 +Address=10.3.3.211/16 +Address=10.3.3.212/16 +Address=10.3.3.213/16 +Address=10.3.3.214/16 +Address=10.3.3.215/16 +Address=10.3.3.216/16 +Address=10.3.3.217/16 +Address=10.3.3.218/16 +Address=10.3.3.219/16 +Address=10.3.3.220/16 +Address=10.3.3.221/16 +Address=10.3.3.222/16 +Address=10.3.3.223/16 +Address=10.3.3.224/16 +Address=10.3.3.225/16 +Address=10.3.3.226/16 +Address=10.3.3.227/16 +Address=10.3.3.228/16 +Address=10.3.3.229/16 +Address=10.3.3.230/16 +Address=10.3.3.231/16 +Address=10.3.3.232/16 +Address=10.3.3.233/16 +Address=10.3.3.234/16 +Address=10.3.3.235/16 +Address=10.3.3.236/16 +Address=10.3.3.237/16 +Address=10.3.3.238/16 +Address=10.3.3.239/16 +Address=10.3.3.240/16 +Address=10.3.3.241/16 +Address=10.3.3.242/16 +Address=10.3.3.243/16 +Address=10.3.3.244/16 +Address=10.3.3.245/16 +Address=10.3.3.246/16 +Address=10.3.3.247/16 +Address=10.3.3.248/16 +Address=10.3.3.249/16 +Address=10.3.3.250/16 +Address=10.3.3.251/16 +Address=10.3.3.252/16 +Address=10.3.3.253/16 +Address=10.3.3.254/16 diff --git a/test/test-network/conf/25-address-static.network.d/10-override-route-metric.conf b/test/test-network/conf/25-address-static.network.d/10-override-route-metric.conf new file mode 100644 index 0000000000..da5bec2a34 --- /dev/null +++ b/test/test-network/conf/25-address-static.network.d/10-override-route-metric.conf @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +[Address] +Address=10.9.0.1/16 +RouteMetric=256 + +[Address] +Address=2001:db8:0:f104::16/64 +RouteMetric=256 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index c1a017d16b..7c13af58e8 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -2329,20 +2329,8 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): def tearDown(self): tear_down_common() - def test_address_static(self): - # test for #22515. The address will be removed and replaced with /64 prefix. - check_output('ip link add dummy98 type dummy') - check_output('ip link set dev dummy98 up') - check_output('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98') - self.wait_address('dummy98', '2001:db8:0:f101::15/128', ipv='-6') - check_output('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98') - self.wait_address('dummy98', '10.3.2.3/16 brd 10.3.255.250', ipv='-4') - - copy_network_unit('25-address-static.network', '12-dummy.netdev') - start_networkd() - - self.wait_online(['dummy98:routable']) - + def verify_address_static(self, route_metric): + # IPv4 addresses output = check_output('ip -4 address show dev dummy98') print(output) self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output) @@ -2351,16 +2339,13 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output) self.assertIn('inet 10.8.8.1/16 scope global dummy98', output) self.assertIn('inet 10.8.8.2/16 brd 10.8.8.128 scope global secondary dummy98', output) - self.assertRegex(output, 'inet 10.9.0.1/16 (metric 128 |)brd 10.9.255.255 scope global dummy98') - - # test for ENOBUFS issue #17012 - for i in range(1, 254): - self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output) + self.assertRegex(output, rf'inet 10.9.0.1/16 (metric {route_metric} |)brd 10.9.255.255 scope global dummy98') # invalid sections self.assertNotIn('10.10.0.1/16', output) self.assertNotIn('10.10.0.2/16', output) + # address labels output = check_output('ip -4 address show dev dummy98 label 32') self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output) @@ -2373,10 +2358,15 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): output = check_output('ip -4 address show dev dummy98 label 35') self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35') - output = check_output('ip -4 route show dev dummy98') + # check metric of prefix route + output = check_output('ip -4 route show dev dummy98 10.9.0.0/16') print(output) - self.assertIn('10.9.0.0/16 proto kernel scope link src 10.9.0.1 metric 128', output) + self.assertIn(f'10.9.0.0/16 proto kernel scope link src 10.9.0.1 metric {route_metric}', output) + output = check_output('ip -6 route show dev dummy98 2001:db8:0:f104::/64') + print(output) + self.assertIn(f'2001:db8:0:f104::/64 proto kernel metric {route_metric}', output) + # IPv6 addresses output = check_output('ip -6 address show dev dummy98') print(output) self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output) @@ -2384,11 +2374,40 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output) self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output) self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output) + self.assertRegex(output, rf'inet6 2001:db8:0:f104::16/64 (metric {route_metric} |)scope global') self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output) self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global') + # netlabel self.check_netlabel('dummy98', r'10\.4\.3\.0/24') + output = check_output(*networkctl_cmd, '--json=short', 'status', env=env) + check_json(output) + + def test_address_static(self): + # test for #22515. The address will be removed and replaced with /64 prefix. + check_output('ip link add dummy98 type dummy') + check_output('ip link set dev dummy98 up') + check_output('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98') + self.wait_address('dummy98', '2001:db8:0:f101::15/128', ipv='-6') + check_output('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98') + self.wait_address('dummy98', '10.3.2.3/16 brd 10.3.255.250', ipv='-4') + + copy_network_unit('25-address-static.network', '12-dummy.netdev', copy_dropins=False) + start_networkd() + + self.wait_online(['dummy98:routable']) + self.verify_address_static(route_metric=128) + + copy_network_unit('25-address-static.network.d/10-override-route-metric.conf') + networkctl_reload() + self.wait_online(['dummy98:routable']) + self.verify_address_static(route_metric=256) + + networkctl_reconfigure('dummy98') + self.wait_online(['dummy98:routable']) + self.verify_address_static(route_metric=256) + # Tests for #20891. # 1. set preferred lifetime forever to drop the deprecated flag for testing #20891. check_output('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever') @@ -2412,14 +2431,20 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output) - # test for ENOBUFS issue #17012 + # test for ENOBUFS issue #17012 (with reload) + copy_network_unit('25-address-static.network.d/10-many-address.conf') + networkctl_reload() + self.wait_online(['dummy98:routable']) output = check_output('ip -4 address show dev dummy98') for i in range(1, 254): self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output) - output = check_output(*networkctl_cmd, '--json=short', 'status', env=env) - check_json(output) - + # (with reconfigure) + networkctl_reconfigure('dummy98') + self.wait_online(['dummy98:routable']) + output = check_output('ip -4 address show dev dummy98') + for i in range(1, 254): + self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output) def test_address_null(self): copy_network_unit('25-address-null.network', '12-dummy.netdev')