summaryrefslogtreecommitdiffstats
path: root/nest/neighbor.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/neighbor.c')
-rw-r--r--nest/neighbor.c67
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
*