changeset 2457:7cf4ee9e75b5 draft

Optimise the initial probe timer. Don't send more than MAX_UNICAST_SOLICIT reachability probes.
author Roy Marples <roy@marples.name>
date Fri, 02 May 2014 11:03:46 +0000
parents ef4a50a6763f
children 4050e5af02d9
files ipv6nd.c ipv6nd.h
diffstat 2 files changed, 19 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/ipv6nd.c	Fri May 02 10:16:00 2014 +0000
+++ b/ipv6nd.c	Fri May 02 11:03:46 2014 +0000
@@ -120,8 +120,8 @@
 //#define DEBUG_NS
 //
 
-static void ipv6nd_handledata(void *arg);
-static void ipv6nd_proberouter(void *arg);
+static void ipv6nd_handledata(void *);
+static void ipv6nd_proberouter(struct ra *);
 
 /*
  * Android ships buggy ICMP6 filter headers.
@@ -1096,7 +1096,6 @@
 ipv6nd_unreachable(void *arg)
 {
 	struct ra *rap = arg;
-	struct timeval tv;
 
 	/* We could add an unreachable flag and persist the information,
 	 * but that is more effort than it's probably worth. */
@@ -1105,22 +1104,12 @@
 	rap->expired = 1;
 	ipv6_buildroutes(rap->iface->ctx);
 	script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
-
-	/* We should still test if it's reachable or not so
-	 * incase it comes back to life and it's preferable. */
-	if (rap->reachable) {
-		ms_to_tv(&tv, rap->reachable);
-	} else {
-		tv.tv_sec = REACHABLE_TIME;
-		tv.tv_usec = 0;
-	}
-	eloop_timeout_add_tv(rap->iface->ctx->eloop,
-	    &tv, ipv6nd_proberouter, rap);
 }
 
 static void
-ipv6nd_proberouter1(struct ra *rap)
+ipv6nd_proberouter1(void *arg)
 {
+	struct ra *rap = arg;
 	struct nd_neighbor_solicit *ns;
 	struct nd_opt_hdr *nd;
 	struct sockaddr_in6 dst;
@@ -1186,20 +1175,24 @@
 		return;
 	}
 
-	ipv6nd_proberouter(rap);
-
 	if (rap->nsprobes++ == 0)
 		eloop_timeout_add_sec(rap->iface->ctx->eloop,
 		    DELAY_FIRST_PROBE_TIME, ipv6nd_unreachable, rap);
+
+	if (rap->nsprobes < MAX_UNICAST_SOLICIT)
+		ipv6nd_proberouter(rap);
 }
 
 static void
-ipv6nd_proberouter(void *arg)
+ipv6nd_proberouter(struct ra *rap)
 {
-	struct ra *rap = arg;
 	struct timeval tv, rtv;
 
-	ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
+	if (rap->nsprobes == 0) {
+		ms_to_tv(&tv, rap->reachable ? rap->reachable : REACHABLE_TIME);
+	} else {
+		ms_to_tv(&tv, rap->retrans ? rap->retrans :  RETRANS_TIMER);
+	}
 	ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
 	timeradd(&tv, &rtv, &tv);
 	rtv.tv_sec = 0;
@@ -1215,7 +1208,7 @@
 ipv6nd_cancelproberouter(struct ra *rap)
 {
 
-	eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_proberouter, rap);
+	eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_proberouter1, rap);
 	eloop_timeout_delete(rap->iface->ctx->eloop, ipv6nd_unreachable, rap);
 }
 
@@ -1350,7 +1343,6 @@
 	struct nd_neighbor_advert *nd_na;
 	struct ra *rap;
 	int is_router, is_solicited;
-	struct timeval tv;
 
 	if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
 		syslog(LOG_ERR, "IPv6 NA packet too short from %s", ctx->sfrom);
@@ -1413,17 +1405,10 @@
 			ipv6_buildroutes(ifp->ctx);
 			script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */
 		}
-		rap->nsprobes = 0;
-		if (rap->reachable) {
-			ms_to_tv(&tv, rap->reachable);
-		} else {
-			tv.tv_sec = REACHABLE_TIME;
-			tv.tv_usec = 0;
-		}
-		eloop_timeout_add_tv(rap->iface->ctx->eloop,
-		    &tv, ipv6nd_proberouter, rap);
 		eloop_timeout_delete(rap->iface->ctx->eloop,
 		    ipv6nd_unreachable, rap);
+		rap->nsprobes = 0;
+		ipv6nd_proberouter(rap);
 	}
 }
 
--- a/ipv6nd.h	Fri May 02 10:16:00 2014 +0000
+++ b/ipv6nd.h	Fri May 02 11:03:46 2014 +0000
@@ -75,8 +75,10 @@
 
 #define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6ND])
 
+#define MAX_UNICAST_SOLICIT	3	/* 3 transmissions */
+
 #define MAX_REACHABLE_TIME	3600	/* seconds */
-#define REACHABLE_TIME		30	/* seconds */
+#define REACHABLE_TIME		30000	/* milliseconds */
 #define RETRANS_TIMER		1000	/* milliseconds */
 #define DELAY_FIRST_PROBE_TIME	5	/* seconds */