#include <vnet/dpo/drop_dpo.h>
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/ip_null_dpo.h>
+#include <vnet/bfd/bfd_main.h>
#include <vnet/mpls/mpls.h>
#include <vnet/fib/fib_node_list.h>
#include <vnet/fib/fib_urpf_list.h>
+/*
+ * Add debugs for passing tests
+ */
+static int fib_test_do_debug;
+
#define FIB_TEST_I(_cond, _comment, _args...) \
({ \
int _evald = (_cond); \
fformat(stderr, "FAIL:%d: " _comment "\n", \
__LINE__, ##_args); \
} else { \
- fformat(stderr, "PASS:%d: " _comment "\n", \
- __LINE__, ##_args); \
+ if (fib_test_do_debug) \
+ fformat(stderr, "PASS:%d: " _comment "\n", \
+ __LINE__, ##_args); \
} \
_evald; \
})
/*
* at this stage there are 5 entries in the test FIB (plus 5 in the default),
* all of which are special sourced and so none of which share path-lists.
- * There are also 6 entries, and 6 non-shared path-lists, in the v6 default
- * table
+ * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
+ * table, and 4 path-lists in the v6 MFIB table
*/
-#define NBR (5+5+6)
+#define ENBR (5+5+2)
+#define PNBR (5+5+6)
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* +2 interface routes +2 non-shared path-lists
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* -1 shared-path-list
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* +2 adj-fibs, and their non-shared path-lists
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* +1 entry and a shared path-list
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/* 1.1.2.0/24 */
* +1 entry only
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* +1 shared-pathlist
*/
FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
fib_prefix_t bgp_101_pfx = {
*/
FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+14 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+9 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
*/
FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
*/
FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
fib_table_entry_delete(fib_index,
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
+ /*
+ * An adj-fib that fails the refinement criteria - no connected cover
+ */
+ fib_prefix_t pfx_12_10_10_2_s_32 = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ /* 12.10.10.2 */
+ .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
+ },
+ };
+
+ fib_table_entry_update_one_path(fib_index,
+ &pfx_12_10_10_2_s_32,
+ FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ FIB_PROTOCOL_IP4,
+ &pfx_12_10_10_2_s_32.fp_addr,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
+ dpo = fib_entry_contribute_ip_forwarding(fei);
+ FIB_TEST(!dpo_id_is_valid(dpo),
+ "no connected cover adj-fib fails refinement");
+
+ fib_table_entry_delete(fib_index,
+ &pfx_12_10_10_2_s_32,
+ FIB_SOURCE_ADJ);
+
+ /*
+ * An adj-fib that fails the refinement criteria - cover is connected
+ * but on a different interface
+ */
+ fib_prefix_t pfx_10_10_10_127_s_32 = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ /* 10.10.10.127 */
+ .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
+ },
+ };
+
+ fib_table_entry_update_one_path(fib_index,
+ &pfx_10_10_10_127_s_32,
+ FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ FIB_PROTOCOL_IP4,
+ &pfx_10_10_10_127_s_32.fp_addr,
+ tm->hw[1]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
+ dpo = fib_entry_contribute_ip_forwarding(fei);
+ FIB_TEST(!dpo_id_is_valid(dpo),
+ "wrong interface adj-fib fails refinement");
+
+ fib_table_entry_delete(fib_index,
+ &pfx_10_10_10_127_s_32,
+ FIB_SOURCE_ADJ);
+
/*
* CLEANUP
* remove adj-fibs:
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NBR-5 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
- FIB_TEST((NBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
+ FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
pool_elts(fib_urpf_list_pool));
return 0;
/*
* At this stage there is one v4 FIB with 5 routes and two v6 FIBs
- * each with 6 entries. All entries are special so no path-list sharing.
+ * each with 2 entries and a v6 mfib with 4 path-lists.
+ * All entries are special so no path-list sharing.
*/
-#define NPS (5+6+6)
+#define ENPS (5+4)
+#define PNPS (5+4+4)
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is %d",
+ FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
fib_path_list_pool_size());
- FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
* +2 entries. +2 unshared path-lists
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
- FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+4 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
*/
FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
*/
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
/*
FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
fib_path_list_db_size());
- FIB_TEST((NPS-6 == fib_path_list_pool_size()), "path list pool size is%d",
+ FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
fib_path_list_pool_size());
- FIB_TEST((NPS-6 == fib_entry_pool_size()), "entry pool size is %d",
+ FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
fib_entry_pool_size());
adj_unlock(ai_02);
&a_o_10_10_11_1,
&adj_o_10_10_11_2),
"1.1.1.1/32 LB 2 buckets via: "
- "adj over 10.10.11.1",
+ "adj over 10.10.11.1, "
"adj-v4 over 10.10.11.2");
fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
&a_o_10_10_11_1,
&adj_o_10_10_11_2),
"24001/eos LB 2 buckets via: "
- "adj over 10.10.11.1",
+ "adj over 10.10.11.1, "
"adj-v4 over 10.10.11.2");
fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
return (0);
}
+/*
+ * declaration of the otherwise static callback functions
+ */
+void fib_bfd_notify (bfd_listen_event_e event,
+ const bfd_session_t *session);
+void adj_bfd_notify (bfd_listen_event_e event,
+ const bfd_session_t *session);
+
+/**
+ * Test BFD session interaction with FIB
+ */
+static int
+fib_test_bfd (void)
+{
+ fib_node_index_t fei;
+ test_main_t *tm;
+ int n_feis;
+
+ /* via 10.10.10.1 */
+ ip46_address_t nh_10_10_10_1 = {
+ .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
+ };
+ /* via 10.10.10.2 */
+ ip46_address_t nh_10_10_10_2 = {
+ .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
+ };
+ /* via 10.10.10.10 */
+ ip46_address_t nh_10_10_10_10 = {
+ .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
+ };
+ n_feis = fib_entry_pool_size();
+
+ tm = &test_main;
+
+ /*
+ * add interface routes. we'll assume this works. it's tested elsewhere
+ */
+ fib_prefix_t pfx_10_10_10_10_s_24 = {
+ .fp_len = 24,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = nh_10_10_10_10,
+ };
+
+ fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
+ FIB_SOURCE_INTERFACE,
+ (FIB_ENTRY_FLAG_CONNECTED |
+ FIB_ENTRY_FLAG_ATTACHED),
+ FIB_PROTOCOL_IP4,
+ NULL,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1, // weight
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ fib_prefix_t pfx_10_10_10_10_s_32 = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = nh_10_10_10_10,
+ };
+ fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
+ FIB_SOURCE_INTERFACE,
+ (FIB_ENTRY_FLAG_CONNECTED |
+ FIB_ENTRY_FLAG_LOCAL),
+ FIB_PROTOCOL_IP4,
+ NULL,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1, // weight
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ /*
+ * A BFD session via a neighbour we do not yet know
+ */
+ bfd_session_t bfd_10_10_10_1 = {
+ .udp = {
+ .key = {
+ .fib_index = 0,
+ .peer_addr = nh_10_10_10_1,
+ },
+ },
+ .hop_type = BFD_HOP_TYPE_MULTI,
+ .local_state = BFD_STATE_init,
+ };
+
+ fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
+
+ /*
+ * A new entry will be created that forwards via the adj
+ */
+ adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
+ VNET_LINK_IP4,
+ &nh_10_10_10_1,
+ tm->hw[0]->sw_if_index);
+ fib_prefix_t pfx_10_10_10_1_s_32 = {
+ .fp_addr = nh_10_10_10_1,
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+ fib_test_lb_bucket_t adj_o_10_10_10_1 = {
+ .type = FT_LB_ADJ,
+ .adj = {
+ .adj = ai_10_10_10_1,
+ },
+ };
+
+ fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 1,
+ &adj_o_10_10_10_1),
+ "BFD sourced %U via %U",
+ format_fib_prefix, &pfx_10_10_10_1_s_32,
+ format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
+
+ /*
+ * Delete the BFD session. Expect the fib_entry to be removed
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
+
+ fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
+ FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
+ "BFD sourced %U removed",
+ format_fib_prefix, &pfx_10_10_10_1_s_32);
+
+ /*
+ * Add the BFD source back
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
+
+ /*
+ * source the entry via the ADJ fib
+ */
+ fei = fib_table_entry_update_one_path(0,
+ &pfx_10_10_10_1_s_32,
+ FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_1,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ /*
+ * Delete the BFD session. Expect the fib_entry to remain
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
+
+ fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 1,
+ &adj_o_10_10_10_1),
+ "BFD sourced %U remains via %U",
+ format_fib_prefix, &pfx_10_10_10_1_s_32,
+ format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
+
+ /*
+ * Add the BFD source back
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
+
+ /*
+ * Create another ADJ FIB
+ */
+ fib_prefix_t pfx_10_10_10_2_s_32 = {
+ .fp_addr = nh_10_10_10_2,
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+ fib_table_entry_update_one_path(0,
+ &pfx_10_10_10_2_s_32,
+ FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_2,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ /*
+ * A BFD session for the new ADJ FIB
+ */
+ bfd_session_t bfd_10_10_10_2 = {
+ .udp = {
+ .key = {
+ .fib_index = 0,
+ .peer_addr = nh_10_10_10_2,
+ },
+ },
+ .hop_type = BFD_HOP_TYPE_MULTI,
+ .local_state = BFD_STATE_init,
+ };
+
+ fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
+
+ /*
+ * remove the adj-fib source whilst the session is present
+ * then add it back
+ */
+ fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
+ fib_table_entry_update_one_path(0,
+ &pfx_10_10_10_2_s_32,
+ FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_2,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ /*
+ * Before adding a recursive via the BFD tracked ADJ-FIBs,
+ * bring one of the sessions UP, leave the other down
+ */
+ bfd_10_10_10_1.local_state = BFD_STATE_up;
+ fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
+ bfd_10_10_10_2.local_state = BFD_STATE_down;
+ fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
+
+ /*
+ * A recursive prefix via both of the ADJ FIBs
+ */
+ fib_prefix_t pfx_200_0_0_0_s_24 = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_len = 32,
+ .fp_addr = {
+ .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
+ },
+ };
+ const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
+
+ dpo_10_10_10_1 =
+ fib_entry_contribute_ip_forwarding(
+ fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
+ dpo_10_10_10_2 =
+ fib_entry_contribute_ip_forwarding(
+ fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
+
+ fib_test_lb_bucket_t lb_o_10_10_10_1 = {
+ .type = FT_LB_O_LB,
+ .lb = {
+ .lb = dpo_10_10_10_1->dpoi_index,
+ },
+ };
+ fib_test_lb_bucket_t lb_o_10_10_10_2 = {
+ .type = FT_LB_O_LB,
+ .lb = {
+ .lb = dpo_10_10_10_2->dpoi_index,
+ },
+ };
+
+ /*
+ * A prefix via the adj-fib that is BFD down => DROP
+ */
+ fei = fib_table_entry_path_add(0,
+ &pfx_200_0_0_0_s_24,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_NONE,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_2,
+ ~0, // recursive
+ 0, // default fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
+ "%U resolves via drop",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * add a path via the UP BFD adj-fib.
+ * we expect that the DOWN BFD ADJ FIB is not used.
+ */
+ fei = fib_table_entry_path_add(0,
+ &pfx_200_0_0_0_s_24,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_NONE,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_1,
+ ~0, // recursive
+ 0, // default fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 1,
+ &lb_o_10_10_10_1),
+ "Recursive %U only UP BFD adj-fibs",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * Send a BFD state change to UP - both sessions are now up
+ * the recursive prefix should LB over both
+ */
+ bfd_10_10_10_2.local_state = BFD_STATE_up;
+ fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
+
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 2,
+ &lb_o_10_10_10_1,
+ &lb_o_10_10_10_2),
+ "Recursive %U via both UP BFD adj-fibs",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * Send a BFD state change to DOWN
+ * the recursive prefix should exclude the down
+ */
+ bfd_10_10_10_2.local_state = BFD_STATE_down;
+ fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
+
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 1,
+ &lb_o_10_10_10_1),
+ "Recursive %U via only UP",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * Delete the BFD session while it is in the DOWN state.
+ * FIB should consider the entry's state as back up
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 2,
+ &lb_o_10_10_10_1,
+ &lb_o_10_10_10_2),
+ "Recursive %U via both UP BFD adj-fibs post down session delete",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * Delete the BFD other session while it is in the UP state.
+ */
+ fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 2,
+ &lb_o_10_10_10_1,
+ &lb_o_10_10_10_2),
+ "Recursive %U via both UP BFD adj-fibs post up session delete",
+ format_fib_prefix, &pfx_200_0_0_0_s_24);
+
+ /*
+ * cleaup
+ */
+ fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
+ fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
+ fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
+
+ fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
+ fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
+
+ adj_unlock(ai_10_10_10_1);
+ /*
+ * test no-one left behind
+ */
+ FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
+ FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
+
+ /*
+ * Single-hop BFD tests
+ */
+ bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
+ bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
+
+ adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
+
+ ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
+ VNET_LINK_IP4,
+ &nh_10_10_10_1,
+ tm->hw[0]->sw_if_index);
+ /*
+ * whilst the BFD session is not signalled, the adj is up
+ */
+ FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
+
+ /*
+ * bring the BFD session up
+ */
+ bfd_10_10_10_1.local_state = BFD_STATE_up;
+ adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
+ FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
+
+ /*
+ * bring the BFD session down
+ */
+ bfd_10_10_10_1.local_state = BFD_STATE_down;
+ adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
+ FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
+
+
+ /*
+ * add an attached next hop FIB entry via the down adj
+ */
+ fib_prefix_t pfx_5_5_5_5_s_32 = {
+ .fp_addr = {
+ .ip4 = {
+ .as_u32 = clib_host_to_net_u32(0x05050505),
+ },
+ },
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ };
+
+ fei = fib_table_entry_path_add(0,
+ &pfx_5_5_5_5_s_32,
+ FIB_SOURCE_CLI,
+ FIB_ENTRY_FLAG_NONE,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_1,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
+ "%U resolves via drop",
+ format_fib_prefix, &pfx_5_5_5_5_s_32);
+
+ /*
+ * Add a path via an ADJ that is up
+ */
+ adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
+ VNET_LINK_IP4,
+ &nh_10_10_10_2,
+ tm->hw[0]->sw_if_index);
+
+ fib_test_lb_bucket_t adj_o_10_10_10_2 = {
+ .type = FT_LB_ADJ,
+ .adj = {
+ .adj = ai_10_10_10_2,
+ },
+ };
+ adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
+
+ fei = fib_table_entry_path_add(0,
+ &pfx_5_5_5_5_s_32,
+ FIB_SOURCE_CLI,
+ FIB_ENTRY_FLAG_NONE,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_2,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 1,
+ &adj_o_10_10_10_2),
+ "BFD sourced %U via %U",
+ format_fib_prefix, &pfx_5_5_5_5_s_32,
+ format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
+
+ /*
+ * Bring up the down session - should now LB
+ */
+ bfd_10_10_10_1.local_state = BFD_STATE_up;
+ adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
+ FIB_TEST(fib_test_validate_entry(fei,
+ FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+ 2,
+ &adj_o_10_10_10_1,
+ &adj_o_10_10_10_2),
+ "BFD sourced %U via noth adjs",
+ format_fib_prefix, &pfx_5_5_5_5_s_32);
+
+ /*
+ * remove the BFD session state from the adj
+ */
+ adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
+
+ /*
+ * clean-up
+ */
+ fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
+ adj_unlock(ai_10_10_10_1);
+ adj_unlock(ai_10_10_10_2);
+
+ /*
+ * test no-one left behind
+ */
+ FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
+ FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
+ return (0);
+}
+
static int
lfib_test (void)
{
res = 0;
fib_test_mk_intf(4);
+ if (unformat (input, "debug"))
+ {
+ fib_test_do_debug = 1;
+ }
+
if (unformat (input, "ip"))
{
res += fib_test_v4();
{
res += fib_test_walk();
}
+ else if (unformat (input, "bfd"))
+ {
+ res += fib_test_bfd();
+ }
else
{
/*
res += fib_test_v4();
res += fib_test_v6();
res += fib_test_ae();
+ res += fib_test_bfd();
res += fib_test_label();
res += lfib_test();
}