diff options
author | Martin Mares <mj@ucw.cz> | 2000-01-19 12:52:32 +0100 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2000-01-19 12:52:32 +0100 |
commit | f5ad9f87a389c1167a8468d0190bcf6d3cc33cf6 (patch) | |
tree | 30f8f843d3767ac567bd0e22dd8dae6ae513b537 | |
parent | 3ea1ba632b3cdb5005a9339fd5e74d5f93631a48 (diff) | |
download | bird-f5ad9f87a389c1167a8468d0190bcf6d3cc33cf6.tar bird-f5ad9f87a389c1167a8468d0190bcf6d3cc33cf6.zip |
Killed a couple of bugs in the neighbor cache.
Manual disable/enable/restart/shutdown/reconfiguration of protocols
no longer hangs on loops in neighbor lists :)
-rw-r--r-- | nest/iface.c | 46 | ||||
-rw-r--r-- | nest/iface.h | 4 |
2 files changed, 19 insertions, 31 deletions
diff --git a/nest/iface.c b/nest/iface.c index bf73b46..ce233cd 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -87,12 +87,7 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags) n->iface = j; add_tail(&neigh_list, &n->n); if (j) - { - n->sibling = j->neigh; - j->neigh = n; - } - else - n->sibling = NULL; + add_tail(&j->neighbors, &n->if_n); n->proto = p; n->data = NULL; n->aux = 0; @@ -135,8 +130,7 @@ neigh_if_up(struct iface *i) if_connected(&n->addr, i) > 0) { n->iface = i; - n->sibling = i->neigh; - i->neigh = n; + add_tail(&i->neighbors, &n->if_n); DBG("Waking up sticky neighbor %I\n", n->addr); if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING) n->proto->neigh_notify(n); @@ -146,12 +140,13 @@ neigh_if_up(struct iface *i) static void neigh_if_down(struct iface *i) { - neighbor *n, *m; + node *x, *y; - for(m=i->neigh; n = m;) + WALK_LIST_DELSAFE(x, y, i->neighbors) { - m = n->sibling; + neighbor *n = SKIP_BACK(neighbor, if_n, x); DBG("Flushing neighbor %I on %s\n", n->addr, i->name); + rem_node(&n->if_n); n->iface = NULL; if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING) n->proto->neigh_notify(n); @@ -161,31 +156,23 @@ neigh_if_down(struct iface *i) sl_free(neigh_slab, n); } } - i->neigh = NULL; } void neigh_prune(void) { - neighbor *n, *m, **N; - struct iface *i; + neighbor *n; + node *m; DBG("Pruning neighbors\n"); - WALK_LIST(i, iface_list) - { - N = &i->neigh; - while (n = *N) - { - if (n->proto->core_state == FS_FLUSHING) - { - *N = n->sibling; - rem_node(&n->n); - sl_free(neigh_slab, n); - continue; - } - N = &n->sibling; - } - } + WALK_LIST_DELSAFE(n, m, neigh_list) + if (n->proto->core_state == FS_FLUSHING) + { + rem_node(&n->n); + if (n->iface) + rem_node(&n->if_n); + sl_free(neigh_slab, n); + } } /* @@ -377,6 +364,7 @@ if_update(struct iface *new) i = mb_alloc(if_pool, sizeof(struct iface)); memcpy(i, new, sizeof(*i)); init_list(&i->addrs); + init_list(&i->neighbors); newif: i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */ add_tail(&iface_list, &i->n); diff --git a/nest/iface.h b/nest/iface.h index 64bc6b4..b13ec71 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -35,7 +35,7 @@ struct iface { unsigned index; /* OS-dependent interface index */ list addrs; /* Addresses assigned to this interface */ struct ifa *addr; /* Primary address */ - struct neighbor *neigh; /* List of neighbors on this interface */ + list neighbors; /* All neighbors on this interface */ }; #define IF_UP 1 /* IF_LINK_UP and IP address known */ @@ -94,9 +94,9 @@ struct iface *if_find_by_name(char *); typedef struct neighbor { node n; /* Node in global neighbor list */ + node if_n; /* Node in per-interface neighbor list */ ip_addr addr; /* Address of the neighbor */ struct iface *iface; /* Interface it's connected to */ - struct neighbor *sibling; /* Next in per-device chain */ struct proto *proto; /* Protocol this belongs to */ void *data; /* Protocol-specific data */ unsigned aux; /* Protocol-specific data */ |