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)
|
if (announce->selected == nexthop)
|
||||||
announce->selected = NULL;
|
announce->selected = NULL;
|
||||||
|
|
||||||
nexthop->neigh->nexthop_refs--;
|
ffd_neigh_unref(nexthop->neigh);
|
||||||
|
|
||||||
free(nexthop);
|
free(nexthop);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,11 @@ static void maintain_nexthops(ffd_announce_t *announce) {
|
||||||
add_interval(&nexthop->last_update, FFD_UPDATE_TIMEOUT(nexthop->interval));
|
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) {
|
if (iface->type == IF_UNSPEC) {
|
||||||
*cur = iface->next;
|
*cur = iface->next;
|
||||||
|
ffd_neigh_unref_list(iface->neigh_list);
|
||||||
ffd_neigh_free_list(iface->neigh_list);
|
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -320,7 +319,7 @@ static ffd_nexthop_t* new_nexthop(ffd_announce_t *announce, ffd_neigh_t *neigh)
|
||||||
nexthop->next = announce->nexthop_list;
|
nexthop->next = announce->nexthop_list;
|
||||||
announce->nexthop_list = nexthop;
|
announce->nexthop_list = nexthop;
|
||||||
|
|
||||||
neigh->nexthop_refs++;
|
ffd_neigh_ref(neigh);
|
||||||
|
|
||||||
return nexthop;
|
return nexthop;
|
||||||
}
|
}
|
||||||
|
@ -475,6 +474,8 @@ static void send_updates(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maintenance(void) {
|
static void maintenance(void) {
|
||||||
|
update_netifs();
|
||||||
|
|
||||||
ffd_iface_t *iface;
|
ffd_iface_t *iface;
|
||||||
for (iface = iface_list; iface; iface = iface->next) {
|
for (iface = iface_list; iface; iface = iface->next) {
|
||||||
ffd_neigh_t **cur, **next;
|
ffd_neigh_t **cur, **next;
|
||||||
|
@ -482,7 +483,7 @@ static void maintenance(void) {
|
||||||
ffd_neigh_t *neigh = *cur;
|
ffd_neigh_t *neigh = *cur;
|
||||||
next = &neigh->next;
|
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;
|
*cur = *next;
|
||||||
next = cur;
|
next = cur;
|
||||||
free(neigh);
|
free(neigh);
|
||||||
|
@ -524,9 +525,10 @@ static void maintenance(void) {
|
||||||
continue;
|
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[0], neigh->addr.d[1], neigh->addr.d[2],
|
||||||
neigh->addr.d[3], neigh->addr.d[4], neigh->addr.d[5],
|
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->metric_seqno.metric, nexthop->metric_seqno.seqno, ffd_neigh_get_cost(neigh),
|
||||||
(nexthop == announce->selected) ? ", selected" : "");
|
(nexthop == announce->selected) ? ", selected" : "");
|
||||||
}
|
}
|
||||||
|
@ -550,7 +552,12 @@ int main() {
|
||||||
struct timespec next_maintenance = now;
|
struct timespec next_maintenance = now;
|
||||||
|
|
||||||
while (true) {
|
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);
|
int hello_timeout = timespec_diff(&next_hello, &now);
|
||||||
if (hello_timeout <= 0) {
|
if (hello_timeout <= 0) {
|
||||||
|
@ -567,13 +574,6 @@ int main() {
|
||||||
add_interval(&next_update, FFD_UPDATE_INTERVAL);
|
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);
|
int timeout = min(min(hello_timeout, update_timeout), maintenance_timeout);
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -91,10 +91,9 @@ typedef struct _ffd_announce_t {
|
||||||
typedef struct _ffd_neigh_t {
|
typedef struct _ffd_neigh_t {
|
||||||
struct _ffd_neigh_t *next;
|
struct _ffd_neigh_t *next;
|
||||||
|
|
||||||
unsigned nexthop_refs;
|
unsigned ref;
|
||||||
|
|
||||||
/* for actual routing, we'd also have to link back to the iface
|
struct _ffd_iface_t *iface;
|
||||||
this neighbour belongs to */
|
|
||||||
eth_addr_t addr;
|
eth_addr_t addr;
|
||||||
|
|
||||||
uint16_t hello_log;
|
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) {
|
if (!neigh) {
|
||||||
neigh = calloc(1, sizeof(ffd_neigh_t));
|
neigh = calloc(1, sizeof(ffd_neigh_t));
|
||||||
neigh->next = iface->neigh_list;
|
neigh->next = iface->neigh_list;
|
||||||
|
neigh->iface = iface;
|
||||||
iface->neigh_list = neigh;
|
iface->neigh_list = neigh;
|
||||||
neigh->addr = *addr;
|
neigh->addr = *addr;
|
||||||
|
|
||||||
|
@ -41,16 +42,21 @@ ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr) {
|
||||||
return neigh;
|
return neigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffd_neigh_free_list(ffd_neigh_t *neigh) {
|
void ffd_neigh_unref_list(ffd_neigh_t *neigh) {
|
||||||
ffd_neigh_t *next;
|
ffd_neigh_t *next;
|
||||||
for (; neigh; neigh = next) {
|
for (; neigh; neigh = next) {
|
||||||
next = 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) {
|
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;
|
return 0xffff;
|
||||||
|
|
||||||
int timediff = timespec_diff(&now, &neigh->last_hello);
|
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) {
|
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;
|
return 0xffff;
|
||||||
else
|
else
|
||||||
return neigh->txcost;
|
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;
|
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);
|
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_rxcost(const ffd_neigh_t *neigh);
|
||||||
uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh);
|
uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh);
|
||||||
|
|
Reference in a new issue