forked from Mirror/frr
Merge pull request #16788 from LabNConsulting/jmuthii/nhrpd-retry-resolution
nhrpd: Implement retrying resolution request
This commit is contained in:
commit
cee061df3c
|
@ -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_do_purge(struct event *t);
|
||||||
static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
|
static void nhrp_shortcut_delete(struct nhrp_shortcut *s,
|
||||||
void *arg __attribute__((__unused__)));
|
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)
|
static void nhrp_shortcut_check_use(struct nhrp_shortcut *s)
|
||||||
{
|
{
|
||||||
if (s->expiring && s->cache && s->cache->used) {
|
if (s->expiring && s->cache && s->cache->used) {
|
||||||
debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX used and expiring",
|
debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX used and expiring",
|
||||||
s->p);
|
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);
|
struct nhrp_shortcut *s = EVENT_ARG(t);
|
||||||
|
|
||||||
event_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3,
|
event_add_timer(master, nhrp_shortcut_do_purge, s, s->holding_time / 3,
|
||||||
&s->t_timer);
|
&s->t_shortcut_purge);
|
||||||
s->expiring = 1;
|
s->expiring = 1;
|
||||||
nhrp_shortcut_check_use(s);
|
nhrp_shortcut_check_use(s);
|
||||||
}
|
}
|
||||||
|
@ -124,12 +126,12 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
|
||||||
s->route_installed = 0;
|
s->route_installed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVENT_OFF(s->t_timer);
|
EVENT_OFF(s->t_shortcut_purge);
|
||||||
if (holding_time) {
|
if (holding_time) {
|
||||||
s->expiring = 0;
|
s->expiring = 0;
|
||||||
s->holding_time = holding_time;
|
s->holding_time = holding_time;
|
||||||
event_add_timer(master, nhrp_shortcut_do_expire, s,
|
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;
|
struct route_node *rn;
|
||||||
afi_t afi = family2afi(PREFIX_FAMILY(s->p));
|
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);
|
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
|
||||||
|
|
||||||
debugf(NHRP_DEBUG_ROUTE, "Shortcut %pFX purged", s->p);
|
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)
|
static void nhrp_shortcut_do_purge(struct event *t)
|
||||||
{
|
{
|
||||||
struct nhrp_shortcut *s = EVENT_ARG(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);
|
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;
|
int holding_time = pp->if_ad->holdtime;
|
||||||
|
|
||||||
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
|
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
|
||||||
EVENT_OFF(s->t_timer);
|
EVENT_OFF(s->t_shortcut_purge);
|
||||||
event_add_timer(master, nhrp_shortcut_do_purge, s, 1, &s->t_timer);
|
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_RESOLUTION_REPLY) {
|
||||||
if (pp->hdr->type == NHRP_PACKET_ERROR_INDICATION
|
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");
|
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 zbuf *zb;
|
||||||
struct nhrp_packet_header *hdr;
|
struct nhrp_packet_header *hdr;
|
||||||
|
@ -389,6 +396,22 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s)
|
||||||
!= NHRP_ROUTE_NBMA_NEXTHOP)
|
!= NHRP_ROUTE_NBMA_NEXTHOP)
|
||||||
return;
|
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)
|
if (s->type == NHRP_CACHE_INVALID || s->type == NHRP_CACHE_NEGATIVE)
|
||||||
s->type = NHRP_CACHE_INCOMPLETE;
|
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,
|
zb, NHRP_PACKET_RESOLUTION_REQUEST, &nifp->nbma,
|
||||||
&nifp->afi[family2afi(sockunion_family(&s->addr))].addr,
|
&nifp->afi[family2afi(sockunion_family(&s->addr))].addr,
|
||||||
&s->addr);
|
&s->addr);
|
||||||
hdr->u.request_id =
|
|
||||||
htonl(nhrp_reqid_alloc(&nhrp_packet_reqid, &s->reqid,
|
/* RFC2332 - The value is taken from a 32 bit counter that is incremented
|
||||||
nhrp_shortcut_recv_resolution_rep));
|
* 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
|
hdr->flags = htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER
|
||||||
| NHRP_FLAG_RESOLUTION_AUTHORATIVE
|
| NHRP_FLAG_RESOLUTION_AUTHORATIVE
|
||||||
| NHRP_FLAG_RESOLUTION_SOURCE_STABLE);
|
| 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)
|
* - Prefix length: widest acceptable prefix we accept (if U set, 0xff)
|
||||||
* - MTU: MTU of the source station
|
* - MTU: MTU of the source station
|
||||||
* - Holding Time: Max time to cache the source information
|
* - Holding Time: Max time to cache the source information
|
||||||
* */
|
*/
|
||||||
/* FIXME: push CIE for each local protocol address */
|
/* FIXME: push CIE for each local protocol address */
|
||||||
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
|
cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL);
|
||||||
if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))];
|
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);
|
s = nhrp_shortcut_get(&p);
|
||||||
if (s && s->type != NHRP_CACHE_INCOMPLETE) {
|
if (s && s->type != NHRP_CACHE_INCOMPLETE) {
|
||||||
s->addr = *addr;
|
s->addr = *addr;
|
||||||
EVENT_OFF(s->t_timer);
|
EVENT_OFF(s->t_shortcut_purge);
|
||||||
event_add_timer(master, nhrp_shortcut_do_purge, s, 30,
|
EVENT_OFF(s->t_retry_resolution);
|
||||||
&s->t_timer);
|
|
||||||
nhrp_shortcut_send_resolution_req(s);
|
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)
|
void nhrp_shortcut_init(void)
|
||||||
{
|
{
|
||||||
shortcut_rib[AFI_IP] = route_table_init();
|
shortcut_rib[AFI_IP] = route_table_init();
|
||||||
|
@ -503,13 +552,14 @@ struct purge_ctx {
|
||||||
|
|
||||||
void nhrp_shortcut_purge(struct nhrp_shortcut *s, int force)
|
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);
|
nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid);
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
/* Immediate purge on route with draw or pending shortcut */
|
/* Immediate purge on route with draw or pending shortcut */
|
||||||
event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 5,
|
event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 5,
|
||||||
&s->t_timer);
|
&s->t_shortcut_purge);
|
||||||
} else {
|
} else {
|
||||||
/* Soft expire - force immediate renewal, but purge
|
/* Soft expire - force immediate renewal, but purge
|
||||||
* in few seconds to make sure stale route is not
|
* 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
|
* This allows to keep nhrp route up, and to not
|
||||||
* cause temporary rerouting via hubs causing latency
|
* cause temporary rerouting via hubs causing latency
|
||||||
* jitter. */
|
* jitter. */
|
||||||
event_add_timer_msec(master, nhrp_shortcut_do_purge, s, 3000,
|
event_add_timer_msec(master, nhrp_shortcut_do_purge, s,
|
||||||
&s->t_timer);
|
NHRPD_PURGE_EXPIRE, &s->t_shortcut_purge);
|
||||||
s->expiring = 1;
|
s->expiring = 1;
|
||||||
nhrp_shortcut_check_use(s);
|
nhrp_shortcut_check_use(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
DECLARE_MGROUP(NHRPD);
|
DECLARE_MGROUP(NHRPD);
|
||||||
|
|
||||||
#define NHRPD_DEFAULT_HOLDTIME 7200
|
#define NHRPD_DEFAULT_HOLDTIME 7200
|
||||||
|
#define NHRPD_DEFAULT_PURGE_TIME 30
|
||||||
|
#define NHRPD_PURGE_EXPIRE 3000
|
||||||
#define NHRP_DEFAULT_CONFIG "nhrpd.conf"
|
#define NHRP_DEFAULT_CONFIG "nhrpd.conf"
|
||||||
|
|
||||||
extern struct event_loop *master;
|
extern struct event_loop *master;
|
||||||
|
@ -250,10 +251,12 @@ struct nhrp_shortcut {
|
||||||
union sockunion addr;
|
union sockunion addr;
|
||||||
|
|
||||||
struct nhrp_reqid reqid;
|
struct nhrp_reqid reqid;
|
||||||
struct event *t_timer;
|
struct event *t_shortcut_purge;
|
||||||
|
struct event *t_retry_resolution;
|
||||||
|
|
||||||
enum nhrp_cache_type type;
|
enum nhrp_cache_type type;
|
||||||
unsigned int holding_time;
|
unsigned int holding_time;
|
||||||
|
unsigned int retry_interval;
|
||||||
unsigned route_installed : 1;
|
unsigned route_installed : 1;
|
||||||
unsigned expiring : 1;
|
unsigned expiring : 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue