From: Roy Marples Date: Fri, 2 May 2014 11:03:46 +0000 (+0000) Subject: Optimise the initial probe timer. X-Git-Tag: v6.4.0~80 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d5de8532429fb574de8a14786686517dc1406de;p=thirdparty%2Fdhcpcd.git Optimise the initial probe timer. Don't send more than MAX_UNICAST_SOLICIT reachability probes. --- diff --git a/ipv6nd.c b/ipv6nd.c index 043d708f..d4875103 100644 --- a/ipv6nd.c +++ b/ipv6nd.c @@ -120,8 +120,8 @@ struct nd_opt_dnssl { /* DNSSL option RFC 6106 */ //#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 @@ static void 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 @@ ipv6nd_unreachable(void *arg) 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 @@ ipv6nd_proberouter1(struct ra *rap) 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 @@ static void 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 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, struct interface *ifp, 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 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, struct interface *ifp, 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); } } diff --git a/ipv6nd.h b/ipv6nd.h index 3f1a592e..7c38e946 100644 --- a/ipv6nd.h +++ b/ipv6nd.h @@ -75,8 +75,10 @@ struct rs_state { #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 */