Handle disappearing interfaces

This commit is contained in:
Matthias Schiffer 2012-10-08 01:16:01 +02:00
parent a934dcc3ce
commit 15fbb0adbd
5 changed files with 42 additions and 22 deletions

View file

@ -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));
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);