networkd-ndisc: Don't add NDisc route for local address (#4467)

When systemd-networkd is run on the same IPv6 enabled interface where
radvd is announcing prefixes, a route is being set up pointing to the
interface address. As this will fail with an invalid argument error,
the link is marked as failed and the following message like the
following will appear in in the logs:

systemd-networkd[21459]: eth1: Could not set NDisc route or address: Invalid argument
systemd-networkd[21459]: eth1: Failed

Should the interface be required by systemd-networkd-wait-online,
network-online.target will wait until its timeout hits thereby
significantly delaying system startup.

The fix is to check whether the gateway address obtained from NDisc
messages is equal to any of the interface addresses on the same link
and not set the NDisc route in that case.
This commit is contained in:
Patrik Flykt 2016-10-24 14:44:01 +03:00 committed by Lennart Poettering
parent 366ddd252e
commit 6d7c761572
1 changed files with 28 additions and 0 deletions

View File

@ -57,6 +57,8 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
unsigned preference;
usec_t time_now;
int r;
Address *address;
Iterator i;
assert(link);
assert(rt);
@ -75,6 +77,32 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
return;
}
SET_FOREACH(address, link->addresses, i) {
if (!memcmp(&gateway, &address->in_addr.in6,
sizeof(address->in_addr.in6))) {
char buffer[INET6_ADDRSTRLEN];
log_link_debug(link, "No NDisc route added, gateway %s matches local address",
inet_ntop(AF_INET6,
&address->in_addr.in6,
buffer, sizeof(buffer)));
return;
}
}
SET_FOREACH(address, link->addresses_foreign, i) {
if (!memcmp(&gateway, &address->in_addr.in6,
sizeof(address->in_addr.in6))) {
char buffer[INET6_ADDRSTRLEN];
log_link_debug(link, "No NDisc route added, gateway %s matches local address",
inet_ntop(AF_INET6,
&address->in_addr.in6,
buffer, sizeof(buffer)));
return;
}
}
r = sd_ndisc_router_get_preference(rt, &preference);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");