Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Implement RFC 7048, making Neighbor Unreachability Detec...
details: https://anonhg.NetBSD.org/src/rev/eb9a37d392a2
branches: trunk
changeset: 955032:eb9a37d392a2
user: roy <roy%NetBSD.org@localhost>
date: Tue Sep 15 10:05:36 2020 +0000
description:
Implement RFC 7048, making Neighbor Unreachability Detection less impatient
RFC 7048 Section 3 says in the UNREACHABLE state packets continue to be
sent to the link-layer address and then backoff exponentially.
We adjust this slightly and move to the INCOMPLETE state after
`nd_mmaxtries` probes and then start backing off.
This results in simpler code whilst providing a more robust model which
doubles the time to failure over what we did before.
We don't want to be back to the old ARP model where no unreachability
errors are returned because very few applications would look at
unreachability hints provided such as ND_LLINFO_UNREACHABLE or RTM_MISS.
diffstat:
sys/net/nd.c | 77 +++++++++++++++++++++++++++++++++++++++------------
sys/net/nd.h | 25 ++++++++++------
sys/netinet/if_arp.c | 10 ++++--
sys/netinet6/nd6.c | 26 ++++++++++++----
4 files changed, 99 insertions(+), 39 deletions(-)
diffs (truncated from 321 to 300 lines):
diff -r 8f74d1818f3d -r eb9a37d392a2 sys/net/nd.c
--- a/sys/net/nd.c Tue Sep 15 09:33:12 2020 +0000
+++ b/sys/net/nd.c Tue Sep 15 10:05:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: */
+/* $NetBSD: nd.c,v 1.3 2020/09/15 10:05:36 roy Exp $ */
/*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd.c,v 1.2 2020/09/14 15:09:57 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd.c,v 1.3 2020/09/15 10:05:36 roy Exp $");
#include <sys/callout.h>
#include <sys/mbuf.h>
@@ -56,7 +56,8 @@
struct ifnet *ifp = NULL;
struct psref psref;
struct mbuf *m = NULL;
- bool send_ns = false, missed = false;
+ bool send_ns = false;
+ uint16_t missed = 0;
union l3addr taddr, *daddrp = NULL;
SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
@@ -84,10 +85,9 @@
break;
case ND_LLINFO_INCOMPLETE:
- if (ln->ln_asked++ < nd->nd_mmaxtries) {
- send_ns = true;
+ send_ns = true;
+ if (ln->ln_asked++ < nd->nd_mmaxtries)
break;
- }
if (ln->ln_hold) {
struct mbuf *m0, *mnxt;
@@ -107,12 +107,8 @@
ln->ln_hold = NULL;
}
- missed = true;
+ missed = ND_LLINFO_INCOMPLETE;
ln->ln_state = ND_LLINFO_WAITDELETE;
- if (ln->ln_asked == nd->nd_mmaxtries)
- nd_set_timer(ln, ND_TIMER_RETRANS);
- else
- send_ns = true;
break;
case ND_LLINFO_REACHABLE:
@@ -144,23 +140,50 @@
break;
case ND_LLINFO_PROBE:
- if (ln->ln_asked < nd->nd_umaxtries) {
- ln->ln_asked++;
- send_ns = true;
+ send_ns = true;
+ if (ln->ln_asked++ < nd->nd_umaxtries) {
daddrp = &taddr;
} else {
- LLE_REMREF(ln);
- nd->nd_free(ln, 0);
- ln = NULL;
+ ln->ln_state = ND_LLINFO_UNREACHABLE;
+ ln->ln_asked = 1;
+ missed = ND_LLINFO_PROBE;
+ /* nd_missed() consumers can use missed to know if
+ * they need to send ICMP UNREACHABLE or not. */
}
break;
+ case ND_LLINFO_UNREACHABLE:
+ /*
+ * RFC 7048 Section 3 says in the UNREACHABLE state
+ * packets continue to be sent to the link-layer address and
+ * then backoff exponentially.
+ * We adjust this slightly and move to the INCOMPLETE state
+ * after nd_mmaxtries probes and then start backing off.
+ *
+ * This results in simpler code whilst providing a more robust
+ * model which doubles the time to failure over what we did
+ * before. We don't want to be back to the old ARP model where
+ * no unreachability errors are returned because very
+ * few applications would look at unreachability hints provided
+ * such as ND_LLINFO_UNREACHABLE or RTM_MISS.
+ */
+ send_ns = true;
+ if (ln->ln_asked++ < nd->nd_mmaxtries)
+ break;
+
+ missed = ND_LLINFO_UNREACHABLE;
+ ln->ln_state = ND_LLINFO_WAITDELETE;
+ ln->la_flags &= ~LLE_VALID;
+ break;
}
if (send_ns) {
uint8_t lladdr[255], *lladdrp;
union l3addr src, *psrc;
- nd_set_timer(ln, ND_TIMER_RETRANS);
+ if (ln->ln_state == ND_LLINFO_WAITDELETE)
+ nd_set_timer(ln, ND_TIMER_RETRANS_BACKOFF);
+ else
+ nd_set_timer(ln, ND_TIMER_RETRANS);
if (ln->ln_state > ND_LLINFO_INCOMPLETE &&
ln->la_flags & LLE_VALID)
{
@@ -181,7 +204,7 @@
SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
if (missed)
- nd->nd_missed(ifp, &taddr, m);
+ nd->nd_missed(ifp, &taddr, missed, m);
if (ifp != NULL)
if_release(ifp, &psref);
}
@@ -241,6 +264,22 @@
case ND_TIMER_RETRANS:
xtick = nd->nd_retrans(ifp) * hz / 1000;
break;
+ case ND_TIMER_RETRANS_BACKOFF:
+ {
+ unsigned int retrans = nd->nd_retrans(ifp);
+ unsigned int attempts = ln->ln_asked - nd->nd_mmaxtries;
+
+ xtick = retrans;
+ while (attempts-- != 0) {
+ xtick *= nd->nd_retransmultiple;
+ if (xtick > nd->nd_maxretrans || xtick < retrans) {
+ xtick = nd->nd_maxretrans;
+ break;
+ }
+ }
+ xtick = xtick * hz / 1000;
+ break;
+ }
case ND_TIMER_REACHABLE:
xtick = nd->nd_reachable(ifp) * hz / 1000;
break;
diff -r 8f74d1818f3d -r eb9a37d392a2 sys/net/nd.h
--- a/sys/net/nd.h Tue Sep 15 09:33:12 2020 +0000
+++ b/sys/net/nd.h Tue Sep 15 10:05:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nd.h,v 1.2 2020/09/14 15:09:57 roy Exp $ */
+/* $NetBSD: nd.h,v 1.3 2020/09/15 10:05:36 roy Exp $ */
/*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -39,6 +39,7 @@
#define ND_LLINFO_STALE 2
#define ND_LLINFO_DELAY 3
#define ND_LLINFO_PROBE 4
+#define ND_LLINFO_UNREACHABLE 5
#ifdef _KERNEL
#define ND_IS_LLINFO_PROBREACH(ln) \
@@ -47,18 +48,21 @@
(((ln)->ln_expire == 0) && ((ln)->ln_state > ND_LLINFO_INCOMPLETE))
/* ND timer types */
-#define ND_TIMER_IMMEDIATE 0
-#define ND_TIMER_TICK 1
-#define ND_TIMER_REACHABLE 2
-#define ND_TIMER_RETRANS 3
-#define ND_TIMER_EXPIRE 4
-#define ND_TIMER_DELAY 5
-#define ND_TIMER_GC 6
+#define ND_TIMER_IMMEDIATE 0
+#define ND_TIMER_TICK 1
+#define ND_TIMER_REACHABLE 2
+#define ND_TIMER_RETRANS 3
+#define ND_TIMER_RETRANS_BACKOFF 4
+#define ND_TIMER_EXPIRE 5
+#define ND_TIMER_DELAY 6
+#define ND_TIMER_GC 7
/* node constants */
#define MAX_REACHABLE_TIME 3600000 /* msec */
#define REACHABLE_TIME 30000 /* msec */
#define RETRANS_TIMER 1000 /* msec */
+#define MAX_RETRANS_TIMER 60000 /* msec */
+#define BACKOFF_MULTIPLE 3
#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */
#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */
#define ND_COMPUTE_RTIME(x) \
@@ -70,6 +74,8 @@
int nd_delay; /* delay first probe time in seconds */
int nd_mmaxtries; /* maximum multicast query */
int nd_umaxtries; /* maximum unicast query */
+ int nd_retransmultiple; /* retransmission multiplier for backoff */
+ int nd_maxretrans; /* maximum retransmission time in msec */
int nd_maxnudhint; /* max # of subsequent upper layer hints */
int nd_maxqueuelen; /* max # of packets in unresolved ND entries */
bool (*nd_nud_enabled)(struct ifnet *);
@@ -78,7 +84,8 @@
union l3addr *(*nd_holdsrc)(struct llentry *, union l3addr *);
void (*nd_output)(struct ifnet *, const union l3addr *,
const union l3addr *, const uint8_t *, const union l3addr *);
- void (*nd_missed)(struct ifnet *, const union l3addr *, struct mbuf *);
+ void (*nd_missed)(struct ifnet *, const union l3addr *,
+ int16_t, struct mbuf *);
void (*nd_free)(struct llentry *, int);
};
diff -r 8f74d1818f3d -r eb9a37d392a2 sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c Tue Sep 15 09:33:12 2020 +0000
+++ b/sys/netinet/if_arp.c Tue Sep 15 10:05:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_arp.c,v 1.296 2020/09/14 15:09:57 roy Exp $ */
+/* $NetBSD: if_arp.c,v 1.297 2020/09/15 10:05:36 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.296 2020/09/14 15:09:57 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.297 2020/09/15 10:05:36 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -145,7 +145,7 @@
static void arp_llinfo_output(struct ifnet *, const union l3addr *,
const union l3addr *, const uint8_t *, const union l3addr *);
static void arp_llinfo_missed(struct ifnet *, const union l3addr *,
- struct mbuf *);
+ int16_t, struct mbuf *);
static void arp_free(struct llentry *, int);
static struct nd_domain arp_nd_domain = {
@@ -153,6 +153,8 @@
.nd_delay = 5, /* delay first probe time 5 second */
.nd_mmaxtries = 3, /* maximum broadcast query */
.nd_umaxtries = 3, /* maximum unicast query */
+ .nd_retransmultiple = BACKOFF_MULTIPLE,
+ .nd_maxretrans = MAX_RETRANS_TIMER,
.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,
@@ -1374,7 +1376,7 @@
static void
arp_llinfo_missed(struct ifnet *ifp, const union l3addr *taddr,
- struct mbuf *m)
+ __unused int16_t type, struct mbuf *m)
{
struct in_addr mdaddr = zeroin_addr;
struct sockaddr_in dsin, tsin;
diff -r 8f74d1818f3d -r eb9a37d392a2 sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c Tue Sep 15 09:33:12 2020 +0000
+++ b/sys/netinet6/nd6.c Tue Sep 15 10:05:36 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.c,v 1.273 2020/09/14 15:09:57 roy Exp $ */
+/* $NetBSD: nd6.c,v 1.274 2020/09/15 10:05:36 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.273 2020/09/14 15:09:57 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.274 2020/09/15 10:05:36 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -111,7 +111,7 @@
static void nd6_llinfo_output(struct ifnet *, const union l3addr *,
const union l3addr *, const uint8_t *, const union l3addr *);
static void nd6_llinfo_missed(struct ifnet *, const union l3addr *,
- struct mbuf *);
+ int16_t, struct mbuf *);
static void nd6_timer(void *);
static void nd6_timer_work(struct work *, void *);
static struct nd_opt_hdr *nd6_option(union nd_opts *);
@@ -126,6 +126,8 @@
.nd_delay = 5, /* delay first probe time 5 second */
.nd_mmaxtries = 3, /* maximum unicast query */
.nd_umaxtries = 3, /* maximum multicast query */
+ .nd_retransmultiple = BACKOFF_MULTIPLE,
+ .nd_maxretrans = MAX_RETRANS_TIMER,
.nd_maxnudhint = 0, /* max # of subsequent upper layer hints */
.nd_maxqueuelen = 1, /* max # of packets in unresolved ND entries */
.nd_nud_enabled = nd6_nud_enabled,
@@ -411,15 +413,25 @@
}
static void
-nd6_llinfo_missed(struct ifnet *ifp, const union l3addr *taddr, struct mbuf *m)
+nd6_llinfo_missed(struct ifnet *ifp, const union l3addr *taddr,
+ int16_t type, struct mbuf *m)
{
struct in6_addr mdaddr6 = zeroin6_addr;
Home |
Main Index |
Thread Index |
Old Index