summaryrefslogtreecommitdiffstats
path: root/src/announce.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/announce.c')
-rw-r--r--src/announce.c112
1 files changed, 111 insertions, 1 deletions
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);
+}