summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/babel.h2
-rw-r--r--src/route.c85
2 files changed, 48 insertions, 39 deletions
diff --git a/src/babel.h b/src/babel.h
index 625b570..0e1ebb9 100644
--- a/src/babel.h
+++ b/src/babel.h
@@ -103,6 +103,8 @@ struct gp_babel_route {
gp_babel_nexthop_t *selected;
gp_babel_nexthop_t *nexthops;
+
+ gmrf_time_t last_nexthop;
};
struct gp_babel_nexthop {
diff --git a/src/route.c b/src/route.c
index db89896..ccb2d84 100644
--- a/src/route.c
+++ b/src/route.c
@@ -27,6 +27,7 @@
#include "babel.h"
#include "neigh.h"
+#include <assert.h>
#include <stdlib.h>
@@ -88,51 +89,52 @@ gp_babel_nexthop_t* gp_babel_route_nexthop_new(gp_babel_route_t *route, gp_babel
return nexthop;
}
-static void maintain_nexthops(gmrf_context_t *ctx, gp_babel_route_t *route) {
- gp_babel_nexthop_t **cur, **next;
- for (cur = &route->nexthops; *cur; cur = next) {
- gp_babel_nexthop_t *nexthop = *cur;
- next = &nexthop->next;
+static inline bool nexthop_has_expired(gmrf_context_t *ctx, gp_babel_nexthop_t *nexthop) {
+ return (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_TIMEOUT(nexthop->interval));
+}
- if (!nexthop->neigh) /* local */
- continue;
+static void 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);
- if (!nexthop->neigh->iface) {
- // TODO find out what this is supposed to to
+ *nexthopp = nexthop->next;
- if (nexthop->metric_seqno.metric != GP_BABEL_INFINITY) {
- nexthop->metric_seqno.metric = GP_BABEL_INFINITY;
- nexthop->last_update = gmrf_now(ctx->gmrf);
- nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10;
- }
+ if (route->selected == nexthop)
+ route->selected = NULL;
- continue;
- }
+ gp_babel_neigh_unref(nexthop->neigh);
+ free(nexthop);
- if (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)) {
- if (nexthop->metric_seqno.metric == GP_BABEL_INFINITY) {
- *cur = *next;
- next = cur;
+ route->last_nexthop = gmrf_now(ctx->gmrf);
+}
- if (route->selected == nexthop)
- route->selected = NULL;
+static void maintain_nexthop(gmrf_context_t *ctx, gp_babel_route_t *route, gp_babel_nexthop_t *nexthop) {
+ if (!nexthop->neigh) /* local */
+ return;
- gp_babel_neigh_unref(nexthop->neigh);
+ if (nexthop_has_expired(ctx, nexthop)) {
+ nexthop_delete(ctx, route, nexthop);
+ return;
+ }
- free(nexthop);
- }
- else {
- nexthop->metric_seqno.metric = GP_BABEL_INFINITY;
- nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10;
- }
- }
- else if (gp_babel_since(ctx, nexthop->last_update) > GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval) && route->selected == nexthop) {
- if (!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;
- }
- }
+ 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);
}
}
@@ -190,12 +192,17 @@ 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) {
- if (ms.metric != GP_BABEL_INFINITY || nexthop->metric_seqno.metric != GP_BABEL_INFINITY)
- nexthop->last_update = gmrf_now(ctx->gmrf);
+ if (ms.metric == GP_BABEL_INFINITY) {
+ gmrf_logf(ctx->gmrf, LOG_DEBUG, "retract received, deleting nexthop");
+ nexthop_delete(ctx, route, nexthop);
+ gp_babel_route_update(ctx, route);
+ return;
+ }
nexthop->metric_seqno = ms;
nexthop->interval = interval;
nexthop->requested_update = false;
+ nexthop->last_update = gmrf_now(ctx->gmrf);
gp_babel_route_update(ctx, route);
}