networkd: link - track state of IPv6LL address

This is managed by the kernel, but we should track whether or not we have
a configured IPv6LL address. This fixes two issues:
 - we now wait for IPv6LL before considering the link ready
 - we now wait for IPv6LL before attempting to do NDisc or DHCPv6
   these protocols relies on an LL address being available.
This commit is contained in:
Tom Gundersen 2015-11-10 21:30:59 +01:00
parent 3b015d40c1
commit e7ab854c6c
3 changed files with 75 additions and 23 deletions

View File

@ -329,6 +329,7 @@ static int address_release(Address *address) {
int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) {
bool ready;
int r;
assert(address);
assert(cinfo);
@ -342,8 +343,17 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
if (address->link) {
link_update_operstate(address->link);
if (!ready && address_is_ready(address))
if (!ready && address_is_ready(address)) {
link_check_ready(address->link);
if (address->family == AF_INET6 &&
in_addr_is_link_local(AF_INET6, &address->in_addr) &&
!address->link->ipv6ll_address) {
r = link_ipv6ll_gained(address->link);
if (r < 0)
return r;
}
}
}
return 0;

View File

@ -603,6 +603,10 @@ void link_check_ready(Link *link) {
!link->ipv4ll_route)
return;
if (link_ipv6ll_enabled(link))
if (!link->ipv6ll_address)
return;
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
!link->dhcp4_configured) ||
(link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
@ -1238,6 +1242,34 @@ static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
}
}
static int link_acquire_ipv6_conf(Link *link) {
int r;
assert(link);
if (link_dhcp6_enabled(link)) {
assert(link->dhcp6_client);
log_link_debug(link, "Acquiring DHCPv6 lease");
r = sd_dhcp6_client_start(link->dhcp6_client);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
}
if (link_ipv6_accept_ra_enabled(link)) {
assert(link->ndisc_router_discovery);
log_link_debug(link, "Discovering IPv6 routers");
r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
if (r < 0)
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
}
return 0;
}
static int link_acquire_conf(Link *link) {
int r;
@ -1266,26 +1298,6 @@ static int link_acquire_conf(Link *link) {
return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
}
if (link_dhcp6_enabled(link)) {
assert(link->dhcp6_client);
log_link_debug(link, "Acquiring DHCPv6 lease");
r = sd_dhcp6_client_start(link->dhcp6_client);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
}
if (link_ipv6_accept_ra_enabled(link)) {
assert(link->ndisc_router_discovery);
log_link_debug(link, "Discovering IPv6 routers");
r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
if (r < 0)
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
}
if (link_lldp_enabled(link)) {
assert(link->lldp);
@ -2093,6 +2105,12 @@ static int link_configure(Link *link) {
r = link_acquire_conf(link);
if (r < 0)
return r;
if (link->ipv6ll_address) {
r = link_acquire_ipv6_conf(link);
if (r < 0)
return r;
}
}
return link_enter_join_netdev(link);
@ -2439,6 +2457,27 @@ failed:
return r;
}
int link_ipv6ll_gained(Link *link) {
int r;
assert(link);
log_link_info(link, "Gained IPv6LL");
link->ipv6ll_address = true;
link_check_ready(link);
if (link->network) {
r = link_acquire_ipv6_conf(link);
if (r < 0) {
link_enter_failed(link);
return r;
}
}
return 0;
}
static int link_carrier_gained(Link *link) {
int r;

View File

@ -99,8 +99,9 @@ struct Link {
bool ndisc_configured;
sd_ipv4ll *ipv4ll;
bool ipv4ll_address;
bool ipv4ll_route;
bool ipv4ll_address:1;
bool ipv4ll_route:1;
bool ipv6ll_address:1;
bool static_configured;
@ -143,6 +144,8 @@ int link_save(Link *link);
int link_carrier_reset(Link *link);
bool link_has_carrier(Link *link);
int link_ipv6ll_gained(Link *link);
int link_set_mtu(Link *link, uint32_t mtu);
int link_set_hostname(Link *link, const char *hostname);
int link_set_timezone(Link *link, const char *timezone);