Handle disappearing interfaces
This commit is contained in:
parent
a934dcc3ce
commit
15fbb0adbd
5 changed files with 42 additions and 22 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
26
ffd/ffd.c
26
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
14
ffd/neigh.c
14
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;
|
||||
|
|
12
ffd/neigh.h
12
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);
|
||||
|
|
Reference in a new issue