diff options
| -rw-r--r-- | nhrpd/nhrp_shortcut.c | 94 | ||||
| -rw-r--r-- | nhrpd/nhrpd.h | 7 | 
2 files changed, 77 insertions, 24 deletions
diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 9b47d974c3..55d61a90b8 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -21,14 +21,16 @@ static struct route_table *shortcut_rib[AFI_MAX];  static void nhrp_shortcut_do_purge(struct event *t);  static void nhrp_shortcut_delete(struct nhrp_shortcut *s,  				 void *arg __attribute__((__unused__))); -static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s); +static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s, +					      bool retry); +static void nhrp_shortcut_retry_resolution_req(struct event *t);  static void nhrp_shortcut_check_use(struct nhrp_shortcut *s)  {  	if (s->expiring && s->cache && s->cache->used) {  		debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX used and expiring",  		       s->p); -		nhrp_shortcut_send_resolution_req(s); +		nhrp_shortcut_send_resolution_req(s, false);  	}  } @@ -37,7 +39,7 @@ static void nhrp_shortcut_do_expire(struct event *t)  	struct nhrp_shortcut *s = EVENT_ARG(t);  	event_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3, -			&s->t_timer); +			&s->t_shortcut_purge);  	s->expiring = 1;  	nhrp_shortcut_check_use(s);  } @@ -124,12 +126,12 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,  		s->route_installed = 0;  	} -	EVENT_OFF(s->t_timer); +	EVENT_OFF(s->t_shortcut_purge);  	if (holding_time) {  		s->expiring = 0;  		s->holding_time = holding_time;  		event_add_timer(master, nhrp_shortcut_do_expire, s, -				2 * holding_time / 3, &s->t_timer); +				2 * holding_time / 3, &s->t_shortcut_purge);  	}  } @@ -139,7 +141,8 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s,  	struct route_node *rn;  	afi_t afi = family2afi(PREFIX_FAMILY(s->p)); -	EVENT_OFF(s->t_timer); +	EVENT_OFF(s->t_shortcut_purge); +	EVENT_OFF(s->t_retry_resolution);  	nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);  	debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX purged", s->p); @@ -159,7 +162,8 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s,  static void nhrp_shortcut_do_purge(struct event *t)  {  	struct nhrp_shortcut *s = EVENT_ARG(t); -	s->t_timer = NULL; +	s->t_shortcut_purge = NULL; +	EVENT_OFF(s->t_retry_resolution);  	nhrp_shortcut_delete(s, NULL);  } @@ -206,8 +210,10 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,  	int holding_time = pp->if_ad->holdtime;  	nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid); -	EVENT_OFF(s->t_timer); -	event_add_timer(master, nhrp_shortcut_do_purge, s, 1, &s->t_timer); +	EVENT_OFF(s->t_shortcut_purge); +	EVENT_OFF(s->t_retry_resolution); +	event_add_timer(master, nhrp_shortcut_do_purge, s, 1, +			&s->t_shortcut_purge);  	if (pp->hdr->type != NHRP_PACKET_RESOLUTION_REPLY) {  		if (pp->hdr->type == NHRP_PACKET_ERROR_INDICATION @@ -374,7 +380,8 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,  	debugf(NHRP_DEBUG_COMMON, "Shortcut: Resolution reply handled");  } -static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s) +static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s, +					      bool retry)  {  	struct zbuf *zb;  	struct nhrp_packet_header *hdr; @@ -389,6 +396,22 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)  	    != NHRP_ROUTE_NBMA_NEXTHOP)  		return; +	/*Retry interval for NHRP resolution request +	 * will start at 1 second and will be doubled every time +	 * another resolution request is sent, until it is +	 * eventually upper-bounded by the purge time of +	 * the shortcut. +	 */ +	if (!retry) +		s->retry_interval = 1; +	event_add_timer(master, nhrp_shortcut_retry_resolution_req, s, +			s->retry_interval, &s->t_retry_resolution); +	if (s->retry_interval != (NHRPD_DEFAULT_PURGE_TIME / 4)) +		s->retry_interval = ((s->retry_interval * 2) < +				     (NHRPD_DEFAULT_PURGE_TIME / 4)) +					    ? (s->retry_interval * 2) +					    : (NHRPD_DEFAULT_PURGE_TIME / 4); +  	if (s->type == NHRP_CACHE_INVALID || s->type == NHRP_CACHE_NEGATIVE)  		s->type = NHRP_CACHE_INCOMPLETE; @@ -401,9 +424,23 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)  		zb, NHRP_PACKET_RESOLUTION_REQUEST, &nifp->nbma,  		&nifp->afi[family2afi(sockunion_family(&s->addr))].addr,  		&s->addr); -	hdr->u.request_id = -		htonl(nhrp_reqid_alloc(&nhrp_packet_reqid, &s->reqid, -				       nhrp_shortcut_recv_resolution_rep)); + +	/* RFC2332 - The value is taken from a 32 bit counter that is incremented +	 * each time a new "request" is transmitted.  The same value MUST +	 * be used when resending a "request", i.e., when a "reply" has not been +	 * received for a "request" and a retry is sent after an +	 * appropriate interval +	 */ +	if (!retry) +		hdr->u.request_id = htonl( +			nhrp_reqid_alloc(&nhrp_packet_reqid, &s->reqid, +					 nhrp_shortcut_recv_resolution_rep)); +	else +		/* Just pull request_id from existing incomplete +		 * shortcut in the case of a retry +		 */ +		hdr->u.request_id = htonl(s->reqid.request_id); +  	hdr->flags = htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER  			   | NHRP_FLAG_RESOLUTION_AUTHORATIVE  			   | NHRP_FLAG_RESOLUTION_SOURCE_STABLE); @@ -412,7 +449,7 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)  	 *  - Prefix length: widest acceptable prefix we accept (if U set, 0xff)  	 *  - MTU: MTU of the source station  	 *  - Holding Time: Max time to cache the source information -	 * */ +	 */  	/* FIXME: push CIE for each local protocol address */  	cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);  	if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))]; @@ -456,13 +493,25 @@ void nhrp_shortcut_initiate(union sockunion *addr)  	s = nhrp_shortcut_get(&p);  	if (s && s->type != NHRP_CACHE_INCOMPLETE) {  		s->addr = *addr; -		EVENT_OFF(s->t_timer); -		event_add_timer(master, nhrp_shortcut_do_purge, s, 30, -				&s->t_timer); -		nhrp_shortcut_send_resolution_req(s); +		EVENT_OFF(s->t_shortcut_purge); +		EVENT_OFF(s->t_retry_resolution); + +		event_add_timer(master, nhrp_shortcut_do_purge, s, +				NHRPD_DEFAULT_PURGE_TIME, &s->t_shortcut_purge); +		nhrp_shortcut_send_resolution_req(s, false);  	}  } +static void nhrp_shortcut_retry_resolution_req(struct event *t) +{ +	struct nhrp_shortcut *s = EVENT_ARG(t); + +	EVENT_OFF(s->t_retry_resolution); +	debugf(NHRP_DEBUG_COMMON, "Shortcut: Retrying Resolution Request"); +	nhrp_shortcut_send_resolution_req(s, true); +} + +  void nhrp_shortcut_init(void)  {  	shortcut_rib[AFI_IP] = route_table_init(); @@ -503,13 +552,14 @@ struct purge_ctx {  void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force)  { -	EVENT_OFF(s->t_timer); +	EVENT_OFF(s->t_shortcut_purge); +	EVENT_OFF(s->t_retry_resolution);  	nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);  	if (force) {  		/* Immediate purge on route with draw or pending shortcut */  		event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 5, -				     &s->t_timer); +				     &s->t_shortcut_purge);  	} else {  		/* Soft expire - force immediate renewal, but purge  		 * in few seconds to make sure stale route is not @@ -518,8 +568,8 @@ void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force)  		 * This allows to keep nhrp route up, and to not  		 * cause temporary rerouting via hubs causing latency  		 * jitter. */ -		event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 3000, -				     &s->t_timer); +		event_add_timer_msec(master, nhrp_shortcut_do_purge, s, +				     NHRPD_PURGE_EXPIRE, &s->t_shortcut_purge);  		s->expiring = 1;  		nhrp_shortcut_check_use(s);  	} diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 344e1d5178..6cab7b3a1d 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -15,7 +15,8 @@  DECLARE_MGROUP(NHRPD);  #define NHRPD_DEFAULT_HOLDTIME	7200 - +#define NHRPD_DEFAULT_PURGE_TIME 30 +#define NHRPD_PURGE_EXPIRE	 3000  #define NHRP_DEFAULT_CONFIG	"nhrpd.conf"  extern struct event_loop *master; @@ -250,10 +251,12 @@ struct nhrp_shortcut {  	union sockunion addr;  	struct nhrp_reqid reqid; -	struct event *t_timer; +	struct event *t_shortcut_purge; +	struct event *t_retry_resolution;  	enum nhrp_cache_type type;  	unsigned int holding_time; +	unsigned int retry_interval;  	unsigned route_installed : 1;  	unsigned expiring : 1;  | 
