Hello Patrik! On 10/04/15 13:03, Patrik Flykt wrote: > When setting IPv6 addresses acquired by DHCPv6, systemd-networkd sets > the IFA_F_NOPREFIXROUTE flag in the IFA_FLAGS netlink attribute. As > the flag and the attribute are present starting with Linux 3.14, older > kernels will need systemd-network to manage prefix route expiry. > > By default, DHCPv6 addresses are first assigned setting the > IFA_F_NOPREFIXROUTE flag in the IFA_FLAGS netlink attribute. Should > the address assignment fail, the same assignment is tried without > the IFA_FLAGS attribute. Should also the second attempt fail, an error > is printed and address assignment ends with failure. As successful use > of the IFA_FLAGS netlink attribute is recorded in the Link structure, > the DHCPv6 code will know if the kernel or systemd-network fallback > code handles expiring prefixes. > > The prefix expiration and IPv6 address updating fallback code is > resurrected from the parts deleted with commit > 47d45d3cde45d6545367570264e4e3636bc9e345. > > This patch can be removed once the minimum kernel requirements are > greater than or equal to 3.14. > --- > > Hi, > > Version 2 attempts to resolve IPv6 address assignment issues at run time, > first by adding IFA_FLAGS, then without. > > Please test with kernels < 3.14 and >= 3.14.
While the patch itself looks good to me, I cannot test it right now, as I actually never used networkd before. > src/network/networkd-address.c | 2 +- > src/network/networkd-dhcp6.c | 66 > ++++++++++++++++++++++++++++++++++++++++-- > src/network/networkd-link.c | 1 + > src/network/networkd-link.h | 1 + > 4 files changed, 67 insertions(+), 3 deletions(-) > > diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c > index 85acc49..df836d3 100644 > --- a/src/network/networkd-address.c > +++ b/src/network/networkd-address.c > @@ -215,7 +215,7 @@ int address_update(Address *address, Link *link, > if (r < 0) > return log_error_errno(r, "Could not set flags: %m"); > > - if (address->flags & ~0xff) { > + if (address->flags & ~0xff && link->rtnl_extended_attrs) { > r = sd_rtnl_message_append_u32(req, IFA_FLAGS, > address->flags); > if (r < 0) > return log_error_errno(r, "Could not set extended > flags: %m"); > diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c > index e863f4b..5668fdf 100644 > --- a/src/network/networkd-dhcp6.c > +++ b/src/network/networkd-dhcp6.c > @@ -28,6 +28,8 @@ > #include "sd-icmp6-nd.h" > #include "sd-dhcp6-client.h" > > +static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); > + > static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, > Link *link) { > return 0; > @@ -42,6 +44,15 @@ static int dhcp6_address_handler(sd_rtnl *rtnl, > sd_rtnl_message *m, > > r = sd_rtnl_message_get_errno(m); > if (r < 0 && r != -EEXIST) { > + if (link->rtnl_extended_attrs) { > + log_link_warning(link, "Could not set extended > netlink attributes, reverting to fallback mechanism"); > + > + link->rtnl_extended_attrs = false; > + dhcp6_lease_address_acquired(link->dhcp6_client, > link); > + > + return 1; > + } > + > log_link_error(link, "Could not set DHCPv6 address: %s", > strerror(-r)); > > @@ -67,7 +78,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr > *ip6_addr, > memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); > > addr->flags = IFA_F_NOPREFIXROUTE; > - addr->prefixlen = 64; > + addr->prefixlen = prefixlen; > > addr->cinfo.ifa_prefered = lifetime_preferred; > addr->cinfo.ifa_valid = lifetime_valid; > @@ -262,6 +273,52 @@ static int dhcp6_configure(Link *link, int event) { > return r; > } > > +static int dhcp6_prefix_expired(Link *link) { > + int r; > + sd_dhcp6_lease *lease; > + struct in6_addr *expired_prefix, ip6_addr; > + uint8_t expired_prefixlen; > + uint32_t lifetime_preferred, lifetime_valid; > + > + r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery, > + &expired_prefix, &expired_prefixlen); > + if (r < 0) > + return r; > + > + r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease); > + if (r < 0) > + return r; > + > + log_link_struct(link, LOG_INFO, > + "MESSAGE=%-*s: IPv6 prefix > "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired", > + IFNAMSIZ, link->ifname, > + SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix), > + expired_prefixlen, NULL); > + > + sd_dhcp6_lease_reset_address_iter(lease); > + > + while (sd_dhcp6_lease_get_address(lease, &ip6_addr, > + &lifetime_preferred, > + &lifetime_valid) >= 0) { > + > + r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen, > + &ip6_addr); > + if (r < 0) > + continue; > + > + log_link_struct(link, LOG_INFO, > + "MESSAGE=%-*s: IPv6 prefix length updated > "SD_ICMP6_ADDRESS_FORMAT_STR"/%d", > + IFNAMSIZ, link->ifname, > + SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128, > + NULL); > + > + dhcp6_address_update(link, &ip6_addr, 128, > lifetime_preferred, > + lifetime_valid); > + } > + > + return 0; > +} > + > static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) > { > Link *link = userdata; > > @@ -274,7 +331,6 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int > event, void *userdata) { > > switch(event) { > case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE: > - case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED: > return; > > case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT: > @@ -284,6 +340,12 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int > event, void *userdata) { > > break; > > + case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED: > + if (!link->rtnl_extended_attrs) > + dhcp6_prefix_expired(link); > + > + break; > + > default: > if (event < 0) > log_link_warning(link, "ICMPv6 error: %s", > diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c > index 3bd37d8..d00a828 100644 > --- a/src/network/networkd-link.c > +++ b/src/network/networkd-link.c > @@ -227,6 +227,7 @@ static int link_new(Manager *manager, sd_rtnl_message > *message, Link **ret) { > link->n_ref = 1; > link->manager = manager; > link->state = LINK_STATE_PENDING; > + link->rtnl_extended_attrs = true; > link->ifindex = ifindex; > link->ifname = strdup(ifname); > if (!link->ifname) > diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h > index 479098c..c3bc1b9 100644 > --- a/src/network/networkd-link.h > +++ b/src/network/networkd-link.h > @@ -82,6 +82,7 @@ struct Link { > > sd_icmp6_nd *icmp6_router_discovery; > sd_dhcp6_client *dhcp6_client; > + bool rtnl_extended_attrs; > > sd_lldp *lldp; > char *lldp_file; Best regards, Alexander. _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel