Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Sep 2015 11:19:54 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288062 - in head/sys: netinet netinet6
Message-ID:  <201509211119.t8LBJsLE077569@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Mon Sep 21 11:19:53 2015
New Revision: 288062
URL: https://svnweb.freebsd.org/changeset/base/288062

Log:
  Unify nd6 state switching by using newly-created nd6_llinfo_setstate()
    function. The change is mostly mechanical with the following exception:
  Last piece of nd6_resolve_slow() was refactored: ND6_LLINFO_PERMANENT
    condition was removed as always-true, explicit ND6_LLINFO_NOSTATE ->
    ND6_LLINFO_INCOMPLETE state transition was removed as duplicate.
  
  Reviewed by:	ae
  Sponsored by:	Yandex LLC

Modified:
  head/sys/netinet/toecore.c
  head/sys/netinet6/nd6.c
  head/sys/netinet6/nd6.h
  head/sys/netinet6/nd6_nbr.c

Modified: head/sys/netinet/toecore.c
==============================================================================
--- head/sys/netinet/toecore.c	Mon Sep 21 10:27:30 2015	(r288061)
+++ head/sys/netinet/toecore.c	Mon Sep 21 11:19:53 2015	(r288062)
@@ -468,7 +468,6 @@ restart:
 		lle = nd6_alloc(&sin6->sin6_addr, 0, ifp);
 		if (lle == NULL)
 			return (ENOMEM); /* Couldn't create entry in cache. */
-		lle->ln_state = ND6_LLINFO_INCOMPLETE;
 		IF_AFDATA_WLOCK(ifp);
 		LLE_WLOCK(lle);
 		lle_tmp = nd6_lookup(&sin6->sin6_addr, ND6_EXCLUSIVE, ifp);
@@ -478,8 +477,7 @@ restart:
 		IF_AFDATA_WUNLOCK(ifp);
 		if (lle_tmp == NULL) {
 			/* Arm timer for newly-created entry and send NS */
-			nd6_llinfo_settimer_locked(lle,
-			    (long)ND_IFINFO(ifp)->retrans * hz / 1000);
+			nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE);
 			LLE_WUNLOCK(lle);
 
 			nd6_ns_output(ifp, NULL, NULL, &sin6->sin6_addr, 0);
@@ -503,8 +501,7 @@ restart:
 		LLE_WLOCK_ASSERT(lle);
 
 		lle->la_asked = 0;
-		lle->ln_state = ND6_LLINFO_DELAY;
-		nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
+		nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY);
 	}
 
 	if (lle->la_flags & LLE_VALID) {

Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c	Mon Sep 21 10:27:30 2015	(r288061)
+++ head/sys/netinet6/nd6.c	Mon Sep 21 11:19:53 2015	(r288062)
@@ -539,6 +539,44 @@ nd6_llinfo_get_holdsrc(struct llentry *l
 	return (src);
 }
 
+/*
+ * Switch @lle state to new state optionally arming timers.
+ */
+void
+nd6_llinfo_setstate(struct llentry *lle, int newstate)
+{
+	struct ifnet *ifp;
+	long delay;
+
+	delay = 0;
+
+	switch (newstate) {
+	case ND6_LLINFO_INCOMPLETE:
+		ifp = lle->lle_tbl->llt_ifp;
+		delay = (long)ND_IFINFO(ifp)->retrans * hz / 1000;
+		break;
+	case ND6_LLINFO_REACHABLE:
+		if (!ND6_LLINFO_PERMANENT(lle)) {
+			ifp = lle->lle_tbl->llt_ifp;
+			delay = (long)ND_IFINFO(ifp)->reachable * hz;
+		}
+		break;
+	case ND6_LLINFO_STALE:
+		delay = (long)V_nd6_gctimer * hz;
+		break;
+	case ND6_LLINFO_DELAY:
+		lle->la_asked = 0;
+		delay = (long)V_nd6_delay * hz;
+		break;
+	}
+
+	if (delay > 0)
+		nd6_llinfo_settimer_locked(lle, delay);
+
+	lle->ln_state = newstate;
+}
+
+
 void
 nd6_llinfo_settimer(struct llentry *ln, long tick)
 {
@@ -638,10 +676,8 @@ nd6_llinfo_timer(void *arg)
 		}
 		break;
 	case ND6_LLINFO_REACHABLE:
-		if (!ND6_LLINFO_PERMANENT(ln)) {
-			ln->ln_state = ND6_LLINFO_STALE;
-			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
-		}
+		if (!ND6_LLINFO_PERMANENT(ln))
+			nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 		break;
 
 	case ND6_LLINFO_STALE:
@@ -657,12 +693,10 @@ nd6_llinfo_timer(void *arg)
 		if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
 			/* We need NUD */
 			ln->la_asked = 1;
-			ln->ln_state = ND6_LLINFO_PROBE;
+			nd6_llinfo_setstate(ln, ND6_LLINFO_PROBE);
 			send_ns = 1;
-		} else {
-			ln->ln_state = ND6_LLINFO_STALE; /* XXX */
-			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
-		}
+		} else
+			nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); /* XXX */
 		break;
 	case ND6_LLINFO_PROBE:
 		if (ln->la_asked < V_nd6_umaxtries) {
@@ -1316,11 +1350,7 @@ nd6_nud_hint(struct rtentry *rt, struct 
 		}
 	}
 
- 	ln->ln_state = ND6_LLINFO_REACHABLE;
-	if (!ND6_LLINFO_PERMANENT(ln)) {
-		nd6_llinfo_settimer_locked(ln,
-		    (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
-	}
+ 	nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
 done:
 	LLE_WUNLOCK(ln);
 }
@@ -1740,8 +1770,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
 		if (ln_tmp == NULL) {
 			/* No existing lle, mark as new entry */
 			is_newentry = 1;
-			ln->ln_state = ND6_LLINFO_STALE;
-			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
+			nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 		} else {
 			lltable_free_entry(LLTABLE6(ifp), ln);
 			ln = ln_tmp;
@@ -1788,8 +1817,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
 		 */
 		bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
 		ln->la_flags |= LLE_VALID;
-		ln->ln_state = ND6_LLINFO_STALE;
-		nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
+		nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 
 		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
 
@@ -1892,9 +1920,7 @@ nd6_grab_holdchain(struct llentry *ln, s
 		 * detection on expiration.
 		 * (RFC 2461 7.3.3)
 		 */
-		ln->la_asked = 0;
-		ln->ln_state = ND6_LLINFO_DELAY;
-		nd6_llinfo_settimer_locked(ln, (long)V_nd6_delay * hz);
+		nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY);
 	}
 }
 
@@ -2034,6 +2060,8 @@ nd6_resolve_slow(struct ifnet *ifp, stru
     const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
 {
 	struct llentry *lle = NULL, *lle_tmp;
+	struct in6_addr *psrc, src;
+	int send_ns;
 
 	/*
 	 * Address resolution or Neighbor Unreachability Detection
@@ -2061,7 +2089,6 @@ nd6_resolve_slow(struct ifnet *ifp, stru
 				m_freem(m);
 				return (ENOBUFS);
 			}
-			lle->ln_state = ND6_LLINFO_NOSTATE;
 
 			IF_AFDATA_WLOCK(ifp);
 			LLE_WLOCK(lle);
@@ -2097,11 +2124,8 @@ nd6_resolve_slow(struct ifnet *ifp, stru
 	 * neighbor unreachability detection on expiration.
 	 * (RFC 2461 7.3.3)
 	 */
-	if (lle->ln_state == ND6_LLINFO_STALE) {
-		lle->la_asked = 0;
-		lle->ln_state = ND6_LLINFO_DELAY;
-		nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
-	}
+	if (lle->ln_state == ND6_LLINFO_STALE)
+		nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY);
 
 	/*
 	 * If the neighbor cache entry has a state other than INCOMPLETE
@@ -2123,8 +2147,6 @@ nd6_resolve_slow(struct ifnet *ifp, stru
 	 * does not exceed nd6_maxqueuelen.  When it exceeds nd6_maxqueuelen,
 	 * the oldest packet in the queue will be removed.
 	 */
-	if (lle->ln_state == ND6_LLINFO_NOSTATE)
-		lle->ln_state = ND6_LLINFO_INCOMPLETE;
 
 	if (lle->la_hold != NULL) {
 		struct mbuf *m_hold;
@@ -2151,20 +2173,22 @@ nd6_resolve_slow(struct ifnet *ifp, stru
 	/*
 	 * If there has been no NS for the neighbor after entering the
 	 * INCOMPLETE state, send the first solicitation.
+	 * Note that for newly-created lle la_asked will be 0,
+	 * so we will transition from ND6_LLINFO_NOSTATE to
+	 * ND6_LLINFO_INCOMPLETE state here.
 	 */
-	if (!ND6_LLINFO_PERMANENT(lle) && lle->la_asked == 0) {
-		struct in6_addr src, *psrc;
+	psrc = NULL;
+	send_ns = 0;
+	if (lle->la_asked == 0) {
 		lle->la_asked++;
-		
-		nd6_llinfo_settimer_locked(lle,
-		    (long)ND_IFINFO(ifp)->retrans * hz / 1000);
+		send_ns = 1;
 		psrc = nd6_llinfo_get_holdsrc(lle, &src);
-		LLE_WUNLOCK(lle);
-		nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL);
-	} else {
-		/* We did the lookup so we need to do the unlock here. */
-		LLE_WUNLOCK(lle);
+
+		nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE);
 	}
+	LLE_WUNLOCK(lle);
+	if (send_ns != 0)
+		nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL);
 
 	return (EWOULDBLOCK);
 }

Modified: head/sys/netinet6/nd6.h
==============================================================================
--- head/sys/netinet6/nd6.h	Mon Sep 21 10:27:30 2015	(r288061)
+++ head/sys/netinet6/nd6.h	Mon Sep 21 11:19:53 2015	(r288062)
@@ -409,6 +409,7 @@ int nd6_options(union nd_opts *);
 struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
 struct llentry *nd6_alloc(const struct in6_addr *, int, struct ifnet *);
 void nd6_setmtu(struct ifnet *);
+void nd6_llinfo_setstate(struct llentry *lle, int newstate);
 void nd6_llinfo_settimer(struct llentry *, long);
 void nd6_llinfo_settimer_locked(struct llentry *, long);
 void nd6_timer(void *);

Modified: head/sys/netinet6/nd6_nbr.c
==============================================================================
--- head/sys/netinet6/nd6_nbr.c	Mon Sep 21 10:27:30 2015	(r288061)
+++ head/sys/netinet6/nd6_nbr.c	Mon Sep 21 11:19:53 2015	(r288062)
@@ -769,16 +769,10 @@ nd6_na_input(struct mbuf *m, int off, in
 		ln->la_flags |= LLE_VALID;
 		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
 		if (is_solicited) {
-			ln->ln_state = ND6_LLINFO_REACHABLE;
+			nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
 			ln->ln_byhint = 0;
-			if (!ND6_LLINFO_PERMANENT(ln)) {
-				nd6_llinfo_settimer_locked(ln,
-				    (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
-			}
-		} else {
-			ln->ln_state = ND6_LLINFO_STALE;
-			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
-		}
+		} else
+			nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 		if ((ln->ln_router = is_router) != 0) {
 			/*
 			 * This means a router's state has changed from
@@ -829,10 +823,8 @@ nd6_na_input(struct mbuf *m, int off, in
 			 * If state is REACHABLE, make it STALE.
 			 * no other updates should be done.
 			 */
-			if (ln->ln_state == ND6_LLINFO_REACHABLE) {
-				ln->ln_state = ND6_LLINFO_STALE;
-				nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
-			}
+			if (ln->ln_state == ND6_LLINFO_REACHABLE)
+				nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 			goto freeit;
 		} else if (is_override				   /* (2a) */
 			|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
@@ -853,18 +845,11 @@ nd6_na_input(struct mbuf *m, int off, in
 			 * changed, make it STALE.
 			 */
 			if (is_solicited) {
-				ln->ln_state = ND6_LLINFO_REACHABLE;
 				ln->ln_byhint = 0;
-				if (!ND6_LLINFO_PERMANENT(ln)) {
-					nd6_llinfo_settimer_locked(ln,
-					    (long)ND_IFINFO(ifp)->reachable * hz);
-				}
+				nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
 			} else {
-				if (lladdr != NULL && llchange) {
-					ln->ln_state = ND6_LLINFO_STALE;
-					nd6_llinfo_settimer_locked(ln,
-					    (long)V_nd6_gctimer * hz);
-				}
+				if (lladdr != NULL && llchange)
+					nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
 			}
 		}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509211119.t8LBJsLE077569>