diff options
author | Fernando Gont <fgont@si6networks.com> | 2020-03-28 01:30:04 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-04-02 13:19:13 +0200 |
commit | 2da092b5922b823b51ec5ff5ad6e8d6d41c82a69 (patch) | |
tree | d88726d69aa5b39ae592716b1640f38a416d3034 | |
parent | 5feba97cd186f662fb944087dca9cbfb7a643132 (diff) | |
download | NetworkManager-2da092b5922b823b51ec5ff5ad6e8d6d41c82a69.tar.gz |
IPv6 SLAAC: Honor small PIO Valid Lifetimes
This commit implements Section 4.2 of
<https://tools.ietf.org/html/draft-gont-6man-slaac-renum-05>, to improve the
reaction of IPv6 SLAAC to renumbering events.
Namely:
* It honors PIO Valid Lifetimes < 2 hours, deviating from item "e)"
(pp. 19-20) of Section 5.5.3 of RFC4862.
[thaller@redhat.com: squash commits and adjust unit test]
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/454
-rw-r--r-- | src/ndisc/nm-ndisc.c | 39 | ||||
-rw-r--r-- | src/ndisc/tests/test-ndisc-fake.c | 5 |
2 files changed, 18 insertions, 26 deletions
diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index 5e556084e8..bb3a92b05d 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -442,8 +442,15 @@ nm_ndisc_add_address (NMNDisc *ndisc, } if (existing) { + /* A Valid Lifetime of 0 eliminates the corresponding address(es). This deviates + * from RFC4862 Section 5.5.3, item e), as recommended in IETF draft draft-gont-6man-slaac-renum. + */ + if (new->lifetime == 0) { + g_array_remove_index (rdata->addresses, i); + return TRUE; + } + if (from_ra) { - const gint32 NM_NDISC_PREFIX_LFT_MIN = 7200; /* seconds, RFC4862 5.5.3.e */ gint64 old_expiry_lifetime, old_expiry_preferred; old_expiry_lifetime = get_expiry (existing); @@ -452,25 +459,16 @@ nm_ndisc_add_address (NMNDisc *ndisc, if (new->lifetime == NM_NDISC_INFINITY) existing->lifetime = NM_NDISC_INFINITY; else { - gint64 new_lifetime, remaining_lifetime; + gint64 new_lifetime; - /* see RFC4862 5.5.3.e */ - if (existing->lifetime == NM_NDISC_INFINITY) - remaining_lifetime = G_MAXINT64; - else - remaining_lifetime = ((gint64) existing->timestamp) + ((gint64) existing->lifetime) - ((gint64) now_s); + /* Honor small valid lifetimes, as discussed in + * draft-gont-6man-slaac-renum, to allow for more timelier + * reaction to renumbering events. This deviates from + * RFC4862 Section 5.5.3, item e). + */ new_lifetime = ((gint64) new->timestamp) + ((gint64) new->lifetime) - ((gint64) now_s); - - if ( new_lifetime > (gint64) NM_NDISC_PREFIX_LFT_MIN - || new_lifetime > remaining_lifetime) { - existing->timestamp = now_s; - existing->lifetime = CLAMP (new_lifetime, (gint64) 0, (gint64) (G_MAXUINT32 - 1)); - } else if (remaining_lifetime <= (gint64) NM_NDISC_PREFIX_LFT_MIN) { - /* keep the current lifetime. */ - } else { - existing->timestamp = now_s; - existing->lifetime = NM_NDISC_PREFIX_LFT_MIN; - } + existing->timestamp = now_s; + existing->lifetime = CLAMP (new_lifetime, (gint64) 0, (gint64) (G_MAXUINT32 - 1)); } if (new->preferred == NM_NDISC_INFINITY) { @@ -487,11 +485,6 @@ nm_ndisc_add_address (NMNDisc *ndisc, || old_expiry_preferred != get_expiry_preferred (existing); } - if (new->lifetime == 0) { - g_array_remove_index (rdata->addresses, i); - return TRUE; - } - if ( get_expiry (existing) == get_expiry (new) && get_expiry_preferred (existing) == get_expiry_preferred (new)) return FALSE; diff --git a/src/ndisc/tests/test-ndisc-fake.c b/src/ndisc/tests/test-ndisc-fake.c index 91fe9802d7..7a5eea012d 100644 --- a/src/ndisc/tests/test-ndisc-fake.c +++ b/src/ndisc/tests/test-ndisc-fake.c @@ -217,9 +217,8 @@ test_everything_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed g_assert_cmpint (rdata->gateways_n, ==, 1); match_gateway (rdata, 0, "fe80::2", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - g_assert_cmpint (rdata->addresses_n, ==, 2); - match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 0); - match_address (rdata, 1, "2001:db8:a:b::1", data->timestamp1, 10, 10); + g_assert_cmpint (rdata->addresses_n, ==, 1); + match_address (rdata, 0, "2001:db8:a:b::1", data->timestamp1, 10, 10); g_assert_cmpint (rdata->routes_n, ==, 1); match_route (rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1, 10, 10); g_assert_cmpint (rdata->dns_servers_n, ==, 1); |