diff options
Diffstat (limited to 'src/vnet/ip-neighbor/ip_neighbor.c')
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor.c | 63 |
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 */ |