inet6: Send initial NS in a timely fashion.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 17 Aug 2015 12:31:01 +0000 (20:31 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 18 Aug 2015 01:24:36 +0000 (09:24 +0800)
The call of nd6_rtrequest() in nd6_output() sets the newly created
neighbor cache entry expire to time_uptime, which prevents the NS
output at the end of nd6_output().  Though the NS will be sent when
the neighbor cache times out, it will cause large delay (0~1s).

sys/netinet6/nd6.c

index 6a6abbd..deb03dc 100644 (file)
@@ -1976,8 +1976,19 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
         * 7.2.2 of RFC 2461, because the timer is set correctly after sending
         * an NS below.
         */
-       if (ln->ln_state == ND6_LLINFO_NOSTATE)
+       if (ln->ln_state == ND6_LLINFO_NOSTATE) {
+               /*
+                * This neighbor cache entry was just created; change its
+                * state to INCOMPLETE and start its life cycle.
+                *
+                * We force an NS output below by setting ln_expire to 1
+                * (nd6_rtrequest() could set it to the current time_uptime)
+                * and zeroing out ln_asked (XXX this may not be necessary).
+                */
                ln->ln_state = ND6_LLINFO_INCOMPLETE;
+               ln->ln_expire = 1;
+               ln->ln_asked = 0;
+       }
        if (ln->ln_hold)
                m_freem(ln->ln_hold);
        ln->ln_hold = m;