git: 5f27592e149f - main - nd6: Break nd6_prefix_lifetime_update out of prelist_update
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Apr 2026 22:58:50 UTC
The branch main has been updated by pouria:
URL: https://cgit.FreeBSD.org/src/commit/?id=5f27592e149fbbb6318ef6c4b72482e1a7a41ef4
commit 5f27592e149fbbb6318ef6c4b72482e1a7a41ef4
Author: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
AuthorDate: 2026-04-17 14:16:51 +0000
Commit: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-04-17 22:52:21 +0000
nd6: Break nd6_prefix_lifetime_update out of prelist_update
Logic of updating prefix lifetime is big enough that deserves
its own function.
While here, fix style.
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D56135
---
sys/netinet6/nd6_rtr.c | 207 ++++++++++++++++++++++++-------------------------
1 file changed, 100 insertions(+), 107 deletions(-)
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 2a73007d5118..e0ea36586985 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -1552,6 +1552,80 @@ nd6_prefix_update(struct nd_prefixctl *new, struct nd_prefix *pr)
}
}
+/*
+ * RFC 4862 5.5.3 (e): update the lifetimes according to the "two hours" rule
+ * and the privacy extension.
+ * We apply some clarifications in rfc2462bis:
+ * - use remaininglifetime instead of storedlifetime as a variable name
+ * - remove the dead code in the "two-hour" rule
+ */
+static void
+nd6_prefix_lifetime_update(struct nd_prefixctl *new, struct nd_prefix *pr,
+ struct in6_ifaddr *ia6, bool auth)
+{
+ struct in6_addrlifetime lt6_tmp;
+ uint32_t remaininglifetime;
+
+ NET_EPOCH_ASSERT();
+
+#define TWOHOUR (120*60)
+ lt6_tmp = ia6->ia6_lifetime;
+ if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
+ remaininglifetime = ND6_INFINITE_LIFETIME;
+ else if (time_uptime - ia6->ia6_updatetime > lt6_tmp.ia6t_vltime)
+ /* The case of "invalid" address. We should usually not see this case. */
+ remaininglifetime = 0;
+ else
+ remaininglifetime = lt6_tmp.ia6t_vltime - (time_uptime - ia6->ia6_updatetime);
+
+ /* when not updating, keep the current stored lifetime. */
+ lt6_tmp.ia6t_vltime = remaininglifetime;
+
+ if (TWOHOUR < new->ndpr_vltime || remaininglifetime < new->ndpr_vltime) {
+ lt6_tmp.ia6t_vltime = new->ndpr_vltime;
+ } else if (remaininglifetime <= TWOHOUR) {
+ if (auth)
+ lt6_tmp.ia6t_vltime = new->ndpr_vltime;
+ } else {
+ /* new->ndpr_vltime <= TWOHOUR && TWOHOUR < remaininglifetime */
+ lt6_tmp.ia6t_vltime = TWOHOUR;
+ }
+
+ /* The 2 hour rule is not imposed for preferred lifetime. */
+ lt6_tmp.ia6t_pltime = new->ndpr_pltime;
+
+ in6_init_address_ltimes(pr, <6_tmp);
+
+ /*
+ * We need to treat lifetimes for temporary addresses differently, according
+ * to draft-ietf-ipv6-privacy-addrs-v2-01.txt 3.3 (1);
+ * we only update the lifetimes when they are in the maximum intervals.
+ */
+ if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
+ uint32_t maxvltime, maxpltime, vltime;
+
+ vltime = time_uptime - ia6->ia6_createtime + V_ip6_desync_factor;
+ if (V_ip6_temp_valid_lifetime > vltime)
+ maxvltime = V_ip6_temp_valid_lifetime - vltime;
+ else
+ maxvltime = 0;
+ if (V_ip6_temp_preferred_lifetime > vltime)
+ maxpltime = V_ip6_temp_preferred_lifetime - vltime;
+ else
+ maxpltime = 0;
+
+ if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
+ lt6_tmp.ia6t_vltime > maxvltime)
+ lt6_tmp.ia6t_vltime = maxvltime;
+
+ if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
+ lt6_tmp.ia6t_pltime > maxpltime)
+ lt6_tmp.ia6t_pltime = maxpltime;
+ }
+ ia6->ia6_lifetime = lt6_tmp;
+ ia6->ia6_updatetime = time_uptime;
+}
+
static void
prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
bool auth, int mcast)
@@ -1561,7 +1635,6 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
struct ifnet *ifp = new->ndpr_ifp;
struct nd_prefix *pr;
int error = 0;
- struct in6_addrlifetime lt6_tmp;
char ip6buf[INET6_ADDRSTRLEN];
bool has_temporary = false;
@@ -1622,14 +1695,13 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
* add it to the list). We first check if we have a matching prefix.
*/
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- struct in6_ifaddr *ifa6;
- uint32_t remaininglifetime;
+ struct in6_ifaddr *ia6;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- ifa6 = (struct in6_ifaddr *)ifa;
- if (!(ifa6->ia6_flags & IN6_IFF_AUTOCONF))
+ ia6 = (struct in6_ifaddr *)ifa;
+ if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
continue;
/*
@@ -1637,122 +1709,43 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
* or is associated with a prefix that is different from this
* one. (pr is never NULL here)
*/
- if (ifa6->ia6_ndpr != pr)
+ if (ia6->ia6_ndpr != pr)
continue;
/*
- * An already autoconfigured address matched. Now that we
- * are sure there is at least one matched address, we can
- * proceed to 5.5.3. (e): update the lifetimes according to the
- * "two hours" rule and the privacy extension.
- * We apply some clarifications in rfc2462bis:
- * - use remaininglifetime instead of storedlifetime as a
- * variable name
- * - remove the dead code in the "two-hour" rule
+ * An already autoconfigured address matched.
+ * Now that we are sure there is at least one matched address.
*/
-#define TWOHOUR (120*60)
- lt6_tmp = ifa6->ia6_lifetime;
+ nd6_prefix_lifetime_update(new, pr, ia6, auth);
- if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
- remaininglifetime = ND6_INFINITE_LIFETIME;
- else if (time_uptime - ifa6->ia6_updatetime >
- lt6_tmp.ia6t_vltime) {
+ if ((ifp->if_inet6->nd_flags & ND6_IFF_STABLEADDR) != 0) {
/*
- * The case of "invalid" address. We should usually
- * not see this case.
+ * if stable addresses (RFC 7217) are enabled, mark that
+ * a temporary address has been found to avoid generating
+ * uneeded extra ones.
*/
- remaininglifetime = 0;
- } else
- remaininglifetime = lt6_tmp.ia6t_vltime -
- (time_uptime - ifa6->ia6_updatetime);
-
- /* when not updating, keep the current stored lifetime. */
- lt6_tmp.ia6t_vltime = remaininglifetime;
-
- if (TWOHOUR < new->ndpr_vltime ||
- remaininglifetime < new->ndpr_vltime) {
- lt6_tmp.ia6t_vltime = new->ndpr_vltime;
- } else if (remaininglifetime <= TWOHOUR) {
- if (auth) {
- lt6_tmp.ia6t_vltime = new->ndpr_vltime;
- }
- } else {
- /*
- * new->ndpr_vltime <= TWOHOUR &&
- * TWOHOUR < remaininglifetime
- */
- lt6_tmp.ia6t_vltime = TWOHOUR;
- }
-
- /* The 2 hour rule is not imposed for preferred lifetime. */
- lt6_tmp.ia6t_pltime = new->ndpr_pltime;
-
- in6_init_address_ltimes(pr, <6_tmp);
-
- /*
- * We need to treat lifetimes for temporary addresses
- * differently, according to
- * draft-ietf-ipv6-privacy-addrs-v2-01.txt 3.3 (1);
- * we only update the lifetimes when they are in the maximum
- * intervals.
- */
- if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
- u_int32_t maxvltime, maxpltime;
+ if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0)
+ has_temporary = true;
/*
- * if stable addresses (RFC 7217) are enabled, mark that a temporary address has been found
- * to avoid generating uneeded extra ones.
+ * If using stable addresses (RFC 7217) and we still have retries
+ * to perform, ignore addresses already marked as duplicated, since
+ * a new one will be generated. Also ignore addresses marked as
+ * temporary, since their generation is orthogonal to opaque stable ones.
+ *
+ * There is a small race condition, in that the dad_counter could be
+ * incremented between here and when a new address is generated, but this
+ * will cause that generation to fail and no further retries should happen.
*/
- if (ifp->if_inet6->nd_flags & ND6_IFF_STABLEADDR)
- has_temporary = true;
-
- if (V_ip6_temp_valid_lifetime >
- (u_int32_t)((time_uptime - ifa6->ia6_createtime) +
- V_ip6_desync_factor)) {
- maxvltime = V_ip6_temp_valid_lifetime -
- (time_uptime - ifa6->ia6_createtime) -
- V_ip6_desync_factor;
- } else
- maxvltime = 0;
- if (V_ip6_temp_preferred_lifetime >
- (u_int32_t)((time_uptime - ifa6->ia6_createtime) +
- V_ip6_desync_factor)) {
- maxpltime = V_ip6_temp_preferred_lifetime -
- (time_uptime - ifa6->ia6_createtime) -
- V_ip6_desync_factor;
- } else
- maxpltime = 0;
-
- if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
- lt6_tmp.ia6t_vltime > maxvltime) {
- lt6_tmp.ia6t_vltime = maxvltime;
- }
- if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
- lt6_tmp.ia6t_pltime > maxpltime) {
- lt6_tmp.ia6t_pltime = maxpltime;
- }
+ if (atomic_load_int(&DAD_FAILURES(ifp)) <= V_ip6_stableaddr_maxretries &&
+ (ia6->ia6_flags & (IN6_IFF_DUPLICATED | IN6_IFF_TEMPORARY)) != 0)
+ continue;
}
- ifa6->ia6_lifetime = lt6_tmp;
- ifa6->ia6_updatetime = time_uptime;
-
- /*
- * If using stable addresses (RFC 7217) and we still have retries to perform, ignore
- * addresses already marked as duplicated, since a new one will be generated.
- * Also ignore addresses marked as temporary, since their generation is orthogonal to
- * opaque stable ones.
- *
- * There is a small race condition, in that the dad_counter could be incremented
- * between here and when a new address is generated, but this will cause that generation
- * to fail and no further retries should happen.
- */
- if (ifp->if_inet6->nd_flags & ND6_IFF_STABLEADDR &&
- atomic_load_int(&DAD_FAILURES(ifp)) <= V_ip6_stableaddr_maxretries &&
- ifa6->ia6_flags & (IN6_IFF_DUPLICATED | IN6_IFF_TEMPORARY))
- continue;
if (ia6_match == NULL) /* remember the first one */
- ia6_match = ifa6;
+ ia6_match = ia6;
}
+
if (ia6_match == NULL && new->ndpr_vltime) {
int ifidlen;