Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet6 inet6: Re-introduce ND6_LLINFO_WAITDELETE so we...



details:   https://anonhg.NetBSD.org/src/rev/29a0f3a2e70e
branches:  trunk
changeset: 459260:29a0f3a2e70e
user:      roy <roy%NetBSD.org@localhost>
date:      Sun Sep 01 19:26:21 2019 +0000

description:
inet6: Re-introduce ND6_LLINFO_WAITDELETE so we can return EHOSTDOWN

Once we've sent nd6_mmaxtries NS messages, send RTM_MISS and move to the
ND6_LLINFO_WAITDELETE state rather than freeing the llentry right away.
Wait for a probe cycle and then free the llentry.

If a connection attempts to re-use the llentry during ND6_LLINFO_WAITDELETE,
return EHOSTDOWN (or EHOSTUNREACH if a gateway) to match inet behaviour.
Continue to ND6_LLINFO_INCOMPLETE and send another NS probe in hope of a
reply. Rinse and repeat.

This reverts part of nd6.c r1.14 - an 18 year old commit!

diffstat:

 sys/netinet6/nd6.c |  39 ++++++++++++++++++++++++++++++---------
 sys/netinet6/nd6.h |  11 ++---------
 2 files changed, 32 insertions(+), 18 deletions(-)

diffs (121 lines):

diff -r 69e25d958cf2 -r 29a0f3a2e70e sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c        Sun Sep 01 19:20:45 2019 +0000
+++ b/sys/netinet6/nd6.c        Sun Sep 01 19:26:21 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $    */
+/*     $NetBSD: nd6.c,v 1.263 2019/09/01 19:26:21 roy Exp $    */
 /*     $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $   */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.263 2019/09/01 19:26:21 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -480,9 +480,14 @@
        ndi = ND_IFINFO(ifp);
 
        switch (ln->ln_state) {
+       case ND6_LLINFO_WAITDELETE:
+               LLE_REMREF(ln);
+               nd6_free(ln, 0);
+               ln = NULL;
+               break;
+
        case ND6_LLINFO_INCOMPLETE:
-               if (ln->ln_asked < nd6_mmaxtries) {
-                       ln->ln_asked++;
+               if (ln->ln_asked++ < nd6_mmaxtries) {
                        send_ns = true;
                        break;
                }
@@ -506,9 +511,17 @@
                sockaddr_in6_init(&sin6, taddr6, 0, 0, 0);
                rt_clonedmsg(RTM_MISS, sin6tosa(&sin6), NULL, ifp);
 
-               LLE_REMREF(ln);
-               nd6_free(ln, 0);
-               ln = NULL;
+               /*
+                * Move to the ND6_LLINFO_WAITDELETE state for another
+                * interval at which point the llentry will be freed
+                * unless it's attempted to be used again and we'll
+                * resend NS again, rinse and repeat.
+                */
+               ln->ln_state = ND6_LLINFO_WAITDELETE;
+               if (ln->ln_asked == nd6_mmaxtries)
+                       nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000);
+               else
+                       send_ns = true;
                break;
 
        case ND6_LLINFO_REACHABLE:
@@ -2312,6 +2325,7 @@
        struct llentry *ln = NULL;
        bool created = false;
        const struct sockaddr_in6 *dst = satocsin6(_dst);
+       int error;
 
        /* discard the packet if IPv6 operation is disabled on the interface */
        if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
@@ -2406,7 +2420,8 @@
         * does not exceed nd6_maxqueuelen.  When it exceeds nd6_maxqueuelen,
         * the oldest packet in the queue will be removed.
         */
-       if (ln->ln_state == ND6_LLINFO_NOSTATE)
+       if (ln->ln_state == ND6_LLINFO_NOSTATE ||
+           ln->ln_state == ND6_LLINFO_WAITDELETE)
                ln->ln_state = ND6_LLINFO_INCOMPLETE;
        if (ln->ln_hold) {
                struct mbuf *m_hold;
@@ -2430,6 +2445,12 @@
                ln->ln_hold = m;
        }
 
+       if (ln->ln_asked >= nd6_mmaxtries)
+               error = (rt != NULL && rt->rt_flags & RTF_GATEWAY) ?
+                   EHOSTUNREACH : EHOSTDOWN;
+       else
+               error = EWOULDBLOCK;
+
        /*
         * If there has been no NS for the neighbor after entering the
         * INCOMPLETE state, send the first solicitation.
@@ -2448,7 +2469,7 @@
        if (created)
                nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr);
 
-       return EWOULDBLOCK;
+       return error;
 }
 
 int
diff -r 69e25d958cf2 -r 29a0f3a2e70e sys/netinet6/nd6.h
--- a/sys/netinet6/nd6.h        Sun Sep 01 19:20:45 2019 +0000
+++ b/sys/netinet6/nd6.h        Sun Sep 01 19:26:21 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nd6.h,v 1.86 2018/03/06 10:57:00 roy Exp $     */
+/*     $NetBSD: nd6.h,v 1.87 2019/09/01 19:26:21 roy Exp $     */
 /*     $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $    */
 
 /*
@@ -38,14 +38,7 @@
 
 #define ND6_LLINFO_PURGE       -3
 #define ND6_LLINFO_NOSTATE     -2
-/*
- * We don't need the WAITDELETE state any more, but we keep the definition
- * in a comment line instead of removing it. This is necessary to avoid
- * unintentionally reusing the value for another purpose, which might
- * affect backward compatibility with old applications.
- * (20000711 jinmei%kame.net@localhost)
- */
-/* #define ND6_LLINFO_WAITDELETE       -1 */
+#define ND6_LLINFO_WAITDELETE  -1
 #define ND6_LLINFO_INCOMPLETE  0
 #define ND6_LLINFO_REACHABLE   1
 #define ND6_LLINFO_STALE       2



Home | Main Index | Thread Index | Old Index