Keep track of forwarded seqno requests

This commit is contained in:
Matthias Schiffer 2012-10-08 07:32:38 +02:00
parent e912f03740
commit 8e810f5fd8
3 changed files with 132 additions and 30 deletions

View file

@ -110,6 +110,26 @@ ffd_metric_seqno_t get_metric(const ffd_announce_t *announce) {
return (ffd_metric_seqno_t){0xffff, 0}; 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) { void ffd_announce_update(ffd_announce_t *announce) {
maintain_nexthops(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"); fprintf(stderr, "info: announce metric has changed significantly, sending updates\n");
ffd_send_update(NULL, NULL, announce, false); 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) { 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; 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);
}
}

View file

@ -284,28 +284,6 @@ static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len,
arg->node_id = tlv_node_id->id; arg->node_id = tlv_node_id->id;
} }
static ffd_nexthop_t* find_nexthop(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;
}
static ffd_nexthop_t* new_nexthop(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 void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, handle_tlv_arg_t *arg) { static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, handle_tlv_arg_t *arg) {
if (len < sizeof(ffd_tlv_update_t)) { if (len < sizeof(ffd_tlv_update_t)) {
fprintf(stderr, "warn: received short update TLV.\n"); fprintf(stderr, "warn: received short update TLV.\n");
@ -329,11 +307,11 @@ static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, ha
bool feasible = ffd_is_feasible(announce, ms); bool feasible = ffd_is_feasible(announce, ms);
ffd_neigh_t *neigh = get_tlv_neigh(arg); ffd_neigh_t *neigh = get_tlv_neigh(arg);
ffd_nexthop_t *nexthop = find_nexthop(announce, neigh); ffd_nexthop_t *nexthop = ffd_announce_nexthop_find(announce, neigh);
if (!nexthop) { if (!nexthop) {
if (feasible && tlv_update->metric != 0xffff /* no need to ntohs */) if (feasible && tlv_update->metric != 0xffff /* no need to ntohs */)
nexthop = new_nexthop(announce, neigh); nexthop = ffd_announce_nexthop_new(announce, neigh);
} }
else { else {
if (!feasible && nexthop == announce->selected) { if (!feasible && nexthop == announce->selected) {
@ -397,8 +375,6 @@ static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len,
return; return;
} }
fprintf(stderr, "debug: received seqno request\n");
ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key)); ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key));
if (!announce) { if (!announce) {
@ -416,21 +392,28 @@ static void handle_tlv_seqno_req(const ffd_tlv_seqno_req_t *tlv_req, size_t len,
if (announce->selected->neigh == neigh) if (announce->selected->neigh == neigh)
return; return;
if ((int16_t)(ntohs(tlv_req->seqno)-announce->selected->metric_seqno.seqno) <= 0) { uint16_t seqno = ntohs(tlv_req->seqno);
if ((int16_t)(seqno-announce->selected->metric_seqno.seqno) <= 0) {
fprintf(stderr, "debug: received seqno request, seqno already ok\n"); fprintf(stderr, "debug: received seqno request, seqno already ok\n");
ffd_send_update(NULL, neigh, announce, false); ffd_send_update(NULL, neigh, announce, false);
return; return;
} }
if (!announce->selected->neigh) { if (!announce->selected->neigh) {
fprintf(stderr, "debug: incrementing seqno\n"); fprintf(stderr, "debug: received seqno request, incrementing seqno\n");
announce->selected->metric_seqno.seqno++; announce->selected->metric_seqno.seqno++;
ffd_send_update(NULL, neigh, announce, false); ffd_send_update(NULL, neigh, announce, false);
return; return;
} }
if (ffd_announce_seqno_request(announce, neigh, seqno)) {
fprintf(stderr, "debug: received seqno request, forwarding\n"); fprintf(stderr, "debug: received seqno request, forwarding\n");
ffd_send_seqno_request(announce->selected->neigh, announce, ntohs(tlv_req->seqno)); ffd_send_seqno_request(announce->selected->neigh, announce, seqno);
}
else {
fprintf(stderr, "debug: received seqno request, not forwarding again\n");
}
} }
static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) { static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) {
@ -547,6 +530,7 @@ static void maintenance(void) {
if (!announce->nexthop_list) { if (!announce->nexthop_list) {
*cur = *next; *cur = *next;
next = cur; next = cur;
ffd_announce_seqno_request_free_list(announce);
free(announce); free(announce);
continue; continue;

View file

@ -47,6 +47,8 @@
#define FFD_UPDATE_REQUEST_TIMEOUT(interval) ((interval)*13/4) /* 3.25 intervals */ #define FFD_UPDATE_REQUEST_TIMEOUT(interval) ((interval)*13/4) /* 3.25 intervals */
#define FFD_SEQNO_REQUEST_TIMEOUT 50
#define FFD_MAINTENANCE_INTERVAL FFD_HELLO_INTERVAL #define FFD_MAINTENANCE_INTERVAL FFD_HELLO_INTERVAL
@ -73,6 +75,14 @@ typedef struct _ffd_nexthop_t {
bool requested_update; bool requested_update;
} ffd_nexthop_t; } ffd_nexthop_t;
typedef struct _ffd_seqno_req_t {
struct _ffd_seqno_req_t *next;
struct timespec last_req;
struct _ffd_neigh_t *neigh;
uint16_t seqno;
} ffd_seqno_req_t;
typedef struct _ffd_announce_t { typedef struct _ffd_announce_t {
struct _ffd_announce_t *next; struct _ffd_announce_t *next;
@ -84,6 +94,8 @@ typedef struct _ffd_announce_t {
uint16_t last_metric; uint16_t last_metric;
ffd_metric_seqno_t feasibility_distance; ffd_metric_seqno_t feasibility_distance;
ffd_seqno_req_t *seqno_req_list;
ffd_nexthop_t *selected; ffd_nexthop_t *selected;
ffd_nexthop_t *nexthop_list; ffd_nexthop_t *nexthop_list;
@ -189,6 +201,10 @@ void ffd_announce_update_nexthop(ffd_announce_t *announce, ffd_nexthop_t *nextho
ffd_announce_t* ffd_announce_new(void); ffd_announce_t* ffd_announce_new(void);
ffd_announce_t* ffd_announce_find(const ffd_node_id_t *node, uint16_t type, uint16_t key); ffd_announce_t* ffd_announce_find(const ffd_node_id_t *node, uint16_t type, uint16_t key);
ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint16_t key); ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint16_t key);
ffd_nexthop_t* ffd_announce_nexthop_find(const ffd_announce_t *announce, ffd_neigh_t *neigh);
ffd_nexthop_t* ffd_announce_nexthop_new(ffd_announce_t *announce, ffd_neigh_t *neigh);
bool ffd_announce_seqno_request(ffd_announce_t *announce, ffd_neigh_t *neigh, uint16_t seqno);
void ffd_announce_seqno_request_free_list(ffd_announce_t *announce);
void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce); void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce);
void ffd_send_hellos(void); void ffd_send_hellos(void);