From 8e810f5fd809bad3047ea9224dd058edd20a64ac Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 8 Oct 2012 07:32:38 +0200 Subject: Keep track of forwarded seqno requests --- ffd/announce.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) (limited to 'ffd/announce.c') 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); + } +} -- cgit v1.2.3