diff options
author | Neale Ranns <nranns@cisco.com> | 2020-04-02 17:08:28 +0000 |
---|---|---|
committer | Neale Ranns <nranns@cisco.com> | 2020-04-23 08:15:39 +0000 |
commit | c87fbb417a580bf8e93d0176dba6a90b3cd6a787 (patch) | |
tree | a412c1c9afb4f8728632164d731f1adf67bfd6d3 /src/vnet/ip-neighbor | |
parent | c17ff6ec3b69ef228047bf346e0b524c48d2c96e (diff) |
ip-neighbor: Replace feature for the ip-neighbor data-base
Type: feature
DB replace is implemented with a mark and sweep algorithm (just the the
FIB)
Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: I54ab06e11552219e2a18e1b4a87d531321cf3829
Diffstat (limited to 'src/vnet/ip-neighbor')
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor.api | 37 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor.c | 63 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor.h | 3 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor_api.c | 26 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor_types.c | 17 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip_neighbor_types.h | 14 |
6 files changed, 145 insertions, 15 deletions
diff --git a/src/vnet/ip-neighbor/ip_neighbor.api b/src/vnet/ip-neighbor/ip_neighbor.api index b82036052f7..fc8f8222189 100644 --- a/src/vnet/ip-neighbor/ip_neighbor.api +++ b/src/vnet/ip-neighbor/ip_neighbor.api @@ -126,6 +126,43 @@ autoreply define ip_neighbor_config bool recycle; }; +/** \brief IP neighbour replace begin + + The use-case is that, for some unspecified reason, the control plane + has a different set of neighbours it than VPP + currently has. The CP would thus like to 'replace' VPP's set + only by specifying what the new set shall be, i.e. it is not + going to delete anything that already eixts, rather, is wants any + unspecified neighbors deleted implicitly. + The CP declares the start of this procedure with this replace_begin + API Call, and when it has populated all neighbours it wants, it calls + the below replace_end API. From this point on it is of course free + to add and delete neighbours as usual. + The underlying mechanism by which VPP implements this replace is + intentionally left unspecified. + + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +autoreply define ip_neighbor_replace_begin +{ + u32 client_index; + u32 context; +}; + +/** \brief IP neighbour replace end + + see ip_neighbor_replace_begin description. + + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +autoreply define ip_neighbor_replace_end +{ + u32 client_index; + u32 context; +}; + /** \brief Register for IP4 ARP resolution event on receing ARP reply or MAC/IP info from ARP requests in L2 BDs @param client_index - opaque cookie to identify the sender 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 */ diff --git a/src/vnet/ip-neighbor/ip_neighbor.h b/src/vnet/ip-neighbor/ip_neighbor.h index cb384c5e240..8769fd5efd7 100644 --- a/src/vnet/ip-neighbor/ip_neighbor.h +++ b/src/vnet/ip-neighbor/ip_neighbor.h @@ -62,6 +62,9 @@ extern void ip_neighbor_probe (const ip_adjacency_t * adj); extern void ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * ip); +extern void ip_neighbor_mark (ip46_type_t type); +extern void ip_neighbor_sweep (ip46_type_t type); + /** * From the watcher to the API to publish a new neighbor */ diff --git a/src/vnet/ip-neighbor/ip_neighbor_api.c b/src/vnet/ip-neighbor/ip_neighbor_api.c index ec1e493f368..86587fab31b 100644 --- a/src/vnet/ip-neighbor/ip_neighbor_api.c +++ b/src/vnet/ip-neighbor/ip_neighbor_api.c @@ -275,6 +275,32 @@ vl_api_ip_neighbor_config_t_handler (vl_api_ip_neighbor_config_t * mp) REPLY_MACRO (VL_API_IP_NEIGHBOR_CONFIG_REPLY); } +static void +vl_api_ip_neighbor_replace_begin_t_handler (vl_api_ip_neighbor_replace_begin_t + * mp) +{ + vl_api_ip_neighbor_replace_begin_reply_t *rmp; + int rv = 0; + + ip_neighbor_mark (IP46_TYPE_IP4); + ip_neighbor_mark (IP46_TYPE_IP6); + + REPLY_MACRO (VL_API_IP_NEIGHBOR_REPLACE_BEGIN_REPLY); +} + +static void +vl_api_ip_neighbor_replace_end_t_handler (vl_api_ip_neighbor_replace_end_t * + mp) +{ + vl_api_ip_neighbor_replace_end_reply_t *rmp; + int rv = 0; + + ip_neighbor_sweep (IP46_TYPE_IP4); + ip_neighbor_sweep (IP46_TYPE_IP6); + + REPLY_MACRO (VL_API_IP_NEIGHBOR_REPLACE_END_REPLY); +} + #define vl_msg_name_crc_list #include <vnet/ip-neighbor/ip_neighbor.api.h> #undef vl_msg_name_crc_list diff --git a/src/vnet/ip-neighbor/ip_neighbor_types.c b/src/vnet/ip-neighbor/ip_neighbor_types.c index 27262a5d62c..32c674d2392 100644 --- a/src/vnet/ip-neighbor/ip_neighbor_types.c +++ b/src/vnet/ip-neighbor/ip_neighbor_types.c @@ -22,19 +22,14 @@ format_ip_neighbor_flags (u8 * s, va_list * args) { ip_neighbor_flags_t flags = va_arg (*args, int); - if (flags & IP_NEIGHBOR_FLAG_STATIC) - s = format (s, "S"); - - if (flags & IP_NEIGHBOR_FLAG_DYNAMIC) - s = format (s, "D"); - - if (flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY) - s = format (s, "N"); - - return s; +#define _(a,b,c,d) \ + if (flags & IP_NEIGHBOR_FLAG_##a) \ + s = format (s, "%s", d); + foreach_ip_neighbor_flag +#undef _ + return s; } - u8 * format_ip_neighbor_key (u8 * s, va_list * va) { diff --git a/src/vnet/ip-neighbor/ip_neighbor_types.h b/src/vnet/ip-neighbor/ip_neighbor_types.h index c6d4e104e8b..82c54177e80 100644 --- a/src/vnet/ip-neighbor/ip_neighbor_types.h +++ b/src/vnet/ip-neighbor/ip_neighbor_types.h @@ -37,13 +37,19 @@ typedef struct u8 stale_threshold; /* Threshold in minutes to delete nei entry */ } ip_neighbor_scan_arg_t; +#define foreach_ip_neighbor_flag \ + _(STATIC, 1 << 0, "static", "S") \ + _(DYNAMIC, 1 << 1, "dynamic", "D") \ + _(NO_FIB_ENTRY, 1 << 2, "no-fib-entry", "N") \ + _(PENDING, 1 << 3, "pending", "P") \ + _(STALE, 1 << 4, "stale", "A") \ + typedef enum ip_neighbor_flags_t_ { IP_NEIGHBOR_FLAG_NONE = 0, - IP_NEIGHBOR_FLAG_STATIC = (1 << 0), - IP_NEIGHBOR_FLAG_DYNAMIC = (1 << 1), - IP_NEIGHBOR_FLAG_NO_FIB_ENTRY = (1 << 2), - IP_NEIGHBOR_FLAG_PENDING = (1 << 3), +#define _(a,b,c,d) IP_NEIGHBOR_FLAG_##a = b, + foreach_ip_neighbor_flag +#undef _ } __attribute__ ((packed)) ip_neighbor_flags_t; typedef struct ip_neighbor_watcher_t_ |