From 15fbb0adbd228d40b9fafab937054f68ed2d4a16 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 8 Oct 2012 01:16:01 +0200 Subject: Handle disappearing interfaces --- ffd/announce.c | 7 ++++++- ffd/ffd.c | 26 +++++++++++++------------- ffd/ffd.h | 5 ++--- ffd/neigh.c | 14 ++++++++++---- ffd/neigh.h | 12 +++++++++++- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/ffd/announce.c b/ffd/announce.c index 6b30ec6..62e876a 100644 --- a/ffd/announce.c +++ b/ffd/announce.c @@ -45,7 +45,7 @@ static void maintain_nexthops(ffd_announce_t *announce) { if (announce->selected == nexthop) announce->selected = NULL; - nexthop->neigh->nexthop_refs--; + ffd_neigh_unref(nexthop->neigh); free(nexthop); } @@ -54,6 +54,11 @@ static void maintain_nexthops(ffd_announce_t *announce) { add_interval(&nexthop->last_update, FFD_UPDATE_TIMEOUT(nexthop->interval)); } } + else if (!nexthop->neigh->iface && nexthop->metric_seqno.metric != 0xffff) { + nexthop->metric_seqno.metric = 0xffff; + nexthop->last_update = now; + add_interval(&nexthop->last_update, FFD_UPDATE_TIMEOUT(nexthop->interval)); + } } } diff --git a/ffd/ffd.c b/ffd/ffd.c index 7cc3d3f..f5b3271 100644 --- a/ffd/ffd.c +++ b/ffd/ffd.c @@ -170,8 +170,7 @@ static void update_netifs(void) { if (iface->type == IF_UNSPEC) { *cur = iface->next; - - ffd_neigh_free_list(iface->neigh_list); + ffd_neigh_unref_list(iface->neigh_list); free(iface); } else { @@ -320,7 +319,7 @@ static ffd_nexthop_t* new_nexthop(ffd_announce_t *announce, ffd_neigh_t *neigh) nexthop->next = announce->nexthop_list; announce->nexthop_list = nexthop; - neigh->nexthop_refs++; + ffd_neigh_ref(neigh); return nexthop; } @@ -475,6 +474,8 @@ static void send_updates(void) { } static void maintenance(void) { + update_netifs(); + ffd_iface_t *iface; for (iface = iface_list; iface; iface = iface->next) { ffd_neigh_t **cur, **next; @@ -482,7 +483,7 @@ static void maintenance(void) { ffd_neigh_t *neigh = *cur; next = &neigh->next; - if (ffd_neigh_get_rxcost(neigh) == 0xffff && ffd_neigh_get_txcost(neigh) == 0xffff && !neigh->nexthop_refs) { + if (ffd_neigh_get_rxcost(neigh) == 0xffff && ffd_neigh_get_txcost(neigh) == 0xffff && !neigh->ref) { *cur = *next; next = cur; free(neigh); @@ -524,9 +525,10 @@ static void maintenance(void) { continue; } - fprintf(stderr, "\tnexthop: %02x:%02x:%02x:%02x:%02x:%02x (%u, seqno=%04x, cost=%u%s)\n", + fprintf(stderr, "\tnexthop: %02x:%02x:%02x:%02x:%02x:%02x[%s] (%u, seqno=%04x, cost=%u%s)\n", neigh->addr.d[0], neigh->addr.d[1], neigh->addr.d[2], neigh->addr.d[3], neigh->addr.d[4], neigh->addr.d[5], + neigh->iface ? neigh->iface->name : NULL, nexthop->metric_seqno.metric, nexthop->metric_seqno.seqno, ffd_neigh_get_cost(neigh), (nexthop == announce->selected) ? ", selected" : ""); } @@ -550,7 +552,12 @@ int main() { struct timespec next_maintenance = now; while (true) { - update_netifs(); + int maintenance_timeout = timespec_diff(&next_maintenance, &now); + if (maintenance_timeout <= 0) { + maintenance(); + + add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL); + } int hello_timeout = timespec_diff(&next_hello, &now); if (hello_timeout <= 0) { @@ -567,13 +574,6 @@ int main() { add_interval(&next_update, FFD_UPDATE_INTERVAL); } - int maintenance_timeout = timespec_diff(&next_maintenance, &now); - if (maintenance_timeout <= 0) { - maintenance(); - - add_interval(&next_maintenance, FFD_MAINTENANCE_INTERVAL); - } - int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout); if (timeout <= 0) continue; diff --git a/ffd/ffd.h b/ffd/ffd.h index 9bd0d2c..4199000 100644 --- a/ffd/ffd.h +++ b/ffd/ffd.h @@ -91,10 +91,9 @@ typedef struct _ffd_announce_t { typedef struct _ffd_neigh_t { struct _ffd_neigh_t *next; - unsigned nexthop_refs; + unsigned ref; - /* for actual routing, we'd also have to link back to the iface - this neighbour belongs to */ + struct _ffd_iface_t *iface; eth_addr_t addr; uint16_t hello_log; diff --git a/ffd/neigh.c b/ffd/neigh.c index ca72ccc..1b0d41d 100644 --- a/ffd/neigh.c +++ b/ffd/neigh.c @@ -32,6 +32,7 @@ ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr) { if (!neigh) { neigh = calloc(1, sizeof(ffd_neigh_t)); neigh->next = iface->neigh_list; + neigh->iface = iface; iface->neigh_list = neigh; neigh->addr = *addr; @@ -41,16 +42,21 @@ ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr) { return neigh; } -void ffd_neigh_free_list(ffd_neigh_t *neigh) { +void ffd_neigh_unref_list(ffd_neigh_t *neigh) { ffd_neigh_t *next; for (; neigh; neigh = next) { next = neigh->next; - free(neigh); + + neigh->iface = NULL; + neigh->next = NULL; + + if (!neigh->ref) + free(neigh); } } uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) { - if (!neigh->hello_log || !neigh->hello_interval) + if (!neigh->hello_log || !neigh->hello_interval || !neigh->iface) return 0xffff; int timediff = timespec_diff(&now, &neigh->last_hello); @@ -68,7 +74,7 @@ uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) { } uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh) { - if (timespec_diff(&now, &neigh->last_ihu) > FFD_IHU_TIMEOUT(neigh->ihu_interval)) + if (timespec_diff(&now, &neigh->last_ihu) > FFD_IHU_TIMEOUT(neigh->ihu_interval) || !neigh->iface) return 0xffff; else return neigh->txcost; diff --git a/ffd/neigh.h b/ffd/neigh.h index d82025c..aa0d1f9 100644 --- a/ffd/neigh.h +++ b/ffd/neigh.h @@ -40,8 +40,18 @@ static inline ffd_neigh_t* ffd_neigh_find(const ffd_iface_t *iface, const eth_ad return NULL; } +static inline void ffd_neigh_ref(ffd_neigh_t *neigh) { + neigh->ref++; +} + +static inline void ffd_neigh_unref(ffd_neigh_t *neigh) { + if (!(--neigh->ref) && !neigh->iface) + free(neigh); +} + ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr); -void ffd_neigh_free_list(ffd_neigh_t *neigh); +void ffd_neigh_unref(ffd_neigh_t *neigh); +void ffd_neigh_unref_list(ffd_neigh_t *neigh); uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh); uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh); -- cgit v1.2.3