summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-10-08 01:16:01 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-10-08 01:16:01 +0200
commit15fbb0adbd228d40b9fafab937054f68ed2d4a16 (patch)
tree83ed99ff67f14c3b612250096e623825dcceda01
parenta934dcc3ce78b22a0ff4db5d353a3d8dcc2b5f1d (diff)
downloadffd-15fbb0adbd228d40b9fafab937054f68ed2d4a16.tar
ffd-15fbb0adbd228d40b9fafab937054f68ed2d4a16.zip
Handle disappearing interfaces
-rw-r--r--ffd/announce.c7
-rw-r--r--ffd/ffd.c26
-rw-r--r--ffd/ffd.h5
-rw-r--r--ffd/neigh.c14
-rw-r--r--ffd/neigh.h12
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);