diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2011-12-08 01:09:26 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2011-12-09 05:58:32 +0100 |
commit | b95254f5391542985202b64353c0d0dd6a28ecf7 (patch) | |
tree | f5ff53574e859f24db2ef04f96b5f27f6dea73fb /nest/neighbor.c | |
parent | 2779d50a24dc1b7c6b4cf83a17af817c02462855 (diff) | |
download | bird-b95254f5391542985202b64353c0d0dd6a28ecf7.tar bird-b95254f5391542985202b64353c0d0dd6a28ecf7.zip |
Update the neighbor cache on every address addition or removal
Only updating the cache when an interface goes up or down leaves it unaware
of addresses that are added or removed without taking the interface down.
Diffstat (limited to 'nest/neighbor.c')
-rw-r--r-- | nest/neighbor.c | 67 |
1 files changed, 32 insertions, 35 deletions
diff --git a/nest/neighbor.c b/nest/neighbor.c index 1a5ac21..cf1b2e9 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -220,20 +220,47 @@ neigh_dump_all(void) } /** - * neigh_if_up: notify neighbor cache about interface up event - * @i: interface in question + * neigh_ifa_update: notify neighbor cache about interface address + * add or remove event + * @ifa: interface address in question * - * Tell the neighbor cache that a new interface became up. + * Tell the neighbor cache that a address was added or removed. * * The neighbor cache wakes up all inactive sticky neighbors with - * addresses belonging to prefixes of the interface @i. + * addresses belonging to prefixes of the interface belonging to @ifa + * and causes all unreachable neighbors to be flushed + * + * A change of the scope of a neighbor is handle as a remove with + * a consequent add */ void -neigh_if_up(struct iface *i) +neigh_ifa_update(struct ifa *a) { + node *x, *y; neighbor *n, *next; + struct iface *i = a->iface; int scope; + /* Remove all neighbors whose scope has changed */ + WALK_LIST_DELSAFE(x, y, i->neighbors) + { + n = SKIP_BACK(neighbor, if_n, x); + if (if_connected(&n->addr, i) != n->scope) + { + 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); + rem_node(&n->n); + if (n->flags & NEF_STICKY) + add_tail(&sticky_neigh_list, &n->n); + else + sl_free(neigh_slab, n); + } + } + + /* Traverse the sticky neighbor list to find neighbors that are reachable now */ WALK_LIST_DELSAFE(n, next, sticky_neigh_list) if ((scope = if_connected(&n->addr, i)) >= 0) { @@ -249,36 +276,6 @@ neigh_if_up(struct iface *i) } /** - * neigh_if_down - notify neighbor cache about interface down event - * @i: the interface in question - * - * Notify the neighbor cache that an interface has ceased to exist. - * - * It causes all entries belonging to neighbors connected to this interface - * to be flushed. - */ -void -neigh_if_down(struct iface *i) -{ - node *x, *y; - - WALK_LIST_DELSAFE(x, y, i->neighbors) - { - 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); - rem_node(&n->n); - if (n->flags & NEF_STICKY) - add_tail(&sticky_neigh_list, &n->n); - else - sl_free(neigh_slab, n); - } -} - -/** * neigh_if_link - notify neighbor cache about interface link change * @i: the interface in question * |