network: always check dynamic address assignments before entering configured state

Previously (v248 or earlier), even if no static address is configured,
the link did not enter configured state, as e.g. Link::static_addresses_configured
is false until the link gained its carrier.
But, after the commit 1187fc3375, the
situation was changed. Static addresses, routes, and etc are requested even
if the link does not have its carrier, and thus the link enters configured
state when no static address and etc are specified.

This makes the link does not enter configured state before it gains its
carrier when at least one of dynamic address assignment protocols (e.g.
DHCP) except for NDISC is enabled.

Note that, unfortunately, netplan always enables ConfigureWithoutCarrier=
for all virtual devices, e.g. bridge. See,
978e20f902
So, we need to support e.g. the following strange config:
```
[Netowkr]
ConfigureWithoutCarrier=yes
DHCP=yes
```

Fixes #19855.
This commit is contained in:
Yu Watanabe 2021-06-11 20:34:17 +09:00
parent 740b638267
commit 4bcb862548

View file

@ -469,46 +469,49 @@ void link_check_ready(Link *link) {
if (!link->sr_iov_configured)
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
if (link_has_carrier(link) || !link->network->configure_without_carrier) {
bool has_ndisc_address = false;
NDiscAddress *n;
/* IPv6LL is assigned after the link gains its carrier. */
if (!link->network->configure_without_carrier &&
link_ipv6ll_enabled(link) &&
!in6_addr_is_set(&link->ipv6ll_address))
return (void) log_link_debug(link, "%s(): IPv6LL is not configured yet.", __func__);
if (link_ipv6ll_enabled(link) && !in6_addr_is_set(&link->ipv6ll_address))
return (void) log_link_debug(link, "%s(): IPv6LL is not configured yet.", __func__);
SET_FOREACH(n, link->ndisc_addresses)
if (!n->marked) {
has_ndisc_address = true;
break;
}
if ((link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) || link_ipv4ll_enabled(link)) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
!link->ipv4ll_address_configured)
/* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
return (void) log_link_debug(link, "%s(): DHCP4, DHCP6 or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
link_ipv6_accept_ra_enabled(link) || link_ipv4ll_enabled(link)) {
if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
!(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!link->ipv4ll_address_configured)
/* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
log_link_debug(link, "%s(): dhcp4:%s ipv4ll:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
__func__,
yes_no(link->dhcp4_configured),
yes_no(link->ipv4ll_address_configured),
yes_no(link->dhcp6_address_configured),
yes_no(link->dhcp6_route_configured),
yes_no(link->dhcp6_pd_address_configured),
yes_no(link->dhcp6_pd_route_configured),
yes_no(link->ndisc_addresses_configured),
yes_no(link->ndisc_routes_configured));
bool has_ndisc_address = false;
NDiscAddress *n;
SET_FOREACH(n, link->ndisc_addresses)
if (!n->marked) {
has_ndisc_address = true;
break;
}
if ((link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) || link_ipv4ll_enabled(link)) &&
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
!link->ipv4ll_address_configured)
/* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
return (void) log_link_debug(link, "%s(): DHCP4, DHCP6 or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
/* Ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
(!link->network->configure_without_carrier && link_ipv6_accept_ra_enabled(link)) ||
link_ipv4ll_enabled(link)) {
if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
!(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!link->ipv4ll_address_configured)
/* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
log_link_debug(link, "%s(): dhcp4:%s ipv4ll:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
__func__,
yes_no(link->dhcp4_configured),
yes_no(link->ipv4ll_address_configured),
yes_no(link->dhcp6_address_configured),
yes_no(link->dhcp6_route_configured),
yes_no(link->dhcp6_pd_address_configured),
yes_no(link->dhcp6_pd_route_configured),
yes_no(link->ndisc_addresses_configured),
yes_no(link->ndisc_routes_configured));
}
link_set_state(link, LINK_STATE_CONFIGURED);