summaryrefslogtreecommitdiffstats
path: root/ffd/announce.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/announce.c')
-rw-r--r--ffd/announce.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/ffd/announce.c b/ffd/announce.c
index 26ced28..00bd78c 100644
--- a/ffd/announce.c
+++ b/ffd/announce.c
@@ -110,6 +110,26 @@ ffd_metric_seqno_t get_metric(const ffd_announce_t *announce) {
return (ffd_metric_seqno_t){0xffff, 0};
}
+static inline void seqno_update(ffd_announce_t *announce) {
+ ffd_seqno_req_t **cur, **next;
+ for (cur = &announce->seqno_req_list; *cur; cur = next) {
+ ffd_seqno_req_t *req = *cur;
+ next = &req->next;
+
+ int16_t diff = announce->selected->metric_seqno.seqno - req->seqno;
+
+ if (diff >= 0) {
+ *cur = *next;
+ next = cur;
+
+ fprintf(stderr, "debug: update matches seqno request, forwarding\n");
+ ffd_send_update(NULL, req->neigh, announce, false);
+ ffd_neigh_unref(req->neigh);
+ free(req);
+ }
+ }
+}
+
void ffd_announce_update(ffd_announce_t *announce) {
maintain_nexthops(announce);
@@ -127,6 +147,9 @@ void ffd_announce_update(ffd_announce_t *announce) {
fprintf(stderr, "info: announce metric has changed significantly, sending updates\n");
ffd_send_update(NULL, NULL, announce, false);
}
+
+ if (announce->selected)
+ seqno_update(announce);
}
void ffd_announce_update_nexthop(ffd_announce_t *announce, ffd_nexthop_t *nexthop, ffd_metric_seqno_t ms, uint16_t interval) {
@@ -175,3 +198,82 @@ ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint1
return announce;
}
+
+ffd_nexthop_t* ffd_announce_nexthop_find(const ffd_announce_t *announce, ffd_neigh_t *neigh) {
+ ffd_nexthop_t *nexthop;
+ for (nexthop = announce->nexthop_list; nexthop; nexthop = nexthop->next) {
+ if (nexthop->neigh == neigh)
+ return nexthop;
+ }
+
+ return NULL;
+}
+
+ffd_nexthop_t* ffd_announce_nexthop_new(ffd_announce_t *announce, ffd_neigh_t *neigh) {
+ ffd_nexthop_t *nexthop = calloc(1, sizeof(ffd_nexthop_t));
+ nexthop->neigh = neigh;
+
+ nexthop->next = announce->nexthop_list;
+ announce->nexthop_list = nexthop;
+
+ ffd_neigh_ref(neigh);
+
+ return nexthop;
+}
+
+static inline bool find_seqno_request(ffd_seqno_req_t **reqp, ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno) {
+ ffd_seqno_req_t *req;
+ bool ret = true;
+
+ *reqp = NULL;
+
+ for (req = announce->seqno_req_list; req; req = req->next) {
+ if (req->neigh == neigh)
+ *reqp = req;
+
+ int16_t diff = req->seqno - seqno;
+ if (timespec_diff(&now, &req->last_req) < FFD_SEQNO_REQUEST_TIMEOUT && diff >= 0)
+ ret = false;
+ }
+
+ return ret;
+}
+
+bool ffd_announce_seqno_request(ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno) {
+ ffd_seqno_req_t *req;
+ bool ret = find_seqno_request(&req, announce, neigh, seqno);
+
+ if (!req) {
+ req = calloc(1, sizeof(ffd_seqno_req_t));
+ req->neigh = neigh;
+ req->seqno = seqno;
+ req->last_req = now;
+
+ ffd_neigh_ref(neigh);
+
+ req->next = announce->seqno_req_list;
+ announce->seqno_req_list = req;
+ }
+
+ int16_t diff = seqno - req->seqno;
+ if (diff > 0) {
+ req->seqno = seqno;
+ req->last_req = now;
+ }
+
+ if (ret) {
+ req->last_req = now;
+ return true;
+ }
+
+ return false;
+}
+
+void ffd_announce_seqno_request_free_list(ffd_announce_t *announce) {
+ ffd_seqno_req_t *req, *next;
+ for (req = announce->seqno_req_list; req; req = next) {
+ next = req->next;
+ ffd_neigh_unref(req->neigh);
+ free(req);
+ }
+}