Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Apr 2026 22:58:50 +0000
From:      Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5f27592e149f - main - nd6: Break nd6_prefix_lifetime_update out of prelist_update
Message-ID:  <69e2bb2a.369f6.41d75342@gitrepo.freebsd.org>

index | next in thread | raw e-mail

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, &lt6_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, &lt6_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;
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e2bb2a.369f6.41d75342>