aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip-neighbor/ip_neighbor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip-neighbor/ip_neighbor.c')
-rw-r--r--src/vnet/ip-neighbor/ip_neighbor.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/vnet/ip-neighbor/ip_neighbor.c b/src/vnet/ip-neighbor/ip_neighbor.c
index 960da1252a8..5b18473e462 100644
--- a/src/vnet/ip-neighbor/ip_neighbor.c
+++ b/src/vnet/ip-neighbor/ip_neighbor.c
@@ -99,6 +99,12 @@ ip_neighbor_get_index (const ip_neighbor_t * ipn)
return (ipn - ip_neighbor_pool);
}
+static void
+ip_neighbor_touch (ip_neighbor_t * ipn)
+{
+ ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_STALE;
+}
+
static bool
ip_neighbor_is_dynamic (const ip_neighbor_t * ipn)
{
@@ -145,6 +151,7 @@ ip_neighbor_refresh (ip_neighbor_t * ipn)
* list is time sorted, newest first */
ip_neighbor_elt_t *elt, *head;
+ ip_neighbor_touch (ipn);
ipn->ipn_time_last_updated = vlib_time_now (vlib_get_main ());
ipn->ipn_n_probes = 0;
@@ -473,6 +480,8 @@ ip_neighbor_add (const ip46_address_t * ip,
format_ip_neighbor_flags, flags, format_mac_address_t,
mac);
+ ip_neighbor_touch (ipn);
+
/* Refuse to over-write static neighbor entry. */
if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
@@ -1177,6 +1186,60 @@ ip_neighbor_flush (ip46_type_t type, u32 sw_if_index)
vec_free (ipnis);
}
+static walk_rc_t
+ip_neighbor_mark_one (index_t ipni, void *ctx)
+{
+ ip_neighbor_t *ipn;
+
+ ipn = ip_neighbor_get (ipni);
+
+ ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STALE;
+
+ return (WALK_CONTINUE);
+}
+
+void
+ip_neighbor_mark (ip46_type_t type)
+{
+ ip_neighbor_walk (type, ~0, ip_neighbor_mark_one, NULL);
+}
+
+typedef struct ip_neighbor_sweep_ctx_t_
+{
+ index_t *ipnsc_stale;
+} ip_neighbor_sweep_ctx_t;
+
+static walk_rc_t
+ip_neighbor_sweep_one (index_t ipni, void *arg)
+{
+ ip_neighbor_sweep_ctx_t *ctx = arg;
+ ip_neighbor_t *ipn;
+
+ ipn = ip_neighbor_get (ipni);
+
+ if (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STALE)
+ {
+ vec_add1 (ctx->ipnsc_stale, ipni);
+ }
+
+ return (WALK_CONTINUE);
+}
+
+void
+ip_neighbor_sweep (ip46_type_t type)
+{
+ ip_neighbor_sweep_ctx_t ctx = { };
+ index_t *ipni;
+
+ ip_neighbor_walk (type, ~0, ip_neighbor_sweep_one, &ctx);
+
+ vec_foreach (ipni, ctx.ipnsc_stale)
+ {
+ ip_neighbor_free (ip_neighbor_get (*ipni));
+ }
+ vec_free (ctx.ipnsc_stale);
+}
+
/*
* Remove any arp entries associated with the specified interface
*/