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
diff --git a/src/vnet/fib/fib.c b/src/vnet/fib/fib.c
index 28e18dd..ddfa830 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 fd69db9..0e54828 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 @@
}
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 @@
{
return (esrc->fes_src);
}
- return (FIB_SOURCE_MAX);
+ return (FIB_SOURCE_INVALID);
}
static fib_entry_flag_t
@@ -836,16 +825,17 @@
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_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 @@
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 @@
* 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 @@
* 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_src_action_reactivate(fib_entry, source);
}
+ break;
}
fib_entry_post_update_actions(fib_entry, source, bflags);
@@ -1131,16 +1121,17 @@
* 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 @@
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_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 f0e6e8d..b97c80f 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 176818a..d534135 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 @@
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 @@
}
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_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_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 8f13ae8..3080057 100644
--- a/src/vnet/fib/fib_entry_src.h
+++ b/src/vnet/fib/fib_entry_src.h
@@ -260,8 +260,8 @@
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_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 2a5b46a..ec80a86 100644
--- a/src/vnet/fib/fib_entry_src_adj.c
+++ b/src/vnet/fib/fib_entry_src_adj.c
@@ -411,5 +411,5 @@
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 be93cc2..69102a1 100644
--- a/src/vnet/fib/fib_entry_src_api.c
+++ b/src/vnet/fib/fib_entry_src_api.c
@@ -162,13 +162,5 @@
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 18a039a..534a28c 100644
--- a/src/vnet/fib/fib_entry_src_default.c
+++ b/src/vnet/fib/fib_entry_src_default.c
@@ -113,9 +113,6 @@
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
similarity index 68%
rename from src/vnet/fib/fib_entry_src_default_route.c
rename to src/vnet/fib/fib_entry_src_drop.c
index 431abb6..8869771 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 @@
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 5d609c5..1400360 100644
--- a/src/vnet/fib/fib_entry_src_interface.c
+++ b/src/vnet/fib/fib_entry_src_interface.c
@@ -213,5 +213,6 @@
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 2220fa4..02db391 100644
--- a/src/vnet/fib/fib_entry_src_interpose.c
+++ b/src/vnet/fib/fib_entry_src_interpose.c
@@ -61,17 +61,17 @@
/*
* 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 @@
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 ec8c467..2fc9c92 100644
--- a/src/vnet/fib/fib_entry_src_lisp.c
+++ b/src/vnet/fib/fib_entry_src_lisp.c
@@ -114,7 +114,7 @@
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 @@
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 f3d1dc0..7bbe34d 100644
--- a/src/vnet/fib/fib_entry_src_mpls.c
+++ b/src/vnet/fib/fib_entry_src_mpls.c
@@ -193,5 +193,5 @@
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 9f4f68d..d0256b9 100755
--- a/src/vnet/fib/fib_entry_src_rr.c
+++ b/src/vnet/fib/fib_entry_src_rr.c
@@ -306,6 +306,5 @@
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 0000000..2caa4fc
--- /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 c976da9..0000000
--- 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 0000000..0aeecae
--- /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 0000000..198ef19
--- /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 d3cf5dc..6766028 100644
--- a/src/vnet/fib/fib_table.c
+++ b/src/vnet/fib/fib_table.c
@@ -304,6 +304,21 @@
}
}
+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 @@
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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
*/
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 @@
}
}
+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_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 = 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 74be63d..59ebb0b 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 @@
/**
* 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 @@
/**
* 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 02348af..e4ff1bf 100644
--- a/src/vnet/fib/ip4_fib.c
+++ b/src/vnet/fib/ip4_fib.c
@@ -160,6 +160,7 @@
{
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 @@
* 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 @@
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 @@
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 991fbc1..6d0eca4 100644
--- a/src/vnet/fib/ip6_fib.c
+++ b/src/vnet/fib/ip6_fib.c
@@ -151,11 +151,11 @@
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 @@
{
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 @@
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 6f59eb3..9ec32d2 100644
--- a/src/vnet/fib/mpls_fib.c
+++ b/src/vnet/fib/mpls_fib.c
@@ -275,6 +275,7 @@
}
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 @@
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])
{