Source-Changes-HG archive

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

[src/trunk]: src/sys ARP: Use ND rather than our own.



details:   https://anonhg.NetBSD.org/src/rev/c04580042f32
branches:  trunk
changeset: 938584:c04580042f32
user:      roy <roy%NetBSD.org@localhost>
date:      Fri Sep 11 15:16:00 2020 +0000

description:
ARP: Use ND rather than our own.

This brings the benefit of Neighbour Unreachability Detection which is
something ARP sorely lacks.

The new timings mirror those of IPv6 and are adjustable via sysctl(8).
Unlike IPv6 ND, these are global and not per interface.

diffstat:

 sys/net/if_llatbl.c     |    7 +-
 sys/netinet/if_arp.c    |  568 ++++++++++++++++++++++++-----------------------
 sys/netinet/if_inarp.h  |    5 +-
 sys/netinet/tcp_input.c |   13 +-
 4 files changed, 310 insertions(+), 283 deletions(-)

diffs (truncated from 865 to 300 lines):

diff -r 4932b6ca413d -r c04580042f32 sys/net/if_llatbl.c
--- a/sys/net/if_llatbl.c       Fri Sep 11 15:08:25 2020 +0000
+++ b/sys/net/if_llatbl.c       Fri Sep 11 15:16:00 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_llatbl.c,v 1.32 2020/09/11 15:01:26 roy Exp $       */
+/*     $NetBSD: if_llatbl.c,v 1.33 2020/09/11 15:16:00 roy Exp $       */
 /*
  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
@@ -717,6 +717,11 @@
                        lle->la_flags |= LLE_PUB;
                lle->la_flags |= LLE_VALID;
                switch (dst->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       lle->ln_state = ND_LLINFO_REACHABLE;
+                       break;
+#endif
 #ifdef INET6
                case AF_INET6:
                        lle->ln_state = ND_LLINFO_REACHABLE;
diff -r 4932b6ca413d -r c04580042f32 sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Fri Sep 11 15:08:25 2020 +0000
+++ b/sys/netinet/if_arp.c      Fri Sep 11 15:16:00 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_arp.c,v 1.294 2020/03/09 21:20:55 roy Exp $ */
+/*     $NetBSD: if_arp.c,v 1.295 2020/09/11 15:16:00 roy Exp $ */
 
 /*
  * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.294 2020/03/09 21:20:55 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.295 2020/09/11 15:16:00 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -108,6 +108,7 @@
 #include <net/if_types.h>
 #include <net/if_ether.h>
 #include <net/if_llatbl.h>
+#include <net/nd.h>
 #include <net/route.h>
 #include <net/net_stats.h>
 
@@ -132,12 +133,36 @@
  */
 #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
 
-/* timer values */
-static int arpt_keep = (20*60);        /* once resolved, good for 20 more minutes */
-static int arpt_down = 20;             /* once declared down, don't send for 20 secs */
-static int arp_maxhold = 1;    /* number of packets to hold per ARP entry */
-#define        rt_expire rt_rmx.rmx_expire
-#define        rt_pksent rt_rmx.rmx_pksent
+/* timers */
+static int arp_reachable = REACHABLE_TIME;
+static int arp_retrans = RETRANS_TIMER;
+static int arp_perform_nud = 1;
+
+static bool arp_nud_enabled(struct ifnet *);
+static unsigned int arp_llinfo_reachable(struct ifnet *);
+static unsigned int arp_llinfo_retrans(struct ifnet *);
+static union nd_addr *arp_llinfo_holdsrc(struct llentry *, union nd_addr *);
+static void arp_llinfo_output(struct ifnet *, const union nd_addr *,
+    const union nd_addr *, const uint8_t *, const union nd_addr *);
+static void arp_llinfo_missed(struct ifnet *, const union nd_addr *,
+    struct mbuf *);
+static void arp_free(struct llentry *, int);
+
+static struct nd_domain arp_nd_domain = {
+       .nd_family = AF_INET,
+       .nd_delay = 5,          /* delay first probe time 5 second */
+       .nd_mmaxtries = 3,      /* maximum broadcast query */
+       .nd_umaxtries = 3,      /* maximum unicast query */
+       .nd_maxnudhint = 0,     /* max # of subsequent upper layer hints */
+       .nd_maxqueuelen = 1,    /* max # of packets in unresolved ND entries */
+       .nd_nud_enabled = arp_nud_enabled,
+       .nd_reachable = arp_llinfo_reachable,
+       .nd_retrans = arp_llinfo_retrans,
+       .nd_holdsrc = arp_llinfo_holdsrc,
+       .nd_output = arp_llinfo_output,
+       .nd_missed = arp_llinfo_missed,
+       .nd_free = arp_free,
+};
 
 int ip_dad_count = PROBE_NUM;
 #ifdef ARP_DEBUG
@@ -151,14 +176,10 @@
 
 static void arprequest(struct ifnet *,
     const struct in_addr *, const struct in_addr *,
-    const uint8_t *);
+    const uint8_t *, const uint8_t *);
 static void arpannounce1(struct ifaddr *);
 static struct sockaddr *arp_setgate(struct rtentry *, struct sockaddr *,
     const struct sockaddr *);
-static void arptimer(void *);
-static void arp_settimer(struct llentry *, int);
-static struct llentry *arplookup(struct ifnet *,
-    const struct in_addr *, const struct sockaddr *, int);
 static struct llentry *arpcreate(struct ifnet *,
     const struct in_addr *, const struct sockaddr *, int);
 static void in_arpinput(struct mbuf *);
@@ -173,8 +194,6 @@
 static void arp_dad_stop(struct ifaddr *);
 static void arp_dad_duplicated(struct ifaddr *, const struct sockaddr_dl *);
 
-static void arp_init_llentry(struct ifnet *, struct llentry *);
-
 struct ifqueue arpintrq = {
        .ifq_head = NULL,
        .ifq_tail = NULL,
@@ -182,7 +201,6 @@
        .ifq_maxlen = 50,
        .ifq_drops = 0,
 };
-static int arp_maxtries = 5;
 static int useloopback = 1;    /* use loopback interface for local traffic */
 
 static percpu_t *arpstat_percpu;
@@ -257,6 +275,7 @@
        MOWNER_ATTACH(&arpdomain.dom_mowner);
 #endif
 
+       nd_attach_domain(&arp_nd_domain);
        arp_dad_init();
 }
 
@@ -278,98 +297,6 @@
        lltable_drain(AF_INET);
 }
 
-static void
-arptimer(void *arg)
-{
-       struct llentry *lle = arg;
-       struct ifnet *ifp;
-
-       KASSERT((lle->la_flags & LLE_STATIC) == 0);
-
-       LLE_WLOCK(lle);
-
-       /*
-        * This shortcut is required to avoid trying to touch ifp that may be
-        * being destroyed.
-        */
-       if ((lle->la_flags & LLE_LINKED) == 0) {
-               LLE_FREE_LOCKED(lle);
-               return;
-       }
-
-       ifp = lle->lle_tbl->llt_ifp;
-
-       /* XXX: LOR avoidance. We still have ref on lle. */
-       LLE_WUNLOCK(lle);
-
-       IF_AFDATA_LOCK(ifp);
-       LLE_WLOCK(lle);
-
-       /* Guard against race with other llentry_free(). */
-       if (lle->la_flags & LLE_LINKED) {
-               int rt_cmd;
-               struct in_addr *in;
-               struct sockaddr_in dsin, ssin;
-               struct sockaddr *sa;
-               const char *lladdr;
-               size_t pkts_dropped;
-
-               in = &lle->r_l3addr.addr4;
-               sockaddr_in_init(&dsin, in, 0);
-               if (lle->la_flags & LLE_VALID) {
-                       rt_cmd = RTM_DELETE;
-                       sa = NULL;
-                       lladdr = (const char *)&lle->ll_addr;
-               } else {
-                       if (lle->la_hold != NULL) {
-                               struct mbuf *m = lle->la_hold;
-                               const struct ip *ip = mtod(m, const struct ip *);
-
-                               sockaddr_in_init(&ssin, &ip->ip_src, 0);
-                               sa = sintosa(&ssin);
-                       } else
-                               sa = NULL;
-                       rt_cmd = RTM_MISS;
-                       lladdr = NULL;
-
-               }
-               rt_clonedmsg(rt_cmd, sa, sintosa(&dsin), lladdr, ifp);
-
-               LLE_REMREF(lle);
-               pkts_dropped = llentry_free(lle);
-               ARP_STATADD(ARP_STAT_DFRDROPPED, pkts_dropped);
-               ARP_STATADD(ARP_STAT_DFRTOTAL, pkts_dropped);
-       } else {
-               LLE_FREE_LOCKED(lle);
-       }
-
-       IF_AFDATA_UNLOCK(ifp);
-}
-
-static void
-arp_settimer(struct llentry *la, int sec)
-{
-
-       LLE_WLOCK_ASSERT(la);
-       KASSERT((la->la_flags & LLE_STATIC) == 0);
-
-       /*
-        * We have to take care of a reference leak which occurs if
-        * callout_reset overwrites a pending callout schedule.  Unfortunately
-        * we don't have a mean to know the overwrite, so we need to know it
-        * using callout_stop.  We need to call callout_pending first to exclude
-        * the case that the callout has never been scheduled.
-        */
-       if (callout_pending(&la->la_timer)) {
-               bool expired = callout_stop(&la->la_timer);
-               if (!expired)
-                       /* A pending callout schedule is canceled. */
-                       LLE_REMREF(la);
-       }
-       LLE_ADDREF(la);
-       callout_reset(&la->la_timer, hz * sec, arptimer, la);
-}
-
 /*
  * We set the gateway for RTF_CLONING routes to a "prototype"
  * link-layer sockaddr whose interface type (if_type) and interface
@@ -409,17 +336,6 @@
        return gate;
 }
 
-static void
-arp_init_llentry(struct ifnet *ifp, struct llentry *lle)
-{
-
-       switch (ifp->if_type) {
-       default:
-               /* Nothing. */
-               break;
-       }
-}
-
 /*
  * Parallel to llc_rtrequest.
  */
@@ -478,13 +394,6 @@
                if ((rt->rt_flags & RTF_CONNECTED) ||
                    (rt->rt_flags & RTF_LOCAL)) {
                        /*
-                        * Give this route an expiration time, even though
-                        * it's a "permanent" route, so that routes cloned
-                        * from it do not need their expiration time set.
-                        */
-                       KASSERT(time_uptime != 0);
-                       rt->rt_expire = time_uptime;
-                       /*
                         * linklayers with particular link MTU limitation.
                         */
                        switch (ifp->if_type) {
@@ -552,7 +461,6 @@
                 * interface. So check RTF_LOCAL instead.
                 */
                if (rt->rt_flags & RTF_LOCAL) {
-                       rt->rt_expire = 0;
                        if (useloopback) {
                                rt->rt_ifp = lo0ifp;
                                rt->rt_rmx.rmx_mtu = 0;
@@ -567,7 +475,6 @@
                        goto out;
                }
 
-               rt->rt_expire = 0;
                if (useloopback) {
                        rt->rt_ifp = lo0ifp;
                        rt->rt_rmx.rmx_mtu = 0;
@@ -603,7 +510,7 @@
 static void
 arprequest(struct ifnet *ifp,
     const struct in_addr *sip, const struct in_addr *tip,
-    const uint8_t *enaddr)
+    const uint8_t *saddr, const uint8_t *taddr)
 {
        struct mbuf *m;
        struct arphdr *ah;
@@ -612,7 +519,7 @@
 
        KASSERT(sip != NULL);
        KASSERT(tip != NULL);
-       KASSERT(enaddr != NULL);
+       KASSERT(saddr != NULL);
 
        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
                return;
@@ -644,12 +551,15 @@
        ah->ar_hln = ifp->if_addrlen;           /* hardware address length */
        ah->ar_pln = sizeof(struct in_addr);    /* protocol address length */
        ah->ar_op = htons(ARPOP_REQUEST);



Home | Main Index | Thread Index | Old Index