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 :)
This commit is contained in:
Martin Mares 2000-01-19 11:52:32 +00:00
parent 3ea1ba632b
commit f5ad9f87a3
2 changed files with 19 additions and 31 deletions

View file

@ -87,12 +87,7 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags)
n->iface = j; n->iface = j;
add_tail(&neigh_list, &n->n); add_tail(&neigh_list, &n->n);
if (j) if (j)
{ add_tail(&j->neighbors, &n->if_n);
n->sibling = j->neigh;
j->neigh = n;
}
else
n->sibling = NULL;
n->proto = p; n->proto = p;
n->data = NULL; n->data = NULL;
n->aux = 0; n->aux = 0;
@ -135,8 +130,7 @@ neigh_if_up(struct iface *i)
if_connected(&n->addr, i) > 0) if_connected(&n->addr, i) > 0)
{ {
n->iface = i; n->iface = i;
n->sibling = i->neigh; add_tail(&i->neighbors, &n->if_n);
i->neigh = n;
DBG("Waking up sticky neighbor %I\n", n->addr); DBG("Waking up sticky neighbor %I\n", n->addr);
if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING) if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
n->proto->neigh_notify(n); n->proto->neigh_notify(n);
@ -146,12 +140,13 @@ neigh_if_up(struct iface *i)
static void static void
neigh_if_down(struct iface *i) 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); DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
rem_node(&n->if_n);
n->iface = NULL; n->iface = NULL;
if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING) if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
n->proto->neigh_notify(n); n->proto->neigh_notify(n);
@ -161,30 +156,22 @@ neigh_if_down(struct iface *i)
sl_free(neigh_slab, n); sl_free(neigh_slab, n);
} }
} }
i->neigh = NULL;
} }
void void
neigh_prune(void) neigh_prune(void)
{ {
neighbor *n, *m, **N; neighbor *n;
struct iface *i; node *m;
DBG("Pruning neighbors\n"); DBG("Pruning neighbors\n");
WALK_LIST(i, iface_list) WALK_LIST_DELSAFE(n, m, neigh_list)
{
N = &i->neigh;
while (n = *N)
{
if (n->proto->core_state == FS_FLUSHING) if (n->proto->core_state == FS_FLUSHING)
{ {
*N = n->sibling;
rem_node(&n->n); rem_node(&n->n);
if (n->iface)
rem_node(&n->if_n);
sl_free(neigh_slab, n); sl_free(neigh_slab, n);
continue;
}
N = &n->sibling;
}
} }
} }
@ -377,6 +364,7 @@ if_update(struct iface *new)
i = mb_alloc(if_pool, sizeof(struct iface)); i = mb_alloc(if_pool, sizeof(struct iface));
memcpy(i, new, sizeof(*i)); memcpy(i, new, sizeof(*i));
init_list(&i->addrs); init_list(&i->addrs);
init_list(&i->neighbors);
newif: newif:
i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */ i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
add_tail(&iface_list, &i->n); add_tail(&iface_list, &i->n);

View file

@ -35,7 +35,7 @@ struct iface {
unsigned index; /* OS-dependent interface index */ unsigned index; /* OS-dependent interface index */
list addrs; /* Addresses assigned to this interface */ list addrs; /* Addresses assigned to this interface */
struct ifa *addr; /* Primary address */ 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 */ #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 { typedef struct neighbor {
node n; /* Node in global neighbor list */ node n; /* Node in global neighbor list */
node if_n; /* Node in per-interface neighbor list */
ip_addr addr; /* Address of the neighbor */ ip_addr addr; /* Address of the neighbor */
struct iface *iface; /* Interface it's connected to */ struct iface *iface; /* Interface it's connected to */
struct neighbor *sibling; /* Next in per-device chain */
struct proto *proto; /* Protocol this belongs to */ struct proto *proto; /* Protocol this belongs to */
void *data; /* Protocol-specific data */ void *data; /* Protocol-specific data */
unsigned aux; /* Protocol-specific data */ unsigned aux; /* Protocol-specific data */