Always update a route's nexthop as soon as the current nexthop is deleted (and clean up the route update code a bit)

This commit is contained in:
Matthias Schiffer 2014-03-18 18:33:25 +01:00
parent 2d6ec74c73
commit 5a077ac884
3 changed files with 71 additions and 61 deletions

View file

@ -93,7 +93,7 @@ static void maintain_routes(gmrf_context_t *ctx) {
gp_babel_route_t *route = *cur; gp_babel_route_t *route = *cur;
next = &route->next; next = &route->next;
gp_babel_route_update(ctx, route); gp_babel_route_maintain(ctx, route);
if (!route->nexthops && gp_babel_since(ctx, route->last_nexthop) > GP_BABEL_PURGE_TIMEOUT) { if (!route->nexthops && gp_babel_since(ctx, route->last_nexthop) > GP_BABEL_PURGE_TIMEOUT) {
gmrf_logf(ctx->gmrf, LOG_DEBUG, "node %04x%04x (%u, seqno=%04x): purging.", gmrf_logf(ctx->gmrf, LOG_DEBUG, "node %04x%04x (%u, seqno=%04x): purging.",

View file

@ -134,7 +134,7 @@ void gp_babel_send_seqno_request(gmrf_context_t *ctx, gp_babel_neigh_t *neigh, g
gp_babel_route_t* gp_babel_route_new(gmrf_context_t *ctx); gp_babel_route_t* gp_babel_route_new(gmrf_context_t *ctx);
gp_babel_route_t* gp_babel_route_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node); gp_babel_route_t* gp_babel_route_find(gmrf_context_t *ctx, const gp_babel_node_id_t *node);
gp_babel_route_t* gp_babel_route_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node); gp_babel_route_t* gp_babel_route_get(gmrf_context_t *ctx, const gp_babel_node_id_t *node);
void gp_babel_route_update(gmrf_context_t *ctx, gp_babel_route_t *route); void gp_babel_route_maintain(gmrf_context_t *ctx, gp_babel_route_t *route);
void gp_babel_route_free(gmrf_context_t *ctx, gp_babel_route_t *route); void gp_babel_route_free(gmrf_context_t *ctx, gp_babel_route_t *route);
gp_babel_nexthop_t* gp_babel_route_nexthop_new(gp_babel_route_t *route, gp_babel_neigh_t *neigh); gp_babel_nexthop_t* gp_babel_route_nexthop_new(gp_babel_route_t *route, gp_babel_neigh_t *neigh);

View file

@ -94,50 +94,6 @@ static inline bool nexthop_has_expired(gmrf_context_t *ctx, gp_babel_nexthop_t *
return (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)); return (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_TIMEOUT(nexthop->interval));
} }
void gp_babel_route_nexthop_delete(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
gp_babel_nexthop_t **nexthopp;
for (nexthopp = &route->nexthops; *nexthopp; nexthopp = &(*nexthopp)->next) {
if (*nexthopp == nexthop)
break;
}
assert(*nexthopp == nexthop);
*nexthopp = nexthop->next;
if (route->selected == nexthop)
route->selected = NULL;
gp_babel_neigh_unref(nexthop->neigh);
free(nexthop);
route->last_nexthop = gmrf_now(ctx->gmrf);
}
static void maintain_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
if (!nexthop->neigh) /* local */
return;
if (nexthop_has_expired(ctx, nexthop)) {
gp_babel_route_nexthop_delete(ctx, route, nexthop);
return;
}
if (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval)
&& route->selected == nexthop && !nexthop->requested_update) {
gmrf_logf(ctx->gmrf, LOG_INFO, "route about to expire, requesting update");
gp_babel_send_route_request(ctx, NULL, nexthop->neigh, &route->node);
nexthop->requested_update = true;
}
}
static void maintain_nexthops(gmrf_context_t *ctx, gp_babel_route_t *route) {
gp_babel_nexthop_t *nexthop, *next;
for (nexthop = route->nexthops; nexthop; nexthop = next) {
next = nexthop->next;
maintain_nexthop(ctx, route, nexthop);
}
}
static gp_babel_nexthop_t* select_nexthop(gmrf_context_t *ctx, const gp_babel_route_t *route) { static gp_babel_nexthop_t* select_nexthop(gmrf_context_t *ctx, const gp_babel_route_t *route) {
uint16_t ret_metric = GP_BABEL_INFINITY; uint16_t ret_metric = GP_BABEL_INFINITY;
@ -162,7 +118,7 @@ static gp_babel_nexthop_t* select_nexthop(gmrf_context_t *ctx, const gp_babel_ro
return ret; return ret;
} }
gp_babel_metric_seqno_t get_metric(gmrf_context_t *ctx, const gp_babel_route_t *route) { static gp_babel_metric_seqno_t get_metric(gmrf_context_t *ctx, const gp_babel_route_t *route) {
if (route->selected) { if (route->selected) {
uint32_t metric = route->selected->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, route->selected->neigh); uint32_t metric = route->selected->metric_seqno.metric + gp_babel_neigh_get_cost(ctx, route->selected->neigh);
@ -173,9 +129,7 @@ gp_babel_metric_seqno_t get_metric(gmrf_context_t *ctx, const gp_babel_route_t *
return (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0}; return (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0};
} }
void gp_babel_route_update(gmrf_context_t *ctx, gp_babel_route_t *route) { static void update_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route) {
maintain_nexthops(ctx, route);
route->selected = select_nexthop(ctx, route); route->selected = select_nexthop(ctx, route);
route->metric = get_metric(ctx, route); route->metric = get_metric(ctx, route);
@ -203,18 +157,74 @@ void gp_babel_route_update(gmrf_context_t *ctx, gp_babel_route_t *route) {
} }
} }
void gp_babel_route_update_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval) { static void delete_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
if (ms.metric == GP_BABEL_INFINITY) { gp_babel_nexthop_t **nexthopp;
gmrf_logf(ctx->gmrf, LOG_DEBUG, "retract received, deleting nexthop"); for (nexthopp = &route->nexthops; *nexthopp; nexthopp = &(*nexthopp)->next) {
gp_babel_route_nexthop_delete(ctx, route, nexthop); if (*nexthopp == nexthop)
gp_babel_route_update(ctx, route); break;
}
assert(*nexthopp == nexthop);
*nexthopp = nexthop->next;
if (route->selected == nexthop)
route->selected = NULL;
gp_babel_neigh_unref(nexthop->neigh);
free(nexthop);
route->last_nexthop = gmrf_now(ctx->gmrf);
}
void gp_babel_route_nexthop_delete(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
delete_nexthop(ctx, route, nexthop);
if (!route->selected)
gp_babel_route_maintain(ctx, route);
}
static void maintain_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
if (!nexthop->neigh) /* local */
return;
if (nexthop_has_expired(ctx, nexthop)) {
delete_nexthop(ctx, route, nexthop);
return; return;
} }
nexthop->metric_seqno = ms; if (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval)
nexthop->interval = interval; && route->selected == nexthop && !nexthop->requested_update) {
nexthop->requested_update = false; gmrf_logf(ctx->gmrf, LOG_INFO, "route about to expire, requesting update");
nexthop->last_update = gmrf_now(ctx->gmrf); gp_babel_send_route_request(ctx, NULL, nexthop->neigh, &route->node);
nexthop->requested_update = true;
gp_babel_route_update(ctx, route); }
}
static void maintain_nexthops(gmrf_context_t *ctx, gp_babel_route_t *route) {
gp_babel_nexthop_t *nexthop, *next;
for (nexthop = route->nexthops; nexthop; nexthop = next) {
next = nexthop->next;
maintain_nexthop(ctx, route, nexthop);
}
}
void gp_babel_route_maintain(gmrf_context_t *ctx, gp_babel_route_t *route) {
maintain_nexthops(ctx, route);
update_nexthop(ctx, route);
}
void gp_babel_route_update_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval) {
if (ms.metric == GP_BABEL_INFINITY) {
gmrf_logf(ctx->gmrf, LOG_DEBUG, "retract received, deleting nexthop");
delete_nexthop(ctx, route, nexthop);
}
else {
nexthop->metric_seqno = ms;
nexthop->interval = interval;
nexthop->requested_update = false;
nexthop->last_update = gmrf_now(ctx->gmrf);
}
gp_babel_route_maintain(ctx, route);
} }