From 47bd032564a4812a607cbe9f5a44ef2b2f93278d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 24 Mar 2013 03:45:16 +0100 Subject: Initial nexthop maintenance implementation Mostly taken from the FFD project, and quite incomplete. --- src/announce.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) (limited to 'src/announce.c') diff --git a/src/announce.c b/src/announce.c index 1891341..1d17a02 100644 --- a/src/announce.c +++ b/src/announce.c @@ -33,7 +33,7 @@ gp_babel_announce_t* gp_babel_announce_new(gmrf_t *gmrf, gmrf_context_t *ctx) { gp_babel_announce_t *a = calloc(1, sizeof(gp_babel_announce_t)); - a->metric.metric = a->feasibility_distance.metric = a->last_metric = 0xffff; + a->metric.metric = a->feasibility_distance.metric = a->last_metric = GP_BABEL_INFINITY; a->next = ctx->announces; ctx->announces = a; @@ -91,3 +91,113 @@ gp_babel_nexthop_t* gp_babel_announce_nexthop_new(gp_babel_announce_t *announce, return nexthop; } + +static void maintain_nexthops(gmrf_t *gmrf, gp_babel_announce_t *announce) { + gp_babel_nexthop_t **cur, **next; + for (cur = &announce->nexthops; *cur; cur = next) { + gp_babel_nexthop_t *nexthop = *cur; + next = &nexthop->next; + + if (!nexthop->neigh) /* local */ + continue; + + if (!nexthop->neigh->iface) { + if (nexthop->metric_seqno.metric != GP_BABEL_INFINITY) { + nexthop->metric_seqno.metric = GP_BABEL_INFINITY; + nexthop->last_update = gmrf_now(gmrf); + nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; + } + + continue; + } + + if (gmrf_now(gmrf) > nexthop->last_update+GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10) { + if (nexthop->metric_seqno.metric == GP_BABEL_INFINITY) { + *cur = *next; + next = cur; + + if (announce->selected == nexthop) + announce->selected = NULL; + + gp_babel_neigh_unref(nexthop->neigh); + + free(nexthop); + } + else { + nexthop->metric_seqno.metric = GP_BABEL_INFINITY; + nexthop->last_update += GP_BABEL_UPDATE_TIMEOUT(nexthop->interval)*10; + } + } + else if (gmrf_now(gmrf) > nexthop->last_update+GP_BABEL_UPDATE_REQUEST_TIMEOUT(nexthop->interval)*10 && announce->selected == nexthop) { + if (!nexthop->requested_update) { + gmrf_logf(gmrf, LOG_INFO, "announce about to expire, requesting update"); + // gp_babel_send_announce_request(nexthop->neigh->iface, nexthop->neigh, announce->node, announce->type, announce->key, false); + nexthop->requested_update = true; + } + } + } +} + +static gp_babel_nexthop_t* select_nexthop(gmrf_t *gmrf, const gp_babel_announce_t *announce) { + uint16_t ret_metric = GP_BABEL_INFINITY; + gp_babel_nexthop_t *ret = NULL; + + gp_babel_nexthop_t *nexthop; + for (nexthop = announce->nexthops; nexthop; nexthop = nexthop->next) { + if (!nexthop->neigh) /* local */ + return nexthop; + + if (!gp_babel_is_feasible(announce, nexthop->metric_seqno)) + continue; + + uint32_t metric = nexthop->metric_seqno.metric + gp_babel_neigh_get_cost(gmrf, nexthop->neigh); + + if (metric < ret_metric) { + ret = nexthop; + ret_metric = metric; + } + } + + return ret; +} + +gp_babel_metric_seqno_t get_metric(gmrf_t *gmrf, const gp_babel_announce_t *announce) { + if (announce->selected) { + uint32_t metric = announce->selected->metric_seqno.metric + gp_babel_neigh_get_cost(gmrf, announce->selected->neigh); + + if (metric < GP_BABEL_INFINITY) + return (gp_babel_metric_seqno_t){metric, announce->selected->metric_seqno.seqno}; + } + + return (gp_babel_metric_seqno_t){GP_BABEL_INFINITY, 0}; +} + +void gp_babel_announce_update(gmrf_t *gmrf, gp_babel_announce_t *announce) { + maintain_nexthops(gmrf, announce); + + announce->selected = select_nexthop(gmrf, announce); + announce->metric = get_metric(gmrf, announce); + + //if (!announce->selected) + // gp_babel_send_seqno_request_for(NULL, announce); + + /* triggered updates */ + /*int diff = announce->metric.metric - announce->last_metric; + + if (((announce->last_metric == GP_BABEL_INFINITY) != (announce->metric.metric == GP_BABEL_INFINITY)) + || diff <= -1024 || diff >= 384) { + gmrf_logf(gmrf, LOG_INFO, "announce metric has changed significantly, sending updates"); + gp_babel_update_enqueue(&announce->node, announce->type, announce->key, NULL, announce->metric.metric == GP_BABEL_INFINITY); + } */ +} + +void gp_babel_announce_update_nexthop(gmrf_t *gmrf, gp_babel_announce_t *announce, gp_babel_nexthop_t *nexthop, gp_babel_metric_seqno_t ms, uint16_t interval) { + nexthop->metric_seqno = ms; + nexthop->interval = interval; + nexthop->requested_update = false; + + if (ms.metric != GP_BABEL_INFINITY) + nexthop->last_update = gmrf_now(gmrf); + + gp_babel_announce_update(gmrf, announce); +} -- cgit v1.2.3