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:
parent
3ea1ba632b
commit
f5ad9f87a3
2 changed files with 19 additions and 31 deletions
36
nest/iface.c
36
nest/iface.c
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue