diff options
author | Neale Ranns <nranns@cisco.com> | 2019-12-04 06:11:00 +0000 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2019-12-04 22:47:12 +0000 |
commit | 3bab8f9c5396a7bf1115b93a9e0691a76a9ed14c (patch) | |
tree | 0212708b47f042ac393848e0471669f837788278 /src/vnet | |
parent | 5f8f6173328f8d77feea5fd100e150c3094c11f0 (diff) |
fib: Decouple source from priority and behaviour
Type: feature
the fib_source_t enum alone no longer defines the priority and
behaviour, instead each source must be allocated these attributes.
This allows the creation of other sources by the plugins (and
soon over the API).
Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: I890ee820fbc16079ee417ea1fbc163192806e853
Diffstat (limited to 'src/vnet')
25 files changed, 752 insertions, 378 deletions
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 11827734a60..21653ab7c7a 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1248,21 +1248,22 @@ list(APPEND VNET_SOURCES fib/fib_node_list.c fib/fib_entry.c fib/fib_entry_src.c - fib/fib_entry_src_rr.c + fib/fib_entry_src_adj.c + fib/fib_entry_src_api.c + fib/fib_entry_src_drop.c fib/fib_entry_src_interface.c fib/fib_entry_src_interpose.c - fib/fib_entry_src_default_route.c - fib/fib_entry_src_special.c - fib/fib_entry_src_api.c - fib/fib_entry_src_adj.c - fib/fib_entry_src_mpls.c fib/fib_entry_src_lisp.c + fib/fib_entry_src_mpls.c + fib/fib_entry_src_simple.c + fib/fib_entry_src_rr.c fib/fib_entry_cover.c fib/fib_entry_delegate.c fib/fib_entry_track.c fib/fib_path_list.c fib/fib_path.c fib/fib_path_ext.c + fib/fib_source.c fib/fib_urpf_list.c fib/fib_attached_export.c fib/fib_api.c @@ -1280,6 +1281,7 @@ list(APPEND VNET_HEADERS fib/fib_node_list.h fib/fib_entry.h fib/fib_entry_delegate.h + fib/fib_source.h ) list(APPEND VNET_API_FILES fib/fib_types.api) diff --git a/src/vnet/fib/fib.c b/src/vnet/fib/fib.c index 28e18dded23..ddfa830bb0f 100644 --- a/src/vnet/fib/fib.c +++ b/src/vnet/fib/fib.c @@ -22,6 +22,7 @@ static clib_error_t * fib_module_init (vlib_main_t * vm) { + fib_source_module_init(); fib_entry_module_init(); fib_entry_src_module_init(); fib_path_module_init(); diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c index fd69db989f2..0e5482840bf 100644 --- a/src/vnet/fib/fib_entry.c +++ b/src/vnet/fib/fib_entry.c @@ -34,7 +34,6 @@ /* * Array of strings/names for the FIB sources */ -static const char *fib_source_names[] = FIB_SOURCES; static const char *fib_attribute_names[] = FIB_ENTRY_ATTRIBUTES; static const char *fib_src_attribute_names[] = FIB_ENTRY_SRC_ATTRIBUTES; @@ -98,16 +97,6 @@ fib_entry_get_default_chain_type (const fib_entry_t *fib_entry) } u8 * -format_fib_source (u8 * s, va_list * args) -{ - fib_source_t source = va_arg (*args, int); - - s = format (s, "src:%s", fib_source_names[source]); - - return (s); -} - -u8 * format_fib_entry_flags (u8 *s, va_list *args) { fib_entry_attribute_t attr; @@ -285,7 +274,7 @@ fib_entry_src_get_source (const fib_entry_src_t *esrc) { return (esrc->fes_src); } - return (FIB_SOURCE_MAX); + return (FIB_SOURCE_INVALID); } static fib_entry_flag_t @@ -836,16 +825,17 @@ fib_entry_source_change_w_flags (fib_entry_t *fib_entry, fib_entry_flag_t old_flags, fib_source_t new_source) { - if (new_source < old_source) + switch (fib_source_cmp(new_source, old_source)) { + case FIB_SOURCE_CMP_BETTER: /* * we have a new winning source. */ fib_entry_src_action_deactivate(fib_entry, old_source); fib_entry_src_action_activate(fib_entry, new_source); - } - else if (new_source > old_source) - { + break; + + case FIB_SOURCE_CMP_WORSE: /* * the new source loses. Re-activate the winning sources * in case it is an interposer and hence relied on the losing @@ -853,15 +843,15 @@ fib_entry_source_change_w_flags (fib_entry_t *fib_entry, */ fib_entry_src_action_reactivate(fib_entry, old_source); return; - } - else - { + + case FIB_SOURCE_CMP_EQUAL: /* * the new source is one this entry already has. * But the path-list was updated, which will contribute new forwarding, * so install it. */ fib_entry_src_action_reactivate(fib_entry, new_source); + break; } fib_entry_post_update_actions(fib_entry, new_source, old_flags); @@ -984,7 +974,7 @@ fib_entry_source_removed (fib_entry_t *fib_entry, bsrc = fib_entry_get_best_src_i(fib_entry); best_source = fib_entry_src_get_source(bsrc); - if (FIB_SOURCE_MAX == best_source) + if (FIB_SOURCE_INVALID == best_source) { /* * no more sources left. this entry is toast. @@ -1040,16 +1030,16 @@ fib_entry_path_remove (fib_node_index_t fib_entry_index, * then we need to create a new one. else we are updating * an existing. */ - if (source < best_source) + switch (fib_source_cmp(source, best_source)) { + case FIB_SOURCE_CMP_BETTER: /* * Que! removing a path from a source that is better than the * one this entry is using. */ ASSERT(0); - } - else if (source > best_source ) - { + break; + case FIB_SOURCE_CMP_WORSE: /* * the source is not the best. no need to update forwarding */ @@ -1067,10 +1057,9 @@ fib_entry_path_remove (fib_node_index_t fib_entry_index, * that remain are non-inherited */ return (fib_entry_src_burn_only_inherited(fib_entry)); - } - } - else - { + } + break; + case FIB_SOURCE_CMP_EQUAL: /* * removing a path from the path-list we were using. */ @@ -1089,6 +1078,7 @@ fib_entry_path_remove (fib_node_index_t fib_entry_index, */ fib_entry_src_action_reactivate(fib_entry, source); } + break; } fib_entry_post_update_actions(fib_entry, source, bflags); @@ -1131,16 +1121,17 @@ fib_entry_special_remove (fib_node_index_t fib_entry_index, * then we need to create a new one. else we are updating * an existing. */ - if (source < best_source ) + switch (fib_source_cmp(source, best_source)) { + case FIB_SOURCE_CMP_BETTER: /* * Que! removing a path from a source that is better than the * one this entry is using. This can only mean it is a source * this prefix does not have. */ return (FIB_ENTRY_SRC_FLAG_ADDED); - } - else if (source > best_source ) { + + case FIB_SOURCE_CMP_WORSE: /* * the source is not the best. no need to update forwarding */ @@ -1174,9 +1165,9 @@ fib_entry_special_remove (fib_node_index_t fib_entry_index, return (FIB_ENTRY_SRC_FLAG_ADDED); } - } - else - { + break; + + case FIB_SOURCE_CMP_EQUAL: if (!(FIB_ENTRY_SRC_FLAG_ADDED & sflag)) { /* @@ -1191,6 +1182,7 @@ fib_entry_special_remove (fib_node_index_t fib_entry_index, */ fib_entry_src_action_reactivate(fib_entry, source); } + break; } fib_entry_post_update_actions(fib_entry, source, bflags); diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h index f0e6e8d8aae..b97c80fd8bf 100644 --- a/src/vnet/fib/fib_entry.h +++ b/src/vnet/fib/fib_entry.h @@ -17,6 +17,7 @@ #define __FIB_ENTRY_H__ #include <vnet/fib/fib_node.h> +#include <vnet/fib/fib_source.h> #include <vnet/adj/adj.h> #include <vnet/ip/ip.h> #include <vnet/dpo/dpo.h> @@ -26,176 +27,6 @@ * The sources are defined here with their relative priority order. * The lower the value the higher the priority */ -typedef enum fib_source_t_ { - /** - * An invalid source - * This is not a real source, so don't use it to source a prefix. - * It exists here to provide a value for inexistant/uninitialized source - */ - FIB_SOURCE_INVALID = 0, - /** - * Marker. Add new values after this one. - */ - FIB_SOURCE_FIRST, - /** - * Special sources. These are for entries that are added to all - * FIBs by default, and should never be over-ridden (hence they - * are the highest priority) - */ - FIB_SOURCE_SPECIAL = FIB_SOURCE_FIRST, - /** - * Classify. A route that links directly to a classify adj - */ - FIB_SOURCE_CLASSIFY, - /** - * A route the is being 'proxied' on behalf of another device - */ - FIB_SOURCE_PROXY, - /** - * Route added as a result of interface configuration. - * this will also come from the API/CLI, but the distinction is - * that is from confiiguration on an interface, not a 'ip route' command - */ - FIB_SOURCE_INTERFACE, - /** - * SRv6 and SR-MPLS - */ - FIB_SOURCE_SR, - /** - * A high priority source a plugin can use - */ - FIB_SOURCE_PLUGIN_HI, - /** - * From the BIER subsystem - */ - FIB_SOURCE_BIER, - /** - * From 6RD. - */ - FIB_SOURCE_6RD, - /** - * From the control plane API - */ - FIB_SOURCE_API, - /** - * From the CLI. - */ - FIB_SOURCE_CLI, - /** - * A low (below routing) priority source a plugin can use - */ - FIB_SOURCE_PLUGIN_LOW, - /** - * LISP - */ - FIB_SOURCE_LISP, - /** - * IPv[46] Mapping - */ - FIB_SOURCE_MAP, - /** - * DHCP - */ - FIB_SOURCE_DHCP, - /** - * IPv6 Proxy ND - */ - FIB_SOURCE_IP6_ND_PROXY, - /** - * IPv6 ND (seen in the link-local tables) - */ - FIB_SOURCE_IP6_ND, - /** - * Adjacency source. - * routes created as a result of ARP/ND entries. This is lower priority - * then the API/CLI. This is on purpose. trust me. - */ - FIB_SOURCE_ADJ, - /** - * MPLS label. The prefix has been assigned a local label. This source - * never provides forwarding information, instead it acts as a place-holder - * so the association of label to prefix can be maintained - */ - FIB_SOURCE_MPLS, - /** - * Attached Export source. - * routes created as a result of attahced export. routes thus sourced - * will be present in the export tables - */ - FIB_SOURCE_AE, - /** - * Recursive resolution source. - * Used to install an entry that is the resolution traget of another. - */ - FIB_SOURCE_RR, - /** - * uRPF bypass/exemption. - * Used to install an entry that is exempt from the loose uRPF check - */ - FIB_SOURCE_URPF_EXEMPT, - /** - * The default route source. - * The default route is always added to the FIB table (like the - * special sources) but we need to be able to over-ride it with - * 'ip route' sources when provided - */ - FIB_SOURCE_DEFAULT_ROUTE, - /** - * The interpose source. - * This is not a real source, so don't use it to source a prefix. - * It exists here to provide a value against which to register to the - * VFT for providing the interpose actions to a real source. - */ - FIB_SOURCE_INTERPOSE, - /** - * Marker. add new entries before this one. - */ - FIB_SOURCE_LAST = FIB_SOURCE_INTERPOSE, -} __attribute__ ((packed)) fib_source_t; - -STATIC_ASSERT (sizeof(fib_source_t) == 1, - "FIB too many sources"); - -/** - * The maximum number of sources - */ -#define FIB_SOURCE_MAX (FIB_SOURCE_LAST+1) - -#define FIB_SOURCES { \ - [FIB_SOURCE_INVALID] = "invalid", \ - [FIB_SOURCE_SPECIAL] = "special", \ - [FIB_SOURCE_INTERFACE] = "interface", \ - [FIB_SOURCE_PROXY] = "proxy", \ - [FIB_SOURCE_BIER] = "BIER", \ - [FIB_SOURCE_6RD] = "6RD", \ - [FIB_SOURCE_API] = "API", \ - [FIB_SOURCE_CLI] = "CLI", \ - [FIB_SOURCE_ADJ] = "adjacency", \ - [FIB_SOURCE_MAP] = "MAP", \ - [FIB_SOURCE_SR] = "SR", \ - [FIB_SOURCE_LISP] = "LISP", \ - [FIB_SOURCE_CLASSIFY] = "classify", \ - [FIB_SOURCE_DHCP] = "DHCP", \ - [FIB_SOURCE_IP6_ND_PROXY] = "IPv6-proxy-nd", \ - [FIB_SOURCE_IP6_ND] = "IPv6-nd", \ - [FIB_SOURCE_RR] = "recursive-resolution", \ - [FIB_SOURCE_AE] = "attached_export", \ - [FIB_SOURCE_MPLS] = "mpls", \ - [FIB_SOURCE_URPF_EXEMPT] = "urpf-exempt", \ - [FIB_SOURCE_DEFAULT_ROUTE] = "default-route", \ - [FIB_SOURCE_PLUGIN_HI] = "plugin-hi", \ - [FIB_SOURCE_PLUGIN_LOW] = "plugin-low", \ - [FIB_SOURCE_INTERPOSE] = "interpose", \ -} - -#define FOR_EACH_FIB_SOURCE(_item) \ - for (_item = FIB_SOURCE_FIRST; _item < FIB_SOURCE_MAX; _item++) - -/** - * The different sources that can create a route. - * The sources are defined here with their relative priority order. - * The lower the value the higher the priority - */ typedef enum fib_entry_attribute_t_ { /** * Marker. Add new values after this one. diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index 176818abc0a..d534135d330 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -28,7 +28,7 @@ /* * per-source type vft */ -static fib_entry_src_vft_t fib_entry_src_vft[FIB_SOURCE_MAX]; +static fib_entry_src_vft_t fib_entry_src_bh_vft[FIB_SOURCE_BH_MAX]; /** * Get the VFT for a given source. This is a combination of the source @@ -37,12 +37,16 @@ static fib_entry_src_vft_t fib_entry_src_vft[FIB_SOURCE_MAX]; const fib_entry_src_vft_t* fib_entry_src_get_vft (const fib_entry_src_t *esrc) { + fib_source_behaviour_t bh; + + bh = fib_source_get_behaviour(esrc->fes_src); + if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_INTERPOSE) { - return (&fib_entry_src_vft[FIB_SOURCE_INTERPOSE]); + return (&fib_entry_src_bh_vft[FIB_SOURCE_BH_INTERPOSE]); } - return (&fib_entry_src_vft[esrc->fes_src]); + return (&fib_entry_src_bh_vft[bh]); } static void @@ -54,14 +58,14 @@ fib_entry_src_copy_default (const fib_entry_src_t *orig_src, } void -fib_entry_src_register (fib_source_t source, - const fib_entry_src_vft_t *vft) +fib_entry_src_behaviour_register (fib_source_behaviour_t bh, + const fib_entry_src_vft_t *vft) { - fib_entry_src_vft[source] = *vft; + fib_entry_src_bh_vft[bh] = *vft; - if (NULL == fib_entry_src_vft[source].fesv_copy) + if (NULL == fib_entry_src_bh_vft[bh].fesv_copy) { - fib_entry_src_vft[source].fesv_copy = fib_entry_src_copy_default; + fib_entry_src_bh_vft[bh].fesv_copy = fib_entry_src_copy_default; } } @@ -71,7 +75,8 @@ fib_entry_src_cmp_for_sort (void * v1, { fib_entry_src_t *esrc1 = v1, *esrc2 = v2; - return (esrc1->fes_src - esrc2->fes_src); + return (fib_source_get_prio(esrc1->fes_src) - + fib_source_get_prio(esrc2->fes_src)); } static void @@ -1925,8 +1930,8 @@ fib_entry_src_module_init (void) fib_entry_src_rr_register(); fib_entry_src_interface_register(); fib_entry_src_interpose_register(); - fib_entry_src_default_route_register(); - fib_entry_src_special_register(); + fib_entry_src_drop_register(); + fib_entry_src_simple_register(); fib_entry_src_api_register(); fib_entry_src_adj_register(); fib_entry_src_mpls_register(); diff --git a/src/vnet/fib/fib_entry_src.h b/src/vnet/fib/fib_entry_src.h index 8f13ae894bb..308005777a0 100644 --- a/src/vnet/fib/fib_entry_src.h +++ b/src/vnet/fib/fib_entry_src.h @@ -260,8 +260,8 @@ extern u8* fib_entry_src_format(fib_entry_t *entry, fib_source_t source, u8* s); -extern void fib_entry_src_register(fib_source_t source, - const fib_entry_src_vft_t *vft); +extern void fib_entry_src_behaviour_register (fib_source_behaviour_t source, + const fib_entry_src_vft_t *vft); extern fib_entry_src_cover_res_t fib_entry_src_action_cover_change( fib_entry_t *entry, @@ -348,8 +348,8 @@ extern void fib_entry_src_default_register(void); extern void fib_entry_src_rr_register(void); extern void fib_entry_src_interface_register(void); extern void fib_entry_src_interpose_register(void); -extern void fib_entry_src_default_route_register(void); -extern void fib_entry_src_special_register(void); +extern void fib_entry_src_drop_register(void); +extern void fib_entry_src_simple_register(void); extern void fib_entry_src_api_register(void); extern void fib_entry_src_adj_register(void); extern void fib_entry_src_mpls_register(void); diff --git a/src/vnet/fib/fib_entry_src_adj.c b/src/vnet/fib/fib_entry_src_adj.c index 2a5b46a2c91..ec80a867d49 100644 --- a/src/vnet/fib/fib_entry_src_adj.c +++ b/src/vnet/fib/fib_entry_src_adj.c @@ -411,5 +411,5 @@ const static fib_entry_src_vft_t adj_src_vft = { void fib_entry_src_adj_register (void) { - fib_entry_src_register(FIB_SOURCE_ADJ, &adj_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_ADJ, &adj_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_api.c b/src/vnet/fib/fib_entry_src_api.c index be93cc23c36..69102a15030 100644 --- a/src/vnet/fib/fib_entry_src_api.c +++ b/src/vnet/fib/fib_entry_src_api.c @@ -162,13 +162,5 @@ const static fib_entry_src_vft_t api_src_vft = { void fib_entry_src_api_register (void) { - fib_entry_src_register(FIB_SOURCE_PLUGIN_HI, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_PLUGIN_LOW, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_API, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_CLI, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_6RD, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_DHCP, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_IP6_ND_PROXY, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_IP6_ND, &api_src_vft); - fib_entry_src_register(FIB_SOURCE_SR, &api_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_API, &api_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_default.c b/src/vnet/fib/fib_entry_src_default.c index 18a039afbd6..534a28ca6f8 100644 --- a/src/vnet/fib/fib_entry_src_default.c +++ b/src/vnet/fib/fib_entry_src_default.c @@ -113,9 +113,6 @@ const static fib_entry_src_vft_t default_src_vft = { void fib_entry_src_default_register (void) { - fib_source_t source; - - FOR_EACH_FIB_SOURCE(source) { - fib_entry_src_register(source, &default_src_vft); - } + fib_entry_src_behaviour_register (FIB_SOURCE_BH_DROP, + &default_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_default_route.c b/src/vnet/fib/fib_entry_src_drop.c index 431abb66d17..886977100f4 100644 --- a/src/vnet/fib/fib_entry_src_default_route.c +++ b/src/vnet/fib/fib_entry_src_drop.c @@ -20,19 +20,19 @@ * Source initialisation Function */ static void -fib_entry_src_default_route_init (fib_entry_src_t *src) +fib_entry_src_drop_init (fib_entry_src_t *src) { src->fes_flags = FIB_ENTRY_SRC_FLAG_NONE; } static void -fib_entry_src_default_route_remove (fib_entry_src_t *src) +fib_entry_src_drop_remove (fib_entry_src_t *src) { src->fes_pl = FIB_NODE_INDEX_INVALID; } static void -fib_entry_src_default_route_add (fib_entry_src_t *src, +fib_entry_src_drop_add (fib_entry_src_t *src, const fib_entry_t *entry, fib_entry_flag_t flags, dpo_proto_t proto, @@ -43,16 +43,17 @@ fib_entry_src_default_route_add (fib_entry_src_t *src, dpo); } -const static fib_entry_src_vft_t interface_src_vft = { - .fesv_init = fib_entry_src_default_route_init, - .fesv_add = fib_entry_src_default_route_add, - .fesv_remove = fib_entry_src_default_route_remove, +const static fib_entry_src_vft_t drop_src_vft = { + .fesv_init = fib_entry_src_drop_init, + .fesv_add = fib_entry_src_drop_add, + .fesv_remove = fib_entry_src_drop_remove, }; void -fib_entry_src_default_route_register (void) +fib_entry_src_drop_register (void) { - fib_entry_src_register(FIB_SOURCE_DEFAULT_ROUTE, &interface_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_DROP, + &drop_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_interface.c b/src/vnet/fib/fib_entry_src_interface.c index 5d609c5857a..140036012b9 100644 --- a/src/vnet/fib/fib_entry_src_interface.c +++ b/src/vnet/fib/fib_entry_src_interface.c @@ -213,5 +213,6 @@ const static fib_entry_src_vft_t interface_src_vft = { void fib_entry_src_interface_register (void) { - fib_entry_src_register(FIB_SOURCE_INTERFACE, &interface_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_INTERFACE, + &interface_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_interpose.c b/src/vnet/fib/fib_entry_src_interpose.c index 2220fa4debd..02db3911dfc 100644 --- a/src/vnet/fib/fib_entry_src_interpose.c +++ b/src/vnet/fib/fib_entry_src_interpose.c @@ -61,17 +61,17 @@ fib_entry_src_rr_get_next_best (const fib_entry_src_t *src, /* * skip to the next best source after this one */ - if (source <= src->fes_src) + switch (fib_source_cmp(source, src->fes_src)) { + case FIB_SOURCE_CMP_BETTER: + case FIB_SOURCE_CMP_EQUAL: continue; - } - else - { + case FIB_SOURCE_CMP_WORSE: best_src = next_src; - break; + goto out; } })); - + out: return (best_src); } @@ -366,5 +366,6 @@ const static fib_entry_src_vft_t interpose_src_vft = { void fib_entry_src_interpose_register (void) { - fib_entry_src_register(FIB_SOURCE_INTERPOSE, &interpose_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_INTERPOSE, + &interpose_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_lisp.c b/src/vnet/fib/fib_entry_src_lisp.c index ec8c467d1cf..2fc9c924e6b 100644 --- a/src/vnet/fib/fib_entry_src_lisp.c +++ b/src/vnet/fib/fib_entry_src_lisp.c @@ -114,7 +114,7 @@ fib_entry_src_lisp_get_data (fib_entry_src_t *src, return (&(src->u.lisp.fesl_fib_index)); } -const static fib_entry_src_vft_t api_src_vft = { +const static fib_entry_src_vft_t lisp_src_vft = { .fesv_init = fib_entry_src_lisp_init, .fesv_deinit = fib_entry_src_lisp_deinit, .fesv_add = fib_entry_src_lisp_add, @@ -129,5 +129,6 @@ const static fib_entry_src_vft_t api_src_vft = { void fib_entry_src_lisp_register (void) { - fib_entry_src_register(FIB_SOURCE_LISP, &api_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_LISP, + &lisp_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_mpls.c b/src/vnet/fib/fib_entry_src_mpls.c index f3d1dc0bd50..7bbe34d0566 100644 --- a/src/vnet/fib/fib_entry_src_mpls.c +++ b/src/vnet/fib/fib_entry_src_mpls.c @@ -193,5 +193,5 @@ const static fib_entry_src_vft_t mpls_src_vft = { void fib_entry_src_mpls_register (void) { - fib_entry_src_register(FIB_SOURCE_MPLS, &mpls_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_MPLS, &mpls_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_rr.c b/src/vnet/fib/fib_entry_src_rr.c index 9f4f68d88f5..d0256b9f24b 100755 --- a/src/vnet/fib/fib_entry_src_rr.c +++ b/src/vnet/fib/fib_entry_src_rr.c @@ -306,6 +306,5 @@ const static fib_entry_src_vft_t rr_src_vft = { void fib_entry_src_rr_register (void) { - fib_entry_src_register(FIB_SOURCE_RR, &rr_src_vft); - fib_entry_src_register(FIB_SOURCE_URPF_EXEMPT, &rr_src_vft); + fib_entry_src_behaviour_register(FIB_SOURCE_BH_RR, &rr_src_vft); } diff --git a/src/vnet/fib/fib_entry_src_simple.c b/src/vnet/fib/fib_entry_src_simple.c new file mode 100644 index 00000000000..2caa4fcc1e1 --- /dev/null +++ b/src/vnet/fib/fib_entry_src_simple.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fib_entry.h" +#include "fib_entry_src.h" + +/** + * Source initialisation Function + */ +static void +fib_entry_src_simple_init (fib_entry_src_t *src) +{ + src->fes_flags = FIB_ENTRY_SRC_FLAG_NONE; +} + +/** + * Source deinitialisation Function + */ +static void +fib_entry_src_simple_deinit (fib_entry_src_t *src) +{ +} + +static void +fib_entry_src_simple_remove (fib_entry_src_t *src) +{ + src->fes_pl = FIB_NODE_INDEX_INVALID; +} + +static void +fib_entry_src_simple_add (fib_entry_src_t *src, + const fib_entry_t *entry, + fib_entry_flag_t flags, + dpo_proto_t proto, + const dpo_id_t *dpo) +{ + src->fes_pl = + fib_path_list_create_special(proto, + fib_entry_src_flags_2_path_list_flags(flags), + dpo); +} + +static void +fib_entry_src_simple_path_swap (fib_entry_src_t *src, + const fib_entry_t *entry, + fib_path_list_flags_t pl_flags, + const fib_route_path_t *rpaths) +{ + src->fes_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | pl_flags), + rpaths); +} + +const static fib_entry_src_vft_t simple_src_vft = { + .fesv_init = fib_entry_src_simple_init, + .fesv_deinit = fib_entry_src_simple_deinit, + .fesv_add = fib_entry_src_simple_add, + .fesv_remove = fib_entry_src_simple_remove, + .fesv_path_swap = fib_entry_src_simple_path_swap, +}; + +void +fib_entry_src_simple_register (void) +{ + fib_entry_src_behaviour_register(FIB_SOURCE_BH_SIMPLE, &simple_src_vft); +} diff --git a/src/vnet/fib/fib_entry_src_special.c b/src/vnet/fib/fib_entry_src_special.c deleted file mode 100644 index c976da9327a..00000000000 --- a/src/vnet/fib/fib_entry_src_special.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "fib_entry.h" -#include "fib_entry_src.h" - -/** - * Source initialisation Function - */ -static void -fib_entry_src_special_init (fib_entry_src_t *src) -{ - src->fes_flags = FIB_ENTRY_SRC_FLAG_NONE; -} - -/** - * Source deinitialisation Function - */ -static void -fib_entry_src_special_deinit (fib_entry_src_t *src) -{ -} - -static void -fib_entry_src_special_remove (fib_entry_src_t *src) -{ - src->fes_pl = FIB_NODE_INDEX_INVALID; -} - -static void -fib_entry_src_special_add (fib_entry_src_t *src, - const fib_entry_t *entry, - fib_entry_flag_t flags, - dpo_proto_t proto, - const dpo_id_t *dpo) -{ - src->fes_pl = - fib_path_list_create_special(proto, - fib_entry_src_flags_2_path_list_flags(flags), - dpo); -} - -static void -fib_entry_src_special_path_swap (fib_entry_src_t *src, - const fib_entry_t *entry, - fib_path_list_flags_t pl_flags, - const fib_route_path_t *rpaths) -{ - src->fes_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | pl_flags), - rpaths); -} - -const static fib_entry_src_vft_t special_src_vft = { - .fesv_init = fib_entry_src_special_init, - .fesv_deinit = fib_entry_src_special_deinit, - .fesv_add = fib_entry_src_special_add, - .fesv_remove = fib_entry_src_special_remove, - .fesv_path_swap = fib_entry_src_special_path_swap, -}; - -void -fib_entry_src_special_register (void) -{ - fib_entry_src_register(FIB_SOURCE_SPECIAL, &special_src_vft); - fib_entry_src_register(FIB_SOURCE_MAP, &special_src_vft); - fib_entry_src_register(FIB_SOURCE_CLASSIFY, &special_src_vft); - fib_entry_src_register(FIB_SOURCE_AE, &special_src_vft); - fib_entry_src_register(FIB_SOURCE_PROXY, &special_src_vft); - fib_entry_src_register(FIB_SOURCE_BIER, &special_src_vft); -} diff --git a/src/vnet/fib/fib_source.c b/src/vnet/fib/fib_source.c new file mode 100644 index 00000000000..0aeecae545f --- /dev/null +++ b/src/vnet/fib/fib_source.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <vnet/fib/fib_source.h> + +static const char *fib_source_names[] = FIB_SOURCES; +static const char *fib_source_behaviour_names[] = FIB_SOURCE_BEHAVIOURS; + +static fib_source_t fib_source_id = FIB_SOURCE_LAST+1; + +typedef struct fib_source_prio_t_ +{ + fib_source_priority_t fsp_class; + fib_source_priority_t fsp_slot; +} fib_source_prio_t; + +/** + * for each client requested priority count the number pf uses of + * that prio so we can asign is usage a slot number, and therefore + * each request will have a unique value. + */ +STATIC_ASSERT_SIZEOF(fib_source_priority_t, 1); +static fib_source_priority_t fib_source_prio_by_class[0x100]; + +typedef struct fib_source_reg_t_ +{ + fib_source_t fsr_source; + const char *fsr_name; + fib_source_behaviour_t fsr_behaviour; + fib_source_prio_t fsr_prio; +} fib_source_reg_t; + +static fib_source_reg_t *fib_source_regs; + + +u16 +fib_source_get_prio (fib_source_t src) +{ + ASSERT(vec_len(fib_source_regs) > src); + + return (((u16)fib_source_regs[src].fsr_prio.fsp_class << 8) | + fib_source_regs[src].fsr_prio.fsp_slot); +} + +fib_source_behaviour_t +fib_source_get_behaviour (fib_source_t src) +{ + ASSERT(vec_len(fib_source_regs) > src); + + return (fib_source_regs[src].fsr_behaviour); +} + +u8 * +format_fib_source (u8 *s, va_list *a) +{ + fib_source_t src = va_arg(*a, int); + + ASSERT(vec_len(fib_source_regs) > src); + + return (format(s, "%s", fib_source_regs[src].fsr_name)); +} + +fib_source_priority_cmp_t +fib_source_cmp (fib_source_t s1, + fib_source_t s2) +{ + if (fib_source_get_prio(s1) < + fib_source_get_prio(s2)) + { + return (FIB_SOURCE_CMP_BETTER); + } + else if (fib_source_get_prio(s1) > + fib_source_get_prio(s2)) + { + return (FIB_SOURCE_CMP_WORSE); + } + return (FIB_SOURCE_CMP_EQUAL); +} + +static void +fib_source_reg_init (fib_source_t src, + const char *name, + fib_source_priority_t prio, + fib_source_behaviour_t bh) +{ + fib_source_priority_t slot; + fib_source_reg_t *fsr; + + /* + * ensure we assign a unique priority to each request + * otherwise different source will be treated like ECMP + */ + slot = fib_source_prio_by_class[prio]++; + + vec_validate(fib_source_regs, src); + + fsr = &fib_source_regs[src]; + fsr->fsr_source = src; + fsr->fsr_name = strdup(name); + fsr->fsr_prio.fsp_class = prio; + fsr->fsr_prio.fsp_slot = slot; + fsr->fsr_behaviour = bh; +} + +fib_source_t +fib_source_allocate (const char *name, + fib_source_priority_t prio, + fib_source_behaviour_t bh) +{ + fib_source_t src; + + // max value range + ASSERT(fib_source_id < 255); + if (fib_source_id == 255) + return (FIB_SOURCE_INVALID); + + src = fib_source_id++; + + fib_source_reg_init(src, name, prio, bh); + + return (src); +} + +void +fib_source_register (fib_source_t src, + fib_source_priority_t prio, + fib_source_behaviour_t bh) +{ + fib_source_reg_init(src, fib_source_names[src], prio, bh); +} + +static u8 * +format_fib_source_reg (u8 *s, va_list *a) +{ + fib_source_reg_t *fsr = va_arg(*a, fib_source_reg_t*); + + s = format(s, "[%d] %U prio:%d.%d behaviour:%s", + fsr->fsr_source, + format_fib_source, fsr->fsr_source, + fsr->fsr_prio.fsp_class, fsr->fsr_prio.fsp_slot, + fib_source_behaviour_names[fsr->fsr_behaviour]); + + return (s); +} + +static int +fib_source_reg_cmp_for_sort (void * v1, + void * v2) +{ + fib_source_reg_t *fsr1 = v1, *fsr2 = v2; + + return (fib_source_get_prio(fsr1->fsr_source) - + fib_source_get_prio(fsr2->fsr_source)); +} + +void +fib_source_walk (fib_source_walk_t fn, + void *ctx) +{ + fib_source_reg_t *fsr; + + vec_foreach(fsr, fib_source_regs) + { + if (WALK_STOP == fn(fsr->fsr_source, + fsr->fsr_name, + fsr->fsr_prio.fsp_class, + fsr->fsr_behaviour, + ctx)) + break; + } +} + +static clib_error_t * +fib_source_show (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + fib_source_reg_t *fsr, *fsrs; + + fsrs = vec_dup(fib_source_regs); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "prio") || + unformat (input, "priority")) + vec_sort_with_function(fsrs, fib_source_reg_cmp_for_sort); + } + vec_foreach(fsr, fsrs) + { + vlib_cli_output(vm, "%U", format_fib_source_reg, fsr); + } + vec_free(fsrs); + + return (NULL); +} + +VLIB_CLI_COMMAND (show_fib_sources, static) = { + .path = "show fib source", + .function = fib_source_show, + .short_help = "show fib source [prio]", +}; + + +void +fib_source_module_init (void) +{ +#define _(s,p,b) fib_source_register(s,p,b); + foreach_fib_source +#undef _ +} diff --git a/src/vnet/fib/fib_source.h b/src/vnet/fib/fib_source.h new file mode 100644 index 00000000000..198ef194e2b --- /dev/null +++ b/src/vnet/fib/fib_source.h @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FIB_SOURCE_H__ +#define __FIB_SOURCE_H__ + +#include <vnet/vnet.h> + +/** + * The different sources that can create a route. + * The sources are defined here with their relative priority order. + * The lower the value the higher the priority + */ +typedef enum fib_source_t_ { + /** + * An invalid source + * This is not a real source, so don't use it to source a prefix. + * It exists here to provide a value for inexistant/uninitialized source + */ + FIB_SOURCE_INVALID = 0, + /** + * Marker. Add new values after this one. + */ + FIB_SOURCE_FIRST, + /** + * Special sources. These are for entries that are added to all + * FIBs by default, and should never be over-ridden (hence they + * are the highest priority) + */ + FIB_SOURCE_SPECIAL = FIB_SOURCE_FIRST, + /** + * Classify. A route that links directly to a classify adj + */ + FIB_SOURCE_CLASSIFY, + /** + * A route the is being 'proxied' on behalf of another device + */ + FIB_SOURCE_PROXY, + /** + * Route added as a result of interface configuration. + * this will also come from the API/CLI, but the distinction is + * that is from confiiguration on an interface, not a 'ip route' command + */ + FIB_SOURCE_INTERFACE, + /** + * SRv6 and SR-MPLS + */ + FIB_SOURCE_SR, + /** + * From the BIER subsystem + */ + FIB_SOURCE_BIER, + /** + * From 6RD. + */ + FIB_SOURCE_6RD, + /** + * From the control plane API + */ + FIB_SOURCE_API, + /** + * From the CLI. + */ + FIB_SOURCE_CLI, + /** + * LISP + */ + FIB_SOURCE_LISP, + /** + * IPv[46] Mapping + */ + FIB_SOURCE_MAP, + /** + * DHCP + */ + FIB_SOURCE_DHCP, + /** + * IPv6 Proxy ND + */ + FIB_SOURCE_IP6_ND_PROXY, + /** + * IPv6 ND (seen in the link-local tables) + */ + FIB_SOURCE_IP6_ND, + /** + * Adjacency source. + * routes created as a result of ARP/ND entries. This is lower priority + * then the API/CLI. This is on purpose. trust me. + */ + FIB_SOURCE_ADJ, + /** + * MPLS label. The prefix has been assigned a local label. This source + * never provides forwarding information, instead it acts as a place-holder + * so the association of label to prefix can be maintained + */ + FIB_SOURCE_MPLS, + /** + * Attached Export source. + * routes created as a result of attahced export. routes thus sourced + * will be present in the export tables + */ + FIB_SOURCE_AE, + /** + * Recursive resolution source. + * Used to install an entry that is the resolution traget of another. + */ + FIB_SOURCE_RR, + /** + * uRPF bypass/exemption. + * Used to install an entry that is exempt from the loose uRPF check + */ + FIB_SOURCE_URPF_EXEMPT, + /** + * The default route source. + * The default route is always added to the FIB table (like the + * special sources) but we need to be able to over-ride it with + * 'ip route' sources when provided + */ + FIB_SOURCE_DEFAULT_ROUTE, + /** + * The interpose source. + * This is not a real source, so don't use it to source a prefix. + * It exists here to provide a value against which to register to the + * VFT for providing the interpose actions to a real source. + */ + FIB_SOURCE_INTERPOSE, + /** + * Marker. add new entries before this one. + */ + FIB_SOURCE_LAST = FIB_SOURCE_INTERPOSE, +} __attribute__ ((packed)) fib_source_t; + +STATIC_ASSERT (sizeof(fib_source_t) == 1, + "FIB too many sources"); + +#define FIB_SOURCES { \ + [FIB_SOURCE_INVALID] = "invalid", \ + [FIB_SOURCE_SPECIAL] = "special", \ + [FIB_SOURCE_INTERFACE] = "interface", \ + [FIB_SOURCE_PROXY] = "proxy", \ + [FIB_SOURCE_BIER] = "BIER", \ + [FIB_SOURCE_6RD] = "6RD", \ + [FIB_SOURCE_API] = "API", \ + [FIB_SOURCE_CLI] = "CLI", \ + [FIB_SOURCE_ADJ] = "adjacency", \ + [FIB_SOURCE_MAP] = "MAP", \ + [FIB_SOURCE_SR] = "SR", \ + [FIB_SOURCE_LISP] = "LISP", \ + [FIB_SOURCE_CLASSIFY] = "classify", \ + [FIB_SOURCE_DHCP] = "DHCP", \ + [FIB_SOURCE_IP6_ND_PROXY] = "IPv6-proxy-nd", \ + [FIB_SOURCE_IP6_ND] = "IPv6-nd", \ + [FIB_SOURCE_RR] = "recursive-resolution", \ + [FIB_SOURCE_AE] = "attached_export", \ + [FIB_SOURCE_MPLS] = "mpls", \ + [FIB_SOURCE_URPF_EXEMPT] = "urpf-exempt", \ + [FIB_SOURCE_DEFAULT_ROUTE] = "default-route", \ + [FIB_SOURCE_INTERPOSE] = "interpose", \ +} + +/** + * Each source is assigned a priority. lower priority is beeter. + * the source with the best source with have its contribution added + * to forwarding. the lesser sources will be 'remembered' by FIB and + * added to forwarding should the best source be removed. + */ +typedef u8 fib_source_priority_t; + +/** + * source comparison + */ +typedef enum fib_source_priority_cmp_t_ +{ + FIB_SOURCE_CMP_BETTER, + FIB_SOURCE_CMP_WORSE, + FIB_SOURCE_CMP_EQUAL, +} fib_source_priority_cmp_t; + +/** + * Each source has a defined behaviour that controls how entries + * behave that have that source + */ +typedef enum fib_source_behaviour_t_ +{ + /** + * If your adding a new source from a plugin pick one of these + */ + /** Default behaviour - always install a drop */ + FIB_SOURCE_BH_DROP, + /** add paths with [mpls] path extensions */ + FIB_SOURCE_BH_API, + /** add paths without path extensions */ + FIB_SOURCE_BH_SIMPLE, + + /** + * If your adding a new source from a plugin + * these are probably not the behaviour you're lokking for. + */ + /** recursive resolution w/ cover tracking*/ + FIB_SOURCE_BH_RR, + /** associated label stored in private data */ + FIB_SOURCE_BH_MPLS, + /** cover tracking w/ glean management */ + FIB_SOURCE_BH_INTERFACE, + /** interpose */ + FIB_SOURCE_BH_INTERPOSE, + /** simple + source fib tracking */ + FIB_SOURCE_BH_LISP, + /** adj w/ cover tracking + refinement */ + FIB_SOURCE_BH_ADJ, +} fib_source_behaviour_t; + +#define FIB_SOURCE_BH_MAX (FIB_SOURCE_BH_ADJ+1) + +#define FIB_SOURCE_BEHAVIOURS { \ + [FIB_SOURCE_BH_DROP] = "drop", \ + [FIB_SOURCE_BH_RR] = "rr", \ + [FIB_SOURCE_BH_MPLS] = "mpls", \ + [FIB_SOURCE_BH_INTERFACE] = "interface", \ + [FIB_SOURCE_BH_INTERPOSE] = "interpose", \ + [FIB_SOURCE_BH_LISP] = "lisp", \ + [FIB_SOURCE_BH_ADJ] = "adjacency", \ + [FIB_SOURCE_BH_API] = "api", \ + [FIB_SOURCE_BH_SIMPLE] = "simple", \ +} + +/** + * The fixed source to priority mappings. + * Declared here so those adding new sources can better determine their respective + * priority values. + */ +#define foreach_fib_source \ + /** you can't do better then the special source */ \ + _(FIB_SOURCE_SPECIAL, 0x00, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_CLASSIFY, 0x01, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_PROXY, 0x02, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_INTERFACE, 0x03, FIB_SOURCE_BH_INTERFACE) \ + _(FIB_SOURCE_SR, 0x10, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_BIER, 0x20, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_6RD, 0x30, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_API, 0x80, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_CLI, 0x81, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_LISP, 0x90, FIB_SOURCE_BH_LISP) \ + _(FIB_SOURCE_MAP, 0xa0, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_DHCP, 0xb0, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_IP6_ND_PROXY, 0xc0, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_IP6_ND, 0xc1, FIB_SOURCE_BH_API) \ + _(FIB_SOURCE_ADJ, 0xd0, FIB_SOURCE_BH_ADJ) \ + _(FIB_SOURCE_MPLS, 0xe0, FIB_SOURCE_BH_MPLS) \ + _(FIB_SOURCE_AE, 0xf0, FIB_SOURCE_BH_SIMPLE) \ + _(FIB_SOURCE_RR, 0xfb, FIB_SOURCE_BH_RR) \ + _(FIB_SOURCE_URPF_EXEMPT, 0xfc, FIB_SOURCE_BH_RR) \ + _(FIB_SOURCE_DEFAULT_ROUTE, 0xfd, FIB_SOURCE_BH_DROP) \ + _(FIB_SOURCE_INTERPOSE, 0xfe, FIB_SOURCE_BH_INTERPOSE) \ + _(FIB_SOURCE_INVALID, 0xff, FIB_SOURCE_BH_DROP) + +/** + * Some priority values that plugins might use when they are not to concerned + * where in the list they'll go. + */ +#define FIB_SOURCE_PRIORITY_HI 0x10 +#define FIB_SOURCE_PRIORITY_LOW 0xd0 + + +extern u16 fib_source_get_prio(fib_source_t src); +extern fib_source_behaviour_t fib_source_get_behaviour(fib_source_t src); +extern fib_source_priority_cmp_t fib_source_cmp(fib_source_t s1, + fib_source_t s2); + +extern u8 *format_fib_source(u8 *s, va_list *a); + +extern fib_source_t fib_source_allocate(const char *name, + fib_source_priority_t prio, + fib_source_behaviour_t bh); + +extern void fib_source_register(fib_source_t src, + fib_source_priority_t prio, + fib_source_behaviour_t bh); + +typedef walk_rc_t (*fib_source_walk_t)(fib_source_t id, + const char *name, + fib_source_priority_t prio, + fib_source_behaviour_t bh, + void *ctx); +extern void fib_source_walk(fib_source_walk_t fn, + void *ctx); + +extern void fib_source_module_init(void); + +#endif diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c index d3cf5dc88b1..6766028762d 100644 --- a/src/vnet/fib/fib_table.c +++ b/src/vnet/fib/fib_table.c @@ -304,6 +304,21 @@ fib_table_fwding_dpo_remove (u32 fib_index, } } +static void +fib_table_source_count_inc (fib_table_t *fib_table, + fib_source_t source) +{ + vec_validate (fib_table->ft_src_route_counts, source); + fib_table->ft_src_route_counts[source]++; +} + +static void +fib_table_source_count_dec (fib_table_t *fib_table, + fib_source_t source) +{ + vec_validate (fib_table->ft_src_route_counts, source); + fib_table->ft_src_route_counts[source]--; +} fib_node_index_t fib_table_entry_special_dpo_add (u32 fib_index, @@ -325,7 +340,7 @@ fib_table_entry_special_dpo_add (u32 fib_index, dpo); fib_table_entry_insert(fib_table, prefix, fib_entry_index); - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } else { @@ -336,7 +351,7 @@ fib_table_entry_special_dpo_add (u32 fib_index, if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } } @@ -364,7 +379,7 @@ fib_table_entry_special_dpo_update (u32 fib_index, dpo); fib_table_entry_insert(fib_table, prefix, fib_entry_index); - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } else { @@ -379,7 +394,7 @@ fib_table_entry_special_dpo_update (u32 fib_index, if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } } @@ -461,7 +476,7 @@ fib_table_entry_special_remove (u32 fib_index, */ if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]--; + fib_table_source_count_dec(fib_table, source); } fib_entry_unlock(fib_entry_index); @@ -591,7 +606,7 @@ fib_table_entry_path_add2 (u32 fib_index, rpaths); fib_table_entry_insert(fib_table, prefix, fib_entry_index); - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } else { @@ -602,7 +617,7 @@ fib_table_entry_path_add2 (u32 fib_index, if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } } @@ -684,7 +699,7 @@ fib_table_entry_path_remove2 (u32 fib_index, */ if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]--; + fib_table_source_count_dec(fib_table, source); } fib_entry_unlock(fib_entry_index); @@ -763,7 +778,7 @@ fib_table_entry_update (u32 fib_index, paths); fib_table_entry_insert(fib_table, prefix, fib_entry_index); - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } else { @@ -774,7 +789,7 @@ fib_table_entry_update (u32 fib_index, if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]++; + fib_table_source_count_inc(fib_table, source); } } @@ -856,7 +871,7 @@ fib_table_entry_delete_i (u32 fib_index, */ if (was_sourced != fib_entry_is_sourced(fib_entry_index, source)) { - fib_table->ft_src_route_counts[source]--; + fib_table_source_count_dec(fib_table, source); } fib_entry_unlock(fib_entry_index); @@ -1246,6 +1261,27 @@ fib_table_sub_tree_walk (u32 fib_index, } } +static void +fib_table_lock_dec (fib_table_t *fib_table, + fib_source_t source) +{ + vec_validate(fib_table->ft_locks, source); + + fib_table->ft_locks[source]--; + fib_table->ft_total_locks--; +} + +static void +fib_table_lock_inc (fib_table_t *fib_table, + fib_source_t source) +{ + vec_validate(fib_table->ft_locks, source); + + ASSERT(fib_table->ft_locks[source] < (0xffff - 1)); + fib_table->ft_locks[source]++; + fib_table->ft_total_locks++; +} + void fib_table_unlock (u32 fib_index, fib_protocol_t proto, @@ -1254,10 +1290,9 @@ fib_table_unlock (u32 fib_index, fib_table_t *fib_table; fib_table = fib_table_get(fib_index, proto); - fib_table->ft_locks[source]--; - fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--; + fib_table_lock_dec(fib_table, source); - if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]) + if (0 == fib_table->ft_total_locks) { /* * no more locak from any source - kill it @@ -1275,10 +1310,7 @@ fib_table_lock (u32 fib_index, fib_table = fib_table_get(fib_index, proto); - ASSERT(fib_table->ft_locks[source] < (0xffff - 1)); - - fib_table->ft_locks[source]++; - fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++; + fib_table_lock_inc(fib_table, source); } u32 diff --git a/src/vnet/fib/fib_table.h b/src/vnet/fib/fib_table.h index 74be63d326a..59ebb0b0161 100644 --- a/src/vnet/fib/fib_table.h +++ b/src/vnet/fib/fib_table.h @@ -23,12 +23,6 @@ #include <vnet/mpls/packet.h> /** - * Keep a lock per-source and a total - */ -#define FIB_TABLE_N_LOCKS (FIB_SOURCE_MAX+1) -#define FIB_TABLE_TOTAL_LOCKS FIB_SOURCE_MAX - -/** * Flags for the source data */ typedef enum fib_table_attribute_t_ { @@ -89,7 +83,8 @@ typedef struct fib_table_t_ /** * per-source number of locks on the table */ - u16 ft_locks[FIB_TABLE_N_LOCKS]; + u16 *ft_locks; + u32 ft_total_locks; /** * Table ID (hash key) for this FIB. @@ -109,7 +104,7 @@ typedef struct fib_table_t_ /** * Per-source route counters */ - u32 ft_src_route_counts[FIB_SOURCE_MAX]; + u32 *ft_src_route_counts; /** * Total route counters diff --git a/src/vnet/fib/ip4_fib.c b/src/vnet/fib/ip4_fib.c index 02348af87d8..e4ff1bf77cc 100644 --- a/src/vnet/fib/ip4_fib.c +++ b/src/vnet/fib/ip4_fib.c @@ -160,6 +160,7 @@ ip4_fib_table_destroy (u32 fib_index) { fib_table_t *fib_table = pool_elt_at_index(ip4_main.fibs, fib_index); ip4_fib_t *v4_fib = pool_elt_at_index(ip4_main.v4_fibs, fib_index); + u32 *n_locks; int ii; /* @@ -182,9 +183,10 @@ ip4_fib_table_destroy (u32 fib_index) * validate no more routes. */ ASSERT(0 == fib_table->ft_total_route_counts); - FOR_EACH_FIB_SOURCE(ii) + + vec_foreach(n_locks, fib_table->ft_src_route_counts) { - ASSERT(0 == fib_table->ft_src_route_counts[ii]); + ASSERT(0 == *n_locks); } if (~0 != fib_table->ft_table_id) @@ -192,6 +194,7 @@ ip4_fib_table_destroy (u32 fib_index) hash_unset (ip4_main.fib_index_by_table_id, fib_table->ft_table_id); } + vec_free(fib_table->ft_src_route_counts); ip4_mtrie_free(&v4_fib->mtrie); pool_put(ip4_main.v4_fibs, v4_fib); @@ -679,7 +682,7 @@ ip4_show_fib (vlib_main_t * vm, fib_table->ft_flow_hash_config, fib_table->ft_epoch, format_fib_table_flags, fib_table->ft_flags); - FOR_EACH_FIB_SOURCE(source) + vec_foreach_index(source, fib_table->ft_locks) { if (0 != fib_table->ft_locks[source]) { diff --git a/src/vnet/fib/ip6_fib.c b/src/vnet/fib/ip6_fib.c index 991fbc1151b..6d0eca4c8d7 100644 --- a/src/vnet/fib/ip6_fib.c +++ b/src/vnet/fib/ip6_fib.c @@ -151,11 +151,11 @@ ip6_fib_table_destroy (u32 fib_index) fib_table_t *fib_table = fib_table_get(fib_index, FIB_PROTOCOL_IP6); fib_source_t source; - /* + /* * validate no more routes. */ ASSERT(0 == fib_table->ft_total_route_counts); - FOR_EACH_FIB_SOURCE(source) + vec_foreach_index(source, fib_table->ft_src_route_counts) { ASSERT(0 == fib_table->ft_src_route_counts[source]); } @@ -164,6 +164,7 @@ ip6_fib_table_destroy (u32 fib_index) { hash_unset (ip6_main.fib_index_by_table_id, fib_table->ft_table_id); } + vec_free(fib_table->ft_src_route_counts); pool_put_index(ip6_main.v6_fibs, fib_table->ft_index); pool_put(ip6_main.fibs, fib_table); } @@ -688,7 +689,7 @@ ip6_show_fib (vlib_main_t * vm, fib_table->ft_epoch, format_fib_table_flags, fib_table->ft_flags); - FOR_EACH_FIB_SOURCE(source) + vec_foreach_index(source, fib_table->ft_locks) { if (0 != fib_table->ft_locks[source]) { diff --git a/src/vnet/fib/mpls_fib.c b/src/vnet/fib/mpls_fib.c index 6f59eb3ee44..9ec32d2fea6 100644 --- a/src/vnet/fib/mpls_fib.c +++ b/src/vnet/fib/mpls_fib.c @@ -275,6 +275,7 @@ mpls_fib_table_destroy (u32 fib_index) } hash_free(mf->mf_entries); + vec_free(fib_table->ft_src_route_counts); pool_put(mpls_main.mpls_fibs, mf); pool_put(mpls_main.fibs, fib_table); } @@ -450,7 +451,7 @@ mpls_fib_show (vlib_main_t * vm, s = format (s, "%v, fib_index:%d locks:[", fib_table->ft_desc, mpls_main.fibs - fib_table); - FOR_EACH_FIB_SOURCE(source) + vec_foreach_index(source, fib_table->ft_locks) { if (0 != fib_table->ft_locks[source]) { diff --git a/src/vnet/ip/ip6_ll_table.c b/src/vnet/ip/ip6_ll_table.c index a7440ea543c..3672b635c87 100644 --- a/src/vnet/ip/ip6_ll_table.c +++ b/src/vnet/ip/ip6_ll_table.c @@ -283,7 +283,7 @@ ip6_ll_show_fib (vlib_main_t * vm, s = format (s, "%U, fib_index:%d, locks:[", format_fib_table_name, fib_index, FIB_PROTOCOL_IP6, fib_index); - FOR_EACH_FIB_SOURCE (source) + vec_foreach_index (source, fib_table->ft_locks) { if (0 != fib_table->ft_locks[source]) { |