blob: 540289ce9891f176a40635b22f492154bf7c2fd0 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/fib/ip6_fib.h>
17#include <vnet/fib/ip4_fib.h>
18#include <vnet/fib/mpls_fib.h>
19#include <vnet/adj/adj.h>
20#include <vnet/dpo/load_balance.h>
21#include <vnet/dpo/load_balance_map.h>
22#include <vnet/dpo/mpls_label_dpo.h>
23#include <vnet/dpo/lookup_dpo.h>
24#include <vnet/dpo/drop_dpo.h>
25#include <vnet/dpo/receive_dpo.h>
Neale Ranns948e00f2016-10-20 13:39:34 +010026#include <vnet/dpo/ip_null_dpo.h>
Neale Ranns88fc83e2017-04-05 08:11:14 -070027#include <vnet/bfd/bfd_main.h>
Neale Ranns43161a82017-08-12 02:12:00 -070028#include <vnet/dpo/interface_rx_dpo.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080029#include <vnet/dpo/replicate_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010030
31#include <vnet/mpls/mpls.h>
32
33#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000034#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035#include <vnet/fib/fib_walk.h>
36#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010037#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010038
Neale Ranns88fc83e2017-04-05 08:11:14 -070039/*
40 * Add debugs for passing tests
41 */
42static int fib_test_do_debug;
43
Neale Ranns0bfe5d82016-08-25 15:29:12 +010044#define FIB_TEST_I(_cond, _comment, _args...) \
45({ \
46 int _evald = (_cond); \
47 if (!(_evald)) { \
48 fformat(stderr, "FAIL:%d: " _comment "\n", \
49 __LINE__, ##_args); \
50 } else { \
Neale Ranns88fc83e2017-04-05 08:11:14 -070051 if (fib_test_do_debug) \
52 fformat(stderr, "PASS:%d: " _comment "\n", \
53 __LINE__, ##_args); \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010054 } \
55 _evald; \
56})
57#define FIB_TEST(_cond, _comment, _args...) \
58{ \
59 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000060 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010061 ASSERT(!("FAIL: " _comment)); \
62 } \
63}
64
65/**
66 * A 'i'm not fussed is this is not efficient' store of test data
67 */
68typedef struct test_main_t_ {
69 /**
70 * HW if indicies
71 */
72 u32 hw_if_indicies[4];
73 /**
74 * HW interfaces
75 */
76 vnet_hw_interface_t * hw[4];
77
78} test_main_t;
79static test_main_t test_main;
80
81/* fake ethernet device class, distinct from "fake-ethX" */
82static u8 * format_test_interface_name (u8 * s, va_list * args)
83{
84 u32 dev_instance = va_arg (*args, u32);
85 return format (s, "test-eth%d", dev_instance);
86}
87
88static uword dummy_interface_tx (vlib_main_t * vm,
89 vlib_node_runtime_t * node,
90 vlib_frame_t * frame)
91{
92 clib_warning ("you shouldn't be here, leaking buffers...");
93 return frame->n_vectors;
94}
95
Neale Ranns8b37b872016-11-21 12:25:22 +000096static clib_error_t *
97test_interface_admin_up_down (vnet_main_t * vnm,
98 u32 hw_if_index,
99 u32 flags)
100{
101 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
102 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
103 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
104 return 0;
105}
106
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100107VNET_DEVICE_CLASS (test_interface_device_class,static) = {
108 .name = "Test interface",
109 .format_device_name = format_test_interface_name,
110 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000111 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100112};
113
114static u8 *hw_address;
115
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000116static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100117fib_test_mk_intf (u32 ninterfaces)
118{
119 clib_error_t * error = NULL;
120 test_main_t *tm = &test_main;
121 u8 byte;
122 u32 i;
123
124 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
125
126 for (i=0; i<6; i++)
127 {
128 byte = 0xd0+i;
129 vec_add1(hw_address, byte);
130 }
131
132 for (i = 0; i < ninterfaces; i++)
133 {
134 hw_address[5] = i;
135
136 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000137 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100138 i /* instance */,
139 hw_address,
140 &tm->hw_if_indicies[i],
141 /* flag change */ 0);
142
143 FIB_TEST((NULL == error), "ADD interface %d", i);
144
Neale Ranns8b37b872016-11-21 12:25:22 +0000145 error = vnet_hw_interface_set_flags(vnet_get_main(),
146 tm->hw_if_indicies[i],
147 VNET_HW_INTERFACE_FLAG_LINK_UP);
148 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100149 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000150 vec_validate (ip4_main.fib_index_by_sw_if_index,
151 tm->hw[i]->sw_if_index);
152 vec_validate (ip6_main.fib_index_by_sw_if_index,
153 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100154 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
155 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000156
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100157 error = vnet_sw_interface_set_flags(vnet_get_main(),
158 tm->hw[i]->sw_if_index,
159 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
160 FIB_TEST((NULL == error), "UP interface %d", i);
161 }
162 /*
163 * re-eval after the inevitable realloc
164 */
165 for (i = 0; i < ninterfaces; i++)
166 {
167 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
168 tm->hw_if_indicies[i]);
169 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000170
171 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100172}
173
Neale Ranns3ee44042016-10-03 13:05:48 +0100174#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100175{ \
176 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
177 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
178 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
179 fib_table_lookup(fib_index, (_via_prefix))); \
180 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100181 load_balance_get_bucket(_rec_dpo->dpoi_index, \
182 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100183 "%U is recursive via %U", \
184 format_fib_prefix, (_rec_prefix), \
185 format_fib_prefix, _via_prefix); \
186}
187
188#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
189{ \
190 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
191 fib_table_lookup_exact_match(fib_index, (_prefix))); \
192 const dpo_id_t *_dpo1 = \
193 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
194 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
195 format_dpo_type, _dpo1->dpoi_type); \
196 FIB_TEST((_ai == _dpo1->dpoi_index), \
197 "%U bucket %d resolves via %U", \
198 format_fib_prefix, (_prefix), \
199 _bucket, \
200 format_dpo_id, _dpo1, 0); \
201}
202
Neale Ranns3ee44042016-10-03 13:05:48 +0100203#define FIB_TEST_RPF(_cond, _comment, _args...) \
204{ \
205 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
206 return (0); \
207 } \
208}
209
210static int
211fib_test_urpf_is_equal (fib_node_index_t fei,
212 fib_forward_chain_type_t fct,
213 u32 num, ...)
214{
Neale Ranns948e00f2016-10-20 13:39:34 +0100215 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100216 fib_urpf_list_t *urpf;
217 index_t ui;
218 va_list ap;
219 int ii;
220
221 va_start(ap, num);
222
223 fib_entry_contribute_forwarding(fei, fct, &dpo);
224 ui = load_balance_get_urpf(dpo.dpoi_index);
225
226 urpf = fib_urpf_list_get(ui);
227
228 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
229 "RPF:%U len %d == %d",
230 format_fib_urpf_list, ui,
231 num, vec_len(urpf->furpf_itfs));
232 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
233 "RPF:%U check-size %d == %d",
234 format_fib_urpf_list, ui,
235 num, vec_len(urpf->furpf_itfs));
236
237 for (ii = 0; ii < num; ii++)
238 {
239 adj_index_t ai = va_arg(ap, adj_index_t);
240
241 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
242 "RPF:%d item:%d - %d == %d",
243 ui, ii, ai, urpf->furpf_itfs[ii]);
244 FIB_TEST_RPF(fib_urpf_check(ui, ai),
245 "RPF:%d %d found",
246 ui, ai);
247 }
248
249 dpo_reset(&dpo);
250
Neale Ranns5899fde2016-10-12 13:51:05 +0100251 va_end(ap);
252
Neale Ranns3ee44042016-10-03 13:05:48 +0100253 return (1);
254}
255
Neale Rannsb80c5362016-10-08 13:03:40 +0100256static u8*
257fib_test_build_rewrite (u8 *eth_addr)
258{
259 u8* rewrite = NULL;
260
261 vec_validate(rewrite, 13);
262
263 memcpy(rewrite, eth_addr, 6);
264 memcpy(rewrite+6, eth_addr, 6);
265
266 return (rewrite);
267}
268
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000269typedef enum fib_test_lb_bucket_type_t_ {
270 FT_LB_LABEL_O_ADJ,
Neale Rannsad422ed2016-11-02 14:20:04 +0000271 FT_LB_LABEL_STACK_O_ADJ,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000272 FT_LB_LABEL_O_LB,
273 FT_LB_O_LB,
274 FT_LB_SPECIAL,
275 FT_LB_ADJ,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800276 FT_LB_INTF,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000277} fib_test_lb_bucket_type_t;
278
279typedef struct fib_test_lb_bucket_t_ {
280 fib_test_lb_bucket_type_t type;
281
282 union
283 {
284 struct
285 {
286 mpls_eos_bit_t eos;
287 mpls_label_t label;
288 u8 ttl;
289 adj_index_t adj;
290 } label_o_adj;
291 struct
292 {
293 mpls_eos_bit_t eos;
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 mpls_label_t label_stack[8];
295 u8 label_stack_size;
296 u8 ttl;
297 adj_index_t adj;
298 } label_stack_o_adj;
299 struct
300 {
301 mpls_eos_bit_t eos;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000302 mpls_label_t label;
303 u8 ttl;
304 index_t lb;
305 } label_o_lb;
306 struct
307 {
308 index_t adj;
309 } adj;
310 struct
311 {
312 index_t lb;
313 } lb;
314 struct
315 {
316 index_t adj;
317 } special;
318 };
319} fib_test_lb_bucket_t;
320
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800321typedef enum fib_test_rep_bucket_type_t_ {
322 FT_REP_LABEL_O_ADJ,
323 FT_REP_DISP_MFIB_LOOKUP,
324 FT_REP_INTF,
325} fib_test_rep_bucket_type_t;
326
327typedef struct fib_test_rep_bucket_t_ {
328 fib_test_rep_bucket_type_t type;
329
330 union
331 {
332 struct
333 {
334 mpls_eos_bit_t eos;
335 mpls_label_t label;
336 u8 ttl;
337 adj_index_t adj;
338 } label_o_adj;
339 struct
340 {
341 adj_index_t adj;
342 } adj;
343 };
344} fib_test_rep_bucket_t;
345
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000346#define FIB_TEST_LB(_cond, _comment, _args...) \
347{ \
348 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
349 return (0); \
350 } \
351}
352
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800353int
354fib_test_validate_rep_v (const replicate_t *rep,
355 u16 n_buckets,
356 va_list ap)
357{
358 const fib_test_rep_bucket_t *exp;
359 const dpo_id_t *dpo;
360 int bucket;
361
362 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
363 "n_buckets = %d", rep->rep_n_buckets);
364
365 for (bucket = 0; bucket < n_buckets; bucket++)
366 {
367 exp = va_arg(ap, fib_test_rep_bucket_t*);
368
369 dpo = replicate_get_bucket_i(rep, bucket);
370
371 switch (exp->type)
372 {
373 case FT_REP_LABEL_O_ADJ:
374 {
375 const mpls_label_dpo_t *mld;
376 mpls_label_t hdr;
377 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
378 "bucket %d stacks on %U",
379 bucket,
380 format_dpo_type, dpo->dpoi_type);
381
382 mld = mpls_label_dpo_get(dpo->dpoi_index);
383 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
384
385 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
386 exp->label_o_adj.label),
387 "bucket %d stacks on label %d",
388 bucket,
389 exp->label_o_adj.label);
390
391 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
392 exp->label_o_adj.eos),
393 "bucket %d stacks on label %d %U",
394 bucket,
395 exp->label_o_adj.label,
396 format_mpls_eos_bit, exp->label_o_adj.eos);
397
398 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
399 "bucket %d label stacks on %U",
400 bucket,
401 format_dpo_type, mld->mld_dpo.dpoi_type);
402
403 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
404 "bucket %d label stacks on adj %d",
405 bucket,
406 exp->label_o_adj.adj);
407 }
408 break;
409 case FT_REP_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700410 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800411 "bucket %d stacks on %U",
412 bucket,
413 format_dpo_type, dpo->dpoi_type);
414
415 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
416 "bucket %d stacks on adj %d",
417 bucket,
418 exp->adj.adj);
419 break;
420 case FT_REP_DISP_MFIB_LOOKUP:
421// ASSERT(0);
422 break;
423 }
424 }
425
426 return (!0);
427}
428
429int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000430fib_test_validate_lb_v (const load_balance_t *lb,
431 u16 n_buckets,
432 va_list ap)
433{
434 const dpo_id_t *dpo;
435 int bucket;
436
437 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
438
439 for (bucket = 0; bucket < n_buckets; bucket++)
440 {
441 const fib_test_lb_bucket_t *exp;
442
443 exp = va_arg(ap, fib_test_lb_bucket_t*);
444 dpo = load_balance_get_bucket_i(lb, bucket);
445
446 switch (exp->type)
447 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000448 case FT_LB_LABEL_STACK_O_ADJ:
449 {
450 const mpls_label_dpo_t *mld;
451 mpls_label_t hdr;
452 u32 ii;
453
454 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
455 "bucket %d stacks on %U",
456 bucket,
457 format_dpo_type, dpo->dpoi_type);
458
459 mld = mpls_label_dpo_get(dpo->dpoi_index);
460
461 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
462 "label stack size",
463 mld->mld_n_labels);
464
465 for (ii = 0; ii < mld->mld_n_labels; ii++)
466 {
467 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
468 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
469 exp->label_stack_o_adj.label_stack[ii]),
470 "bucket %d stacks on label %d",
471 bucket,
472 exp->label_stack_o_adj.label_stack[ii]);
473
474 if (ii == mld->mld_n_labels-1)
475 {
476 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
477 exp->label_o_adj.eos),
478 "bucket %d stacks on label %d %U!=%U",
479 bucket,
480 exp->label_stack_o_adj.label_stack[ii],
481 format_mpls_eos_bit, exp->label_o_adj.eos,
482 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
483 }
484 else
485 {
486 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
487 "bucket %d stacks on label %d %U",
488 bucket,
489 exp->label_stack_o_adj.label_stack[ii],
490 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
491 }
492 }
493
494 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
495 "bucket %d label stacks on %U",
496 bucket,
497 format_dpo_type, mld->mld_dpo.dpoi_type);
498
499 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
500 "bucket %d label stacks on adj %d",
501 bucket,
502 exp->label_stack_o_adj.adj);
503 }
504 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000505 case FT_LB_LABEL_O_ADJ:
506 {
507 const mpls_label_dpo_t *mld;
508 mpls_label_t hdr;
509 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
510 "bucket %d stacks on %U",
511 bucket,
512 format_dpo_type, dpo->dpoi_type);
513
514 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000515 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000516
517 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
518 exp->label_o_adj.label),
519 "bucket %d stacks on label %d",
520 bucket,
521 exp->label_o_adj.label);
522
523 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
524 exp->label_o_adj.eos),
525 "bucket %d stacks on label %d %U",
526 bucket,
527 exp->label_o_adj.label,
528 format_mpls_eos_bit, exp->label_o_adj.eos);
529
530 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
531 "bucket %d label stacks on %U",
532 bucket,
533 format_dpo_type, mld->mld_dpo.dpoi_type);
534
535 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
536 "bucket %d label stacks on adj %d",
537 bucket,
538 exp->label_o_adj.adj);
539 }
540 break;
541 case FT_LB_LABEL_O_LB:
542 {
543 const mpls_label_dpo_t *mld;
544 mpls_label_t hdr;
545
546 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
547 "bucket %d stacks on %U",
548 bucket,
549 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000550
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000551 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000553
Neale Rannsad422ed2016-11-02 14:20:04 +0000554 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
555 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000556 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
557 exp->label_o_lb.label),
558 "bucket %d stacks on label %d",
559 bucket,
560 exp->label_o_lb.label);
561
562 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
563 exp->label_o_lb.eos),
564 "bucket %d stacks on label %d %U",
565 bucket,
566 exp->label_o_lb.label,
567 format_mpls_eos_bit, exp->label_o_lb.eos);
568
569 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
570 "bucket %d label stacks on %U",
571 bucket,
572 format_dpo_type, mld->mld_dpo.dpoi_type);
573
574 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
575 "bucket %d label stacks on LB %d",
576 bucket,
577 exp->label_o_lb.lb);
578 }
579 break;
580 case FT_LB_ADJ:
581 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
582 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
583 "bucket %d stacks on %U",
584 bucket,
585 format_dpo_type, dpo->dpoi_type);
586 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
587 "bucket %d stacks on adj %d",
588 bucket,
589 exp->adj.adj);
590 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800591 case FT_LB_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700592 FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800593 "bucket %d stacks on %U",
594 bucket,
595 format_dpo_type, dpo->dpoi_type);
596 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
597 "bucket %d stacks on adj %d",
598 bucket,
599 exp->adj.adj);
600 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000601 case FT_LB_O_LB:
602 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
603 "bucket %d stacks on %U",
604 bucket,
605 format_dpo_type, dpo->dpoi_type);
606 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
Neale Ranns57b58602017-07-15 07:37:25 -0700607 "bucket %d stacks on lb %d not %d",
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000608 bucket,
Neale Ranns57b58602017-07-15 07:37:25 -0700609 dpo->dpoi_index,
610 exp->lb.lb);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000611 break;
612 case FT_LB_SPECIAL:
613 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
614 "bucket %d stacks on %U",
615 bucket,
616 format_dpo_type, dpo->dpoi_type);
617 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
618 "bucket %d stacks on drop %d",
619 bucket,
620 exp->special.adj);
621 break;
622 }
623 }
624 return (!0);
625}
626
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800627int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000628fib_test_validate_entry (fib_node_index_t fei,
629 fib_forward_chain_type_t fct,
630 u16 n_buckets,
631 ...)
632{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000633 dpo_id_t dpo = DPO_INVALID;
634 fib_prefix_t pfx;
635 index_t fw_lbi;
636 u32 fib_index;
637 va_list ap;
638 int res;
639
640 va_start(ap, n_buckets);
641
642 fib_entry_get_prefix(fei, &pfx);
643 fib_index = fib_entry_get_fib_index(fei);
644 fib_entry_contribute_forwarding(fei, fct, &dpo);
645
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800646 if (DPO_REPLICATE == dpo.dpoi_type)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000647 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800648 const replicate_t *rep;
649
650 rep = replicate_get(dpo.dpoi_index);
651 res = fib_test_validate_rep_v(rep, n_buckets, ap);
652 }
653 else
654 {
655 const load_balance_t *lb;
656
657 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
658 "Entry links to %U",
659 format_dpo_type, dpo.dpoi_type);
660
661 lb = load_balance_get(dpo.dpoi_index);
662 res = fib_test_validate_lb_v(lb, n_buckets, ap);
663
664 /*
665 * ensure that the LB contributed by the entry is the
666 * same as the LB in the forwarding tables
667 */
668 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Rannsad422ed2016-11-02 14:20:04 +0000669 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800670 switch (pfx.fp_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000671 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800672 case FIB_PROTOCOL_IP4:
673 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
Neale Rannsad422ed2016-11-02 14:20:04 +0000674 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800675 case FIB_PROTOCOL_IP6:
676 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
677 break;
678 case FIB_PROTOCOL_MPLS:
679 {
680 mpls_unicast_header_t hdr = {
681 .label_exp_s_ttl = 0,
682 };
683
684 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
685 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
686 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
687
688 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
689 break;
690 }
691 default:
692 fw_lbi = 0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000693 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800694 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
695 "Contributed LB = FW LB: %U\n %U",
696 format_load_balance, fw_lbi, 0,
697 format_load_balance, dpo.dpoi_index, 0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000698 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000699 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000700
701 dpo_reset(&dpo);
702
703 va_end(ap);
704
705 return (res);
706}
707
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000708static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100709fib_test_v4 (void)
710{
711 /*
712 * In the default table check for the presence and correct forwarding
713 * of the special entries
714 */
715 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
716 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
717 const ip_adjacency_t *adj;
718 const load_balance_t *lb;
719 test_main_t *tm;
720 u32 fib_index;
Neale Ranns994dab42017-04-18 12:56:45 -0700721 int lb_count;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100722 int ii;
723
724 /* via 10.10.10.1 */
725 ip46_address_t nh_10_10_10_1 = {
726 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
727 };
728 /* via 10.10.10.2 */
729 ip46_address_t nh_10_10_10_2 = {
730 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
731 };
732
Neale Rannsf12a83f2017-04-18 09:09:40 -0700733 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
734 pool_elts(load_balance_map_pool));
735
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100736 tm = &test_main;
737
Neale Ranns994dab42017-04-18 12:56:45 -0700738 /* record the nubmer of load-balances in use before we start */
739 lb_count = pool_elts(load_balance_pool);
740
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100741 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -0700742 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
743 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100744
745 for (ii = 0; ii < 4; ii++)
746 {
747 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
748 }
749
750 fib_prefix_t pfx_0_0_0_0_s_0 = {
751 .fp_len = 0,
752 .fp_proto = FIB_PROTOCOL_IP4,
753 .fp_addr = {
754 .ip4 = {
755 {0}
756 },
757 },
758 };
759
760 fib_prefix_t pfx = {
761 .fp_len = 0,
762 .fp_proto = FIB_PROTOCOL_IP4,
763 .fp_addr = {
764 .ip4 = {
765 {0}
766 },
767 },
768 };
769
770 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
771
772 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
773 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
774 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
775 "Default route is DROP");
776
777 pfx.fp_len = 32;
778 fei = fib_table_lookup(fib_index, &pfx);
779 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
780 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
781 "all 0s route is DROP");
782
783 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
784 pfx.fp_len = 32;
785 fei = fib_table_lookup(fib_index, &pfx);
786 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
787 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
788 "all 1s route is DROP");
789
790 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
791 pfx.fp_len = 8;
792 fei = fib_table_lookup(fib_index, &pfx);
793 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
794 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
795 "all-mcast route is DROP");
796
797 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
798 pfx.fp_len = 8;
799 fei = fib_table_lookup(fib_index, &pfx);
800 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
801 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
802 "class-e route is DROP");
803
804 /*
805 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
806 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000807 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
808 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100809 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000810#define ENBR (5+5+2)
811#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100812 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000813 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100814 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000815 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100816 fib_entry_pool_size());
817
818 /*
819 * add interface routes.
820 * validate presence of /24 attached and /32 recieve.
821 * test for the presence of the receive address in the glean and local adj
822 */
823 fib_prefix_t local_pfx = {
824 .fp_len = 24,
825 .fp_proto = FIB_PROTOCOL_IP4,
826 .fp_addr = {
827 .ip4 = {
828 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
829 },
830 },
831 };
832
833 fib_table_entry_update_one_path(fib_index, &local_pfx,
834 FIB_SOURCE_INTERFACE,
835 (FIB_ENTRY_FLAG_CONNECTED |
836 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -0700837 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100838 NULL,
839 tm->hw[0]->sw_if_index,
840 ~0, // invalid fib index
841 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000842 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100843 FIB_ROUTE_PATH_FLAG_NONE);
844 fei = fib_table_lookup(fib_index, &local_pfx);
845 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
846 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
847 fib_entry_get_flags(fei)),
848 "Flags set on attached interface");
849
850 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -0700851 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
852 "attached interface route adj present %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100853 adj = adj_get(ai);
854 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
855 "attached interface adj is glean");
856 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
857 &adj->sub_type.glean.receive_addr)),
858 "attached interface adj is receive ok");
859
860 local_pfx.fp_len = 32;
861 fib_table_entry_update_one_path(fib_index, &local_pfx,
862 FIB_SOURCE_INTERFACE,
863 (FIB_ENTRY_FLAG_CONNECTED |
864 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -0700865 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100866 NULL,
867 tm->hw[0]->sw_if_index,
868 ~0, // invalid fib index
869 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000870 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100871 FIB_ROUTE_PATH_FLAG_NONE);
872 fei = fib_table_lookup(fib_index, &local_pfx);
873 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
874 fib_entry_get_flags(fei)),
875 "Flags set on local interface");
876
877 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
878
879 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100880 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
881 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100882 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
883 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
884 "local interface adj is local");
885 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
886
887 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
888 &rd->rd_addr)),
889 "local interface adj is receive ok");
890
891 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
892 FIB_PROTOCOL_IP4,
893 FIB_SOURCE_INTERFACE)),
894 "2 Interface Source'd prefixes");
895
896 /*
897 * +2 interface routes +2 non-shared path-lists
898 */
899 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000900 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100901 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000902 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100903 fib_entry_pool_size());
904
905 /*
906 * Modify the default route to be via an adj not yet known.
907 * this sources the defalut route with the API source, which is
908 * a higher preference to the DEFAULT_ROUTE source
909 */
910 pfx.fp_addr.ip4.as_u32 = 0;
911 pfx.fp_len = 0;
912 fib_table_entry_path_add(fib_index, &pfx,
913 FIB_SOURCE_API,
914 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -0700915 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100916 &nh_10_10_10_1,
917 tm->hw[0]->sw_if_index,
918 ~0, // invalid fib index
919 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000920 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100921 FIB_ROUTE_PATH_FLAG_NONE);
922 fei = fib_table_lookup(fib_index, &pfx);
923 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
924 "Flags set on API route");
925
926 FIB_TEST((fei == dfrt), "default route same index");
927 ai = fib_entry_get_adj(fei);
928 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
929 adj = adj_get(ai);
930 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
931 "adj is incomplete");
932 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
933 "adj nbr next-hop ok");
934 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
935 FIB_PROTOCOL_IP4,
936 FIB_SOURCE_API)),
937 "1 API Source'd prefixes");
938
939 /*
940 * find the adj in the shared db
941 */
942 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100943 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100944 &nh_10_10_10_1,
945 tm->hw[0]->sw_if_index);
946 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
947 adj_unlock(locked_ai);
948
949 /*
950 * +1 shared path-list
951 */
952 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
953 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000954 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100955 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000956 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100957 fib_entry_pool_size());
958
959 /*
960 * remove the API source from the default route. We expected
961 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
962 */
963 pfx.fp_addr.ip4.as_u32 = 0;
964 pfx.fp_len = 0;
965 fib_table_entry_path_remove(fib_index, &pfx,
966 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -0700967 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100968 &nh_10_10_10_1,
969 tm->hw[0]->sw_if_index,
970 ~0, // non-recursive path, so no FIB index
971 1,
972 FIB_ROUTE_PATH_FLAG_NONE);
973
974 fei = fib_table_lookup(fib_index, &pfx);
975
976 FIB_TEST((fei == dfrt), "default route same index");
977 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
978 "Default route is DROP");
979
980 /*
981 * -1 shared-path-list
982 */
983 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000984 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100985 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000986 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100987 fib_entry_pool_size());
988
989 /*
990 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
991 */
992 fib_prefix_t pfx_10_10_10_1_s_32 = {
993 .fp_len = 32,
994 .fp_proto = FIB_PROTOCOL_IP4,
995 .fp_addr = {
996 /* 10.10.10.1 */
997 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
998 },
999 };
1000 fib_prefix_t pfx_10_10_10_2_s_32 = {
1001 .fp_len = 32,
1002 .fp_proto = FIB_PROTOCOL_IP4,
1003 .fp_addr = {
1004 /* 10.10.10.2 */
1005 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1006 },
1007 };
1008 fib_prefix_t pfx_11_11_11_11_s_32 = {
1009 .fp_len = 32,
1010 .fp_proto = FIB_PROTOCOL_IP4,
1011 .fp_addr = {
1012 /* 11.11.11.11 */
1013 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1014 },
1015 };
1016 u8 eth_addr[] = {
1017 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1018 };
Neale Rannsb80c5362016-10-08 13:03:40 +01001019
Neale Ranns3ee44042016-10-03 13:05:48 +01001020 ip46_address_t nh_12_12_12_12 = {
1021 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1022 };
1023 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001024
1025 /*
1026 * Add a route via an incomplete ADJ. then complete the ADJ
1027 * Expect the route LB is updated to use complete adj type.
1028 */
1029 fei = fib_table_entry_update_one_path(fib_index,
1030 &pfx_11_11_11_11_s_32,
1031 FIB_SOURCE_API,
1032 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001033 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001034 &pfx_10_10_10_1_s_32.fp_addr,
1035 tm->hw[0]->sw_if_index,
1036 ~0, // invalid fib index
1037 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001038 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001039 FIB_ROUTE_PATH_FLAG_NONE);
1040
1041 dpo = fib_entry_contribute_ip_forwarding(fei);
1042 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1043 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1044 "11.11.11.11/32 via incomplete adj");
1045
1046 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001047 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001048 &pfx_10_10_10_1_s_32.fp_addr,
1049 tm->hw[0]->sw_if_index);
1050 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1051 adj = adj_get(ai_01);
1052 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1053 "adj is incomplete");
1054 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1055 &adj->sub_type.nbr.next_hop)),
1056 "adj nbr next-hop ok");
1057
Neale Rannsb80c5362016-10-08 13:03:40 +01001058 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1059 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001060 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1061 "adj is complete");
1062 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1063 &adj->sub_type.nbr.next_hop)),
1064 "adj nbr next-hop ok");
1065 ai = fib_entry_get_adj(fei);
1066 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1067
1068 dpo = fib_entry_contribute_ip_forwarding(fei);
1069 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1070 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1071 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001072 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1073 tm->hw[0]->sw_if_index),
1074 "RPF list for adj-fib contains adj");
1075
1076 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001077 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001078 &nh_12_12_12_12,
1079 tm->hw[1]->sw_if_index);
1080 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1081 adj = adj_get(ai_12_12_12_12);
1082 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1083 "adj is incomplete");
1084 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1085 &adj->sub_type.nbr.next_hop)),
1086 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001087 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1088 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001089 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1090 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001091
1092 /*
1093 * add the adj fib
1094 */
Neale Ranns81424992017-05-18 03:03:22 -07001095 fei = fib_table_entry_path_add(fib_index,
1096 &pfx_10_10_10_1_s_32,
1097 FIB_SOURCE_ADJ,
1098 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001099 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001100 &pfx_10_10_10_1_s_32.fp_addr,
1101 tm->hw[0]->sw_if_index,
1102 ~0, // invalid fib index
1103 1,
1104 NULL,
1105 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001106 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1107 "Flags set on adj-fib");
1108 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -07001109 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001110
1111 fib_table_entry_path_remove(fib_index,
1112 &pfx_11_11_11_11_s_32,
1113 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001114 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001115 &pfx_10_10_10_1_s_32.fp_addr,
1116 tm->hw[0]->sw_if_index,
1117 ~0, // invalid fib index
1118 1,
1119 FIB_ROUTE_PATH_FLAG_NONE);
1120
1121 eth_addr[5] = 0xb2;
1122
1123 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001124 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001125 &pfx_10_10_10_2_s_32.fp_addr,
1126 tm->hw[0]->sw_if_index);
1127 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1128 adj = adj_get(ai_02);
1129 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1130 "adj is incomplete");
1131 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1132 &adj->sub_type.nbr.next_hop)),
1133 "adj nbr next-hop ok");
1134
Neale Rannsb80c5362016-10-08 13:03:40 +01001135 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1136 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001137 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1138 "adj is complete");
1139 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1140 &adj->sub_type.nbr.next_hop)),
1141 "adj nbr next-hop ok");
1142 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1143
Neale Ranns81424992017-05-18 03:03:22 -07001144 fib_table_entry_path_add(fib_index,
1145 &pfx_10_10_10_2_s_32,
1146 FIB_SOURCE_ADJ,
1147 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001148 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001149 &pfx_10_10_10_2_s_32.fp_addr,
1150 tm->hw[0]->sw_if_index,
1151 ~0, // invalid fib index
1152 1,
1153 NULL,
1154 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001155
1156 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1157 ai = fib_entry_get_adj(fei);
1158 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1159
1160 /*
1161 * +2 adj-fibs, and their non-shared path-lists
1162 */
1163 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001164 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001165 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001166 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001167 fib_entry_pool_size());
1168
1169 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001170 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001171 */
1172 fib_prefix_t pfx_1_1_1_1_s_32 = {
1173 .fp_len = 32,
1174 .fp_proto = FIB_PROTOCOL_IP4,
1175 .fp_addr = {
1176 /* 1.1.1.1/32 */
1177 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1178 },
1179 };
1180
1181 fib_table_entry_path_add(fib_index,
1182 &pfx_1_1_1_1_s_32,
1183 FIB_SOURCE_API,
1184 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001185 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001186 &nh_10_10_10_1,
1187 tm->hw[0]->sw_if_index,
1188 ~0, // invalid fib index
1189 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001190 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001191 FIB_ROUTE_PATH_FLAG_NONE);
1192 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1193 ai = fib_entry_get_adj(fei);
1194 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1195
1196 /*
1197 * +1 entry and a shared path-list
1198 */
1199 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001200 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001201 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001202 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001203 fib_entry_pool_size());
1204
1205 /* 1.1.2.0/24 */
1206 fib_prefix_t pfx_1_1_2_0_s_24 = {
1207 .fp_len = 24,
1208 .fp_proto = FIB_PROTOCOL_IP4,
1209 .fp_addr = {
1210 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1211 }
1212 };
1213
1214 fib_table_entry_path_add(fib_index,
1215 &pfx_1_1_2_0_s_24,
1216 FIB_SOURCE_API,
1217 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001218 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001219 &nh_10_10_10_1,
1220 tm->hw[0]->sw_if_index,
1221 ~0, // invalid fib index
1222 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001223 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001224 FIB_ROUTE_PATH_FLAG_NONE);
1225 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1226 ai = fib_entry_get_adj(fei);
1227 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1228
1229 /*
1230 * +1 entry only
1231 */
1232 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001233 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001234 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001235 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001236 fib_entry_pool_size());
1237
1238 /*
1239 * modify 1.1.2.0/24 to use multipath.
1240 */
1241 fib_table_entry_path_add(fib_index,
1242 &pfx_1_1_2_0_s_24,
1243 FIB_SOURCE_API,
1244 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001245 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001246 &nh_10_10_10_2,
1247 tm->hw[0]->sw_if_index,
1248 ~0, // invalid fib index
1249 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001250 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001251 FIB_ROUTE_PATH_FLAG_NONE);
1252 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1253 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001254 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1255 1, tm->hw[0]->sw_if_index),
1256 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001257
1258 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1259 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1260 FIB_TEST((ai_01 == dpo1->dpoi_index),
1261 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1262 ai_01, dpo1->dpoi_index);
1263
1264 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1265 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1266 FIB_TEST((ai_02 == dpo1->dpoi_index),
1267 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1268
1269 /*
1270 * +1 shared-pathlist
1271 */
1272 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001273 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001274 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001275 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001276 fib_entry_pool_size());
1277
1278 /*
1279 * revert the modify
1280 */
1281 fib_table_entry_path_remove(fib_index,
1282 &pfx_1_1_2_0_s_24,
1283 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001284 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001285 &nh_10_10_10_2,
1286 tm->hw[0]->sw_if_index,
1287 ~0,
1288 1,
1289 FIB_ROUTE_PATH_FLAG_NONE);
1290 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001291 dpo = fib_entry_contribute_ip_forwarding(fei);
1292 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1293 1, tm->hw[0]->sw_if_index),
1294 "RPF list for 1.1.2.0/24 contains one adj");
1295
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001296 ai = fib_entry_get_adj(fei);
1297 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1298
1299 /*
1300 * +1 shared-pathlist
1301 */
1302 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1303 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001304 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001305 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001306 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001307 fib_entry_pool_size());
1308
1309 /*
1310 * Add 2 recursive routes:
1311 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1312 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1313 */
1314 fib_prefix_t bgp_100_pfx = {
1315 .fp_len = 32,
1316 .fp_proto = FIB_PROTOCOL_IP4,
1317 .fp_addr = {
1318 /* 100.100.100.100/32 */
1319 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1320 },
1321 };
1322 /* via 1.1.1.1 */
1323 ip46_address_t nh_1_1_1_1 = {
1324 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1325 };
1326
Neale Ranns3ee44042016-10-03 13:05:48 +01001327 fei = fib_table_entry_path_add(fib_index,
1328 &bgp_100_pfx,
1329 FIB_SOURCE_API,
1330 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001331 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001332 &nh_1_1_1_1,
1333 ~0, // no index provided.
1334 fib_index, // nexthop in same fib as route
1335 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001336 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001337 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001338
Neale Ranns3ee44042016-10-03 13:05:48 +01001339 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1340 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1341 tm->hw[0]->sw_if_index),
1342 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001343
1344 /*
1345 * +1 entry and +1 shared-path-list
1346 */
1347 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1348 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001349 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001350 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001351 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001352 fib_entry_pool_size());
1353
1354 fib_prefix_t bgp_101_pfx = {
1355 .fp_len = 32,
1356 .fp_proto = FIB_PROTOCOL_IP4,
1357 .fp_addr = {
1358 /* 100.100.100.101/32 */
1359 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1360 },
1361 };
1362
1363 fib_table_entry_path_add(fib_index,
1364 &bgp_101_pfx,
1365 FIB_SOURCE_API,
1366 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001367 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001368 &nh_1_1_1_1,
1369 ~0, // no index provided.
1370 fib_index, // nexthop in same fib as route
1371 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001372 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001373 FIB_ROUTE_PATH_FLAG_NONE);
1374
Neale Ranns3ee44042016-10-03 13:05:48 +01001375 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1376 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1377 tm->hw[0]->sw_if_index),
1378 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001379
1380 /*
1381 * +1 entry, but the recursive path-list is shared.
1382 */
1383 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1384 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001385 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001386 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001387 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001388 fib_entry_pool_size());
1389
1390 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001391 * An special route; one where the user (me) provides the
1392 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001393 */
1394 fib_prefix_t ex_pfx = {
1395 .fp_len = 32,
1396 .fp_proto = FIB_PROTOCOL_IP4,
1397 .fp_addr = {
1398 /* 4.4.4.4/32 */
1399 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1400 },
1401 };
1402
1403 fib_table_entry_special_add(fib_index,
1404 &ex_pfx,
1405 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001406 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001407 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001408 dpo = fib_entry_contribute_ip_forwarding(fei);
1409 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1410 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1411 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001412
1413 fib_table_entry_special_remove(fib_index,
1414 &ex_pfx,
1415 FIB_SOURCE_SPECIAL);
1416 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1417 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1418 "Exclusive reoute removed");
1419
1420 /*
1421 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1422 * adjacency through which the route will resovle
1423 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001424 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001425
1426 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1427 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001428 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001429 LOOKUP_INPUT_DST_ADDR,
1430 LOOKUP_TABLE_FROM_CONFIG,
1431 &ex_dpo);
1432
1433 fib_table_entry_special_dpo_add(fib_index,
1434 &ex_pfx,
1435 FIB_SOURCE_SPECIAL,
1436 FIB_ENTRY_FLAG_EXCLUSIVE,
1437 &ex_dpo);
1438 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1439 dpo = fib_entry_contribute_ip_forwarding(fei);
1440 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1441 "exclusive remote uses lookup DPO");
1442
Neale Ranns948e00f2016-10-20 13:39:34 +01001443 /*
1444 * update the exclusive to use a different DPO
1445 */
Neale Ranns450cd302016-11-09 17:49:42 +00001446 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001447 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1448 &ex_dpo);
1449 fib_table_entry_special_dpo_update(fib_index,
1450 &ex_pfx,
1451 FIB_SOURCE_SPECIAL,
1452 FIB_ENTRY_FLAG_EXCLUSIVE,
1453 &ex_dpo);
1454 dpo = fib_entry_contribute_ip_forwarding(fei);
1455 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1456 "exclusive remote uses now uses NULL DPO");
1457
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001458 fib_table_entry_special_remove(fib_index,
1459 &ex_pfx,
1460 FIB_SOURCE_SPECIAL);
1461 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1462 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1463 "Exclusive reoute removed");
1464 dpo_reset(&ex_dpo);
1465
1466 /*
1467 * Add a recursive route:
1468 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1469 */
1470 fib_prefix_t bgp_200_pfx = {
1471 .fp_len = 32,
1472 .fp_proto = FIB_PROTOCOL_IP4,
1473 .fp_addr = {
1474 /* 200.200.200.200/32 */
1475 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1476 },
1477 };
1478 /* via 1.1.1.2 */
1479 fib_prefix_t pfx_1_1_1_2_s_32 = {
1480 .fp_len = 32,
1481 .fp_proto = FIB_PROTOCOL_IP4,
1482 .fp_addr = {
1483 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1484 },
1485 };
1486
Neale Ranns57b58602017-07-15 07:37:25 -07001487 fei = fib_table_entry_path_add(fib_index,
1488 &bgp_200_pfx,
1489 FIB_SOURCE_API,
1490 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001491 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07001492 &pfx_1_1_1_2_s_32.fp_addr,
1493 ~0, // no index provided.
1494 fib_index, // nexthop in same fib as route
1495 1,
1496 NULL,
1497 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001498
Neale Ranns57b58602017-07-15 07:37:25 -07001499 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1500 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001501
1502 /*
1503 * the adj should be recursive via drop, since the route resolves via
1504 * the default route, which is itself a DROP
1505 */
1506 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1507 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1508 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001509 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1510 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001511
1512 /*
1513 * +2 entry and +1 shared-path-list
1514 */
1515 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1516 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001517 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001518 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001519 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001520 fib_entry_pool_size());
1521
1522 /*
1523 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001524 * The paths are sort by NH first. in this case the the path with greater
1525 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001526 */
1527 fib_prefix_t pfx_1_2_3_4_s_32 = {
1528 .fp_len = 32,
1529 .fp_proto = FIB_PROTOCOL_IP4,
1530 .fp_addr = {
1531 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1532 },
1533 };
1534 fib_table_entry_path_add(fib_index,
1535 &pfx_1_2_3_4_s_32,
1536 FIB_SOURCE_API,
1537 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001538 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001539 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001540 tm->hw[0]->sw_if_index,
1541 ~0,
1542 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001543 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001544 FIB_ROUTE_PATH_FLAG_NONE);
1545 fei = fib_table_entry_path_add(fib_index,
1546 &pfx_1_2_3_4_s_32,
1547 FIB_SOURCE_API,
1548 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001549 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001550 &nh_12_12_12_12,
1551 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001552 ~0,
1553 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001554 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001555 FIB_ROUTE_PATH_FLAG_NONE);
1556
1557 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1558 dpo = fib_entry_contribute_ip_forwarding(fei);
1559 lb = load_balance_get(dpo->dpoi_index);
1560 FIB_TEST((lb->lb_n_buckets == 4),
1561 "1.2.3.4/32 LB has %d bucket",
1562 lb->lb_n_buckets);
1563
Neale Ranns3ee44042016-10-03 13:05:48 +01001564 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1565 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1566 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1567 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001568
Neale Ranns3ee44042016-10-03 13:05:48 +01001569 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1570 tm->hw[0]->sw_if_index,
1571 tm->hw[1]->sw_if_index),
1572 "RPF list for 1.2.3.4/32 contains both adjs");
1573
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001574
1575 /*
1576 * Unequal Cost load-balance. 4:1 ratio.
1577 * fits in a 16 bucket LB with ratio 13:3
1578 */
1579 fib_prefix_t pfx_1_2_3_5_s_32 = {
1580 .fp_len = 32,
1581 .fp_proto = FIB_PROTOCOL_IP4,
1582 .fp_addr = {
1583 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1584 },
1585 };
1586 fib_table_entry_path_add(fib_index,
1587 &pfx_1_2_3_5_s_32,
1588 FIB_SOURCE_API,
1589 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001590 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001591 &nh_12_12_12_12,
1592 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001593 ~0,
1594 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001595 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001596 FIB_ROUTE_PATH_FLAG_NONE);
1597 fei = fib_table_entry_path_add(fib_index,
1598 &pfx_1_2_3_5_s_32,
1599 FIB_SOURCE_API,
1600 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001601 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001602 &nh_10_10_10_1,
1603 tm->hw[0]->sw_if_index,
1604 ~0,
1605 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001606 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001607 FIB_ROUTE_PATH_FLAG_NONE);
1608
1609 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1610 dpo = fib_entry_contribute_ip_forwarding(fei);
1611 lb = load_balance_get(dpo->dpoi_index);
1612 FIB_TEST((lb->lb_n_buckets == 16),
1613 "1.2.3.5/32 LB has %d bucket",
1614 lb->lb_n_buckets);
1615
1616 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1617 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1618 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1619 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1620 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1621 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1622 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1623 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1624 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1625 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1626 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1627 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1628 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001629 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1630 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1631 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1632
1633 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1634 tm->hw[0]->sw_if_index,
1635 tm->hw[1]->sw_if_index),
1636 "RPF list for 1.2.3.4/32 contains both adjs");
1637
1638 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001639 * Test UCMP with a large weight skew - this produces load-balance objects with large
1640 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1641 * laso testing the LB in placce modify code when number of buckets is large.
1642 */
1643 fib_prefix_t pfx_6_6_6_6_s_32 = {
1644 .fp_len = 32,
1645 .fp_proto = FIB_PROTOCOL_IP4,
1646 .fp_addr = {
1647 /* 1.1.1.1/32 */
1648 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1649 },
1650 };
Neale Ranns81424992017-05-18 03:03:22 -07001651 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001652 .type = FT_LB_ADJ,
1653 .adj = {
1654 .adj = ai_01,
1655 },
1656 };
Neale Ranns81424992017-05-18 03:03:22 -07001657 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001658 .type = FT_LB_ADJ,
1659 .adj = {
1660 .adj = ai_02,
1661 },
1662 };
1663 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1664 .type = FT_LB_ADJ,
1665 .adj = {
1666 .adj = ai_12_12_12_12,
1667 },
1668 };
1669 fib_table_entry_update_one_path(fib_index,
1670 &pfx_6_6_6_6_s_32,
1671 FIB_SOURCE_API,
1672 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001673 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001674 &nh_10_10_10_1,
1675 tm->hw[0]->sw_if_index,
1676 ~0, // invalid fib index
1677 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001678 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001679 FIB_ROUTE_PATH_FLAG_NONE);
1680
1681 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1682 FIB_TEST(fib_test_validate_entry(fei,
1683 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1684 1,
Neale Ranns81424992017-05-18 03:03:22 -07001685 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001686 "6.6.6.6/32 via 10.10.10.1");
1687
1688 fib_table_entry_path_add(fib_index,
1689 &pfx_6_6_6_6_s_32,
1690 FIB_SOURCE_API,
1691 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001692 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001693 &nh_10_10_10_2,
1694 tm->hw[0]->sw_if_index,
1695 ~0, // invalid fib index
1696 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001697 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001698 FIB_ROUTE_PATH_FLAG_NONE);
1699
1700 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1701 FIB_TEST(fib_test_validate_entry(fei,
1702 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1703 64,
Neale Ranns81424992017-05-18 03:03:22 -07001704 &ip_o_10_10_10_2,
1705 &ip_o_10_10_10_2,
1706 &ip_o_10_10_10_2,
1707 &ip_o_10_10_10_2,
1708 &ip_o_10_10_10_2,
1709 &ip_o_10_10_10_2,
1710 &ip_o_10_10_10_2,
1711 &ip_o_10_10_10_2,
1712 &ip_o_10_10_10_2,
1713 &ip_o_10_10_10_2,
1714 &ip_o_10_10_10_2,
1715 &ip_o_10_10_10_2,
1716 &ip_o_10_10_10_2,
1717 &ip_o_10_10_10_2,
1718 &ip_o_10_10_10_2,
1719 &ip_o_10_10_10_2,
1720 &ip_o_10_10_10_2,
1721 &ip_o_10_10_10_2,
1722 &ip_o_10_10_10_2,
1723 &ip_o_10_10_10_2,
1724 &ip_o_10_10_10_2,
1725 &ip_o_10_10_10_2,
1726 &ip_o_10_10_10_2,
1727 &ip_o_10_10_10_2,
1728 &ip_o_10_10_10_2,
1729 &ip_o_10_10_10_2,
1730 &ip_o_10_10_10_2,
1731 &ip_o_10_10_10_2,
1732 &ip_o_10_10_10_2,
1733 &ip_o_10_10_10_2,
1734 &ip_o_10_10_10_2,
1735 &ip_o_10_10_10_2,
1736 &ip_o_10_10_10_2,
1737 &ip_o_10_10_10_2,
1738 &ip_o_10_10_10_2,
1739 &ip_o_10_10_10_2,
1740 &ip_o_10_10_10_2,
1741 &ip_o_10_10_10_2,
1742 &ip_o_10_10_10_2,
1743 &ip_o_10_10_10_2,
1744 &ip_o_10_10_10_2,
1745 &ip_o_10_10_10_2,
1746 &ip_o_10_10_10_2,
1747 &ip_o_10_10_10_2,
1748 &ip_o_10_10_10_2,
1749 &ip_o_10_10_10_2,
1750 &ip_o_10_10_10_2,
1751 &ip_o_10_10_10_2,
1752 &ip_o_10_10_10_2,
1753 &ip_o_10_10_10_2,
1754 &ip_o_10_10_10_2,
1755 &ip_o_10_10_10_2,
1756 &ip_o_10_10_10_2,
1757 &ip_o_10_10_10_2,
1758 &ip_o_10_10_10_2,
1759 &ip_o_10_10_10_2,
1760 &ip_o_10_10_10_2,
1761 &ip_o_10_10_10_2,
1762 &ip_o_10_10_10_2,
1763 &ip_o_10_10_10_2,
1764 &ip_o_10_10_10_2,
1765 &ip_o_10_10_10_2,
1766 &ip_o_10_10_10_2,
1767 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001768 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1769
1770 fib_table_entry_path_add(fib_index,
1771 &pfx_6_6_6_6_s_32,
1772 FIB_SOURCE_API,
1773 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001774 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001775 &nh_12_12_12_12,
1776 tm->hw[1]->sw_if_index,
1777 ~0, // invalid fib index
1778 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001779 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001780 FIB_ROUTE_PATH_FLAG_NONE);
1781
1782 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1783 FIB_TEST(fib_test_validate_entry(fei,
1784 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1785 128,
Neale Ranns81424992017-05-18 03:03:22 -07001786 &ip_o_10_10_10_1,
1787 &ip_o_10_10_10_2,
1788 &ip_o_10_10_10_2,
1789 &ip_o_10_10_10_2,
1790 &ip_o_10_10_10_2,
1791 &ip_o_10_10_10_2,
1792 &ip_o_10_10_10_2,
1793 &ip_o_10_10_10_2,
1794 &ip_o_10_10_10_2,
1795 &ip_o_10_10_10_2,
1796 &ip_o_10_10_10_2,
1797 &ip_o_10_10_10_2,
1798 &ip_o_10_10_10_2,
1799 &ip_o_10_10_10_2,
1800 &ip_o_10_10_10_2,
1801 &ip_o_10_10_10_2,
1802 &ip_o_10_10_10_2,
1803 &ip_o_10_10_10_2,
1804 &ip_o_10_10_10_2,
1805 &ip_o_10_10_10_2,
1806 &ip_o_10_10_10_2,
1807 &ip_o_10_10_10_2,
1808 &ip_o_10_10_10_2,
1809 &ip_o_10_10_10_2,
1810 &ip_o_10_10_10_2,
1811 &ip_o_10_10_10_2,
1812 &ip_o_10_10_10_2,
1813 &ip_o_10_10_10_2,
1814 &ip_o_10_10_10_2,
1815 &ip_o_10_10_10_2,
1816 &ip_o_10_10_10_2,
1817 &ip_o_10_10_10_2,
1818 &ip_o_10_10_10_2,
1819 &ip_o_10_10_10_2,
1820 &ip_o_10_10_10_2,
1821 &ip_o_10_10_10_2,
1822 &ip_o_10_10_10_2,
1823 &ip_o_10_10_10_2,
1824 &ip_o_10_10_10_2,
1825 &ip_o_10_10_10_2,
1826 &ip_o_10_10_10_2,
1827 &ip_o_10_10_10_2,
1828 &ip_o_10_10_10_2,
1829 &ip_o_10_10_10_2,
1830 &ip_o_10_10_10_2,
1831 &ip_o_10_10_10_2,
1832 &ip_o_10_10_10_2,
1833 &ip_o_10_10_10_2,
1834 &ip_o_10_10_10_2,
1835 &ip_o_10_10_10_2,
1836 &ip_o_10_10_10_2,
1837 &ip_o_10_10_10_2,
1838 &ip_o_10_10_10_2,
1839 &ip_o_10_10_10_2,
1840 &ip_o_10_10_10_2,
1841 &ip_o_10_10_10_2,
1842 &ip_o_10_10_10_2,
1843 &ip_o_10_10_10_2,
1844 &ip_o_10_10_10_2,
1845 &ip_o_10_10_10_2,
1846 &ip_o_10_10_10_2,
1847 &ip_o_10_10_10_2,
1848 &ip_o_10_10_10_2,
1849 &ip_o_10_10_10_2,
1850 &ip_o_10_10_10_2,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001851 &ip_6_6_6_6_o_12_12_12_12,
1852 &ip_6_6_6_6_o_12_12_12_12,
1853 &ip_6_6_6_6_o_12_12_12_12,
1854 &ip_6_6_6_6_o_12_12_12_12,
1855 &ip_6_6_6_6_o_12_12_12_12,
1856 &ip_6_6_6_6_o_12_12_12_12,
1857 &ip_6_6_6_6_o_12_12_12_12,
1858 &ip_6_6_6_6_o_12_12_12_12,
1859 &ip_6_6_6_6_o_12_12_12_12,
1860 &ip_6_6_6_6_o_12_12_12_12,
1861 &ip_6_6_6_6_o_12_12_12_12,
1862 &ip_6_6_6_6_o_12_12_12_12,
1863 &ip_6_6_6_6_o_12_12_12_12,
1864 &ip_6_6_6_6_o_12_12_12_12,
1865 &ip_6_6_6_6_o_12_12_12_12,
1866 &ip_6_6_6_6_o_12_12_12_12,
1867 &ip_6_6_6_6_o_12_12_12_12,
1868 &ip_6_6_6_6_o_12_12_12_12,
1869 &ip_6_6_6_6_o_12_12_12_12,
1870 &ip_6_6_6_6_o_12_12_12_12,
1871 &ip_6_6_6_6_o_12_12_12_12,
1872 &ip_6_6_6_6_o_12_12_12_12,
1873 &ip_6_6_6_6_o_12_12_12_12,
1874 &ip_6_6_6_6_o_12_12_12_12,
1875 &ip_6_6_6_6_o_12_12_12_12,
1876 &ip_6_6_6_6_o_12_12_12_12,
1877 &ip_6_6_6_6_o_12_12_12_12,
1878 &ip_6_6_6_6_o_12_12_12_12,
1879 &ip_6_6_6_6_o_12_12_12_12,
1880 &ip_6_6_6_6_o_12_12_12_12,
1881 &ip_6_6_6_6_o_12_12_12_12,
1882 &ip_6_6_6_6_o_12_12_12_12,
1883 &ip_6_6_6_6_o_12_12_12_12,
1884 &ip_6_6_6_6_o_12_12_12_12,
1885 &ip_6_6_6_6_o_12_12_12_12,
1886 &ip_6_6_6_6_o_12_12_12_12,
1887 &ip_6_6_6_6_o_12_12_12_12,
1888 &ip_6_6_6_6_o_12_12_12_12,
1889 &ip_6_6_6_6_o_12_12_12_12,
1890 &ip_6_6_6_6_o_12_12_12_12,
1891 &ip_6_6_6_6_o_12_12_12_12,
1892 &ip_6_6_6_6_o_12_12_12_12,
1893 &ip_6_6_6_6_o_12_12_12_12,
1894 &ip_6_6_6_6_o_12_12_12_12,
1895 &ip_6_6_6_6_o_12_12_12_12,
1896 &ip_6_6_6_6_o_12_12_12_12,
1897 &ip_6_6_6_6_o_12_12_12_12,
1898 &ip_6_6_6_6_o_12_12_12_12,
1899 &ip_6_6_6_6_o_12_12_12_12,
1900 &ip_6_6_6_6_o_12_12_12_12,
1901 &ip_6_6_6_6_o_12_12_12_12,
1902 &ip_6_6_6_6_o_12_12_12_12,
1903 &ip_6_6_6_6_o_12_12_12_12,
1904 &ip_6_6_6_6_o_12_12_12_12,
1905 &ip_6_6_6_6_o_12_12_12_12,
1906 &ip_6_6_6_6_o_12_12_12_12,
1907 &ip_6_6_6_6_o_12_12_12_12,
1908 &ip_6_6_6_6_o_12_12_12_12,
1909 &ip_6_6_6_6_o_12_12_12_12,
1910 &ip_6_6_6_6_o_12_12_12_12,
1911 &ip_6_6_6_6_o_12_12_12_12,
1912 &ip_6_6_6_6_o_12_12_12_12,
1913 &ip_6_6_6_6_o_12_12_12_12),
1914 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1915
1916 fib_table_entry_path_remove(fib_index,
1917 &pfx_6_6_6_6_s_32,
1918 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001919 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001920 &nh_12_12_12_12,
1921 tm->hw[1]->sw_if_index,
1922 ~0, // invalid fib index
1923 100,
1924 FIB_ROUTE_PATH_FLAG_NONE);
1925
1926 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1927 FIB_TEST(fib_test_validate_entry(fei,
1928 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1929 64,
Neale Ranns81424992017-05-18 03:03:22 -07001930 &ip_o_10_10_10_2,
1931 &ip_o_10_10_10_2,
1932 &ip_o_10_10_10_2,
1933 &ip_o_10_10_10_2,
1934 &ip_o_10_10_10_2,
1935 &ip_o_10_10_10_2,
1936 &ip_o_10_10_10_2,
1937 &ip_o_10_10_10_2,
1938 &ip_o_10_10_10_2,
1939 &ip_o_10_10_10_2,
1940 &ip_o_10_10_10_2,
1941 &ip_o_10_10_10_2,
1942 &ip_o_10_10_10_2,
1943 &ip_o_10_10_10_2,
1944 &ip_o_10_10_10_2,
1945 &ip_o_10_10_10_2,
1946 &ip_o_10_10_10_2,
1947 &ip_o_10_10_10_2,
1948 &ip_o_10_10_10_2,
1949 &ip_o_10_10_10_2,
1950 &ip_o_10_10_10_2,
1951 &ip_o_10_10_10_2,
1952 &ip_o_10_10_10_2,
1953 &ip_o_10_10_10_2,
1954 &ip_o_10_10_10_2,
1955 &ip_o_10_10_10_2,
1956 &ip_o_10_10_10_2,
1957 &ip_o_10_10_10_2,
1958 &ip_o_10_10_10_2,
1959 &ip_o_10_10_10_2,
1960 &ip_o_10_10_10_2,
1961 &ip_o_10_10_10_2,
1962 &ip_o_10_10_10_2,
1963 &ip_o_10_10_10_2,
1964 &ip_o_10_10_10_2,
1965 &ip_o_10_10_10_2,
1966 &ip_o_10_10_10_2,
1967 &ip_o_10_10_10_2,
1968 &ip_o_10_10_10_2,
1969 &ip_o_10_10_10_2,
1970 &ip_o_10_10_10_2,
1971 &ip_o_10_10_10_2,
1972 &ip_o_10_10_10_2,
1973 &ip_o_10_10_10_2,
1974 &ip_o_10_10_10_2,
1975 &ip_o_10_10_10_2,
1976 &ip_o_10_10_10_2,
1977 &ip_o_10_10_10_2,
1978 &ip_o_10_10_10_2,
1979 &ip_o_10_10_10_2,
1980 &ip_o_10_10_10_2,
1981 &ip_o_10_10_10_2,
1982 &ip_o_10_10_10_2,
1983 &ip_o_10_10_10_2,
1984 &ip_o_10_10_10_2,
1985 &ip_o_10_10_10_2,
1986 &ip_o_10_10_10_2,
1987 &ip_o_10_10_10_2,
1988 &ip_o_10_10_10_2,
1989 &ip_o_10_10_10_2,
1990 &ip_o_10_10_10_2,
1991 &ip_o_10_10_10_2,
1992 &ip_o_10_10_10_2,
1993 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001994 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1995
1996 fib_table_entry_path_remove(fib_index,
1997 &pfx_6_6_6_6_s_32,
1998 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001999 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00002000 &nh_10_10_10_2,
2001 tm->hw[0]->sw_if_index,
2002 ~0, // invalid fib index
2003 100,
2004 FIB_ROUTE_PATH_FLAG_NONE);
2005
2006 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2007 FIB_TEST(fib_test_validate_entry(fei,
2008 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2009 1,
Neale Ranns81424992017-05-18 03:03:22 -07002010 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00002011 "6.6.6.6/32 via 10.10.10.1");
2012
2013 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2014
2015 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01002016 * A recursive via the two unequal cost entries
2017 */
2018 fib_prefix_t bgp_44_s_32 = {
2019 .fp_len = 32,
2020 .fp_proto = FIB_PROTOCOL_IP4,
2021 .fp_addr = {
2022 /* 200.200.200.201/32 */
2023 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2024 },
2025 };
2026 fei = fib_table_entry_path_add(fib_index,
2027 &bgp_44_s_32,
2028 FIB_SOURCE_API,
2029 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002030 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01002031 &pfx_1_2_3_4_s_32.fp_addr,
2032 ~0,
2033 fib_index,
2034 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002035 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002036 FIB_ROUTE_PATH_FLAG_NONE);
2037 fei = fib_table_entry_path_add(fib_index,
2038 &bgp_44_s_32,
2039 FIB_SOURCE_API,
2040 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002041 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01002042 &pfx_1_2_3_5_s_32.fp_addr,
2043 ~0,
2044 fib_index,
2045 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002046 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002047 FIB_ROUTE_PATH_FLAG_NONE);
2048
2049 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2050 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2051 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2052 tm->hw[0]->sw_if_index,
2053 tm->hw[1]->sw_if_index),
2054 "RPF list for 1.2.3.4/32 contains both adjs");
2055
2056 /*
2057 * test the uRPF check functions
2058 */
Neale Ranns948e00f2016-10-20 13:39:34 +01002059 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01002060 index_t urpfi;
2061
2062 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2063 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2064
2065 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2066 "uRPF check for 68.68.68.68/32 on %d OK",
2067 tm->hw[0]->sw_if_index);
2068 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2069 "uRPF check for 68.68.68.68/32 on %d OK",
2070 tm->hw[1]->sw_if_index);
2071 FIB_TEST(!fib_urpf_check(urpfi, 99),
2072 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2073 99);
2074 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002075
2076 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002077 &bgp_44_s_32,
2078 FIB_SOURCE_API);
2079 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002080 &pfx_1_2_3_5_s_32,
2081 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002082 fib_table_entry_delete(fib_index,
2083 &pfx_1_2_3_4_s_32,
2084 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002085
2086 /*
2087 * Add a recursive route:
2088 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2089 */
2090 fib_prefix_t bgp_201_pfx = {
2091 .fp_len = 32,
2092 .fp_proto = FIB_PROTOCOL_IP4,
2093 .fp_addr = {
2094 /* 200.200.200.201/32 */
2095 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2096 },
2097 };
2098 /* via 1.1.1.200 */
2099 fib_prefix_t pfx_1_1_1_200_s_32 = {
2100 .fp_len = 32,
2101 .fp_proto = FIB_PROTOCOL_IP4,
2102 .fp_addr = {
2103 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2104 },
2105 };
2106
Neale Ranns57b58602017-07-15 07:37:25 -07002107 fei = fib_table_entry_path_add(fib_index,
2108 &bgp_201_pfx,
2109 FIB_SOURCE_API,
2110 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002111 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002112 &pfx_1_1_1_200_s_32.fp_addr,
2113 ~0, // no index provided.
2114 fib_index, // nexthop in same fib as route
2115 1,
2116 NULL,
2117 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002118
Neale Ranns57b58602017-07-15 07:37:25 -07002119 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2120 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002121
2122 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2123 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2124 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002125 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2126 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002127
2128 /*
2129 * +2 entry (BGP & RR) and +1 shared-path-list
2130 */
2131 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2132 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002133 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002134 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002135 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002136 fib_entry_pool_size());
2137
2138 /*
2139 * insert a route that covers the missing 1.1.1.2/32. we epxect
2140 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2141 */
2142 fib_prefix_t pfx_1_1_1_0_s_24 = {
2143 .fp_len = 24,
2144 .fp_proto = FIB_PROTOCOL_IP4,
2145 .fp_addr = {
2146 /* 1.1.1.0/24 */
2147 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2148 },
2149 };
2150
2151 fib_table_entry_path_add(fib_index,
2152 &pfx_1_1_1_0_s_24,
2153 FIB_SOURCE_API,
2154 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002155 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002156 &nh_10_10_10_1,
2157 tm->hw[0]->sw_if_index,
2158 ~0, // invalid fib index
2159 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002160 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002161 FIB_ROUTE_PATH_FLAG_NONE);
2162 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2163 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2164 ai = fib_entry_get_adj(fei);
2165 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2166 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2167 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2168 ai = fib_entry_get_adj(fei);
2169 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2170 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2171 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2172 ai = fib_entry_get_adj(fei);
2173 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2174
2175 /*
2176 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2177 */
2178 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2179 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002180 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002181 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002182 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002183 fib_entry_pool_size());
2184
2185 /*
2186 * the recursive adj for 200.200.200.200 should be updated.
2187 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002188 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2189 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2190 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2191 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2192 tm->hw[0]->sw_if_index),
2193 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002194
2195 /*
2196 * insert a more specific route than 1.1.1.0/24 that also covers the
2197 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2198 * 200.200.200.200 to resolve through it.
2199 */
2200 fib_prefix_t pfx_1_1_1_0_s_28 = {
2201 .fp_len = 28,
2202 .fp_proto = FIB_PROTOCOL_IP4,
2203 .fp_addr = {
2204 /* 1.1.1.0/24 */
2205 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2206 },
2207 };
2208
2209 fib_table_entry_path_add(fib_index,
2210 &pfx_1_1_1_0_s_28,
2211 FIB_SOURCE_API,
2212 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002213 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002214 &nh_10_10_10_2,
2215 tm->hw[0]->sw_if_index,
2216 ~0, // invalid fib index
2217 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002218 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002219 FIB_ROUTE_PATH_FLAG_NONE);
2220 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2221 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2222 ai = fib_entry_get_adj(fei);
2223 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2224
2225 /*
2226 * +1 entry. +1 shared path-list
2227 */
2228 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2229 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002230 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002231 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002232 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002233 fib_entry_pool_size());
2234
2235 /*
2236 * the recursive adj for 200.200.200.200 should be updated.
2237 * 200.200.200.201 remains unchanged.
2238 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002239 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2240 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002241
2242 /*
2243 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2244 */
2245 fib_table_entry_path_remove(fib_index,
2246 &pfx_1_1_1_0_s_28,
2247 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002248 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002249 &nh_10_10_10_2,
2250 tm->hw[0]->sw_if_index,
2251 ~0,
2252 1,
2253 FIB_ROUTE_PATH_FLAG_NONE);
2254 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2255 FIB_NODE_INDEX_INVALID),
2256 "1.1.1.0/28 removed");
2257 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2258 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2259 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002260 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2261 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002262
2263 /*
2264 * -1 entry. -1 shared path-list
2265 */
2266 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2267 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002268 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002269 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002270 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002271 fib_entry_pool_size());
2272
2273 /*
2274 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2275 */
2276 fib_table_entry_path_remove(fib_index,
2277 &pfx_1_1_1_0_s_24,
2278 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002279 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002280 &nh_10_10_10_1,
2281 tm->hw[0]->sw_if_index,
2282 ~0,
2283 1,
2284 FIB_ROUTE_PATH_FLAG_NONE);
2285 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2286 FIB_NODE_INDEX_INVALID),
2287 "1.1.1.0/24 removed");
2288
2289 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2290 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2291 "1.1.1.2/32 route is DROP");
Neale Ranns57b58602017-07-15 07:37:25 -07002292 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002293 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2294 "1.1.1.200/32 route is DROP");
2295
Neale Ranns57b58602017-07-15 07:37:25 -07002296 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2297 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2298 "201 is drop");
2299 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2300 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2301 "200 is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002302
2303 /*
2304 * -1 entry
2305 */
2306 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2307 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002308 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002309 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002310 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002311 fib_entry_pool_size());
2312
2313 /*
2314 * insert the missing 1.1.1.2/32
2315 */
2316 fei = fib_table_entry_path_add(fib_index,
2317 &pfx_1_1_1_2_s_32,
2318 FIB_SOURCE_API,
2319 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002320 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002321 &nh_10_10_10_1,
2322 tm->hw[0]->sw_if_index,
2323 ~0, // invalid fib index
2324 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002325 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002326 FIB_ROUTE_PATH_FLAG_NONE);
2327 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2328 ai = fib_entry_get_adj(fei);
2329 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2330
Neale Ranns57b58602017-07-15 07:37:25 -07002331 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2332 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2333 "201 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01002334 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002335
2336 /*
2337 * no change. 1.1.1.2/32 was already there RR sourced.
2338 */
2339 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2340 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002341 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002342 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002343 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002344 fib_entry_pool_size());
2345
2346 /*
Neale Ranns57b58602017-07-15 07:37:25 -07002347 * give 201 a resolved path.
2348 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2349 * only the latter contributes forwarding.
2350 */
2351 fei = fib_table_entry_path_add(fib_index,
2352 &bgp_201_pfx,
2353 FIB_SOURCE_API,
2354 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002355 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002356 &pfx_1_1_1_2_s_32.fp_addr,
2357 ~0,
2358 fib_index,
2359 1,
2360 NULL,
2361 FIB_ROUTE_PATH_FLAG_NONE);
2362 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2363 fib_table_entry_path_remove(fib_index,
2364 &bgp_201_pfx,
2365 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002366 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002367 &pfx_1_1_1_2_s_32.fp_addr,
2368 ~0,
2369 fib_index,
2370 1,
2371 FIB_ROUTE_PATH_FLAG_NONE);
2372
2373 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002374 * remove 200.200.200.201/32 which does not have a valid via FIB
2375 */
2376 fib_table_entry_path_remove(fib_index,
2377 &bgp_201_pfx,
2378 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002379 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002380 &pfx_1_1_1_200_s_32.fp_addr,
2381 ~0, // no index provided.
2382 fib_index,
2383 1,
2384 FIB_ROUTE_PATH_FLAG_NONE);
2385
2386 /*
2387 * -2 entries (BGP and RR). -1 shared path-list;
2388 */
2389 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2390 FIB_NODE_INDEX_INVALID),
2391 "200.200.200.201/32 removed");
2392 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2393 FIB_NODE_INDEX_INVALID),
2394 "1.1.1.200/32 removed");
2395
2396 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2397 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002398 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002399 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002400 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002401 fib_entry_pool_size());
2402
2403 /*
2404 * remove 200.200.200.200/32 which does have a valid via FIB
2405 */
2406 fib_table_entry_path_remove(fib_index,
2407 &bgp_200_pfx,
2408 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002409 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002410 &pfx_1_1_1_2_s_32.fp_addr,
2411 ~0, // no index provided.
2412 fib_index,
2413 1,
2414 FIB_ROUTE_PATH_FLAG_NONE);
2415
2416 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2417 FIB_NODE_INDEX_INVALID),
2418 "200.200.200.200/32 removed");
2419 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2420 FIB_NODE_INDEX_INVALID),
2421 "1.1.1.2/32 still present");
2422
2423 /*
2424 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2425 */
2426 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2427 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002428 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002429 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002430 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002431 fib_entry_pool_size());
2432
2433 /*
2434 * A recursive prefix that has a 2 path load-balance.
2435 * It also shares a next-hop with other BGP prefixes and hence
2436 * test the ref counting of RR sourced prefixes and 2 level LB.
2437 */
2438 const fib_prefix_t bgp_102 = {
2439 .fp_len = 32,
2440 .fp_proto = FIB_PROTOCOL_IP4,
2441 .fp_addr = {
2442 /* 100.100.100.101/32 */
2443 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2444 },
2445 };
2446 fib_table_entry_path_add(fib_index,
2447 &bgp_102,
2448 FIB_SOURCE_API,
2449 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002450 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002451 &pfx_1_1_1_1_s_32.fp_addr,
2452 ~0, // no index provided.
2453 fib_index, // same as route
2454 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002455 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002456 FIB_ROUTE_PATH_FLAG_NONE);
2457 fib_table_entry_path_add(fib_index,
2458 &bgp_102,
2459 FIB_SOURCE_API,
2460 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002461 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002462 &pfx_1_1_1_2_s_32.fp_addr,
2463 ~0, // no index provided.
2464 fib_index, // same as route's FIB
2465 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002466 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002467 FIB_ROUTE_PATH_FLAG_NONE);
2468 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2469 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2470 dpo = fib_entry_contribute_ip_forwarding(fei);
2471
2472 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2473 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2474 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2475 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2476
2477 lb = load_balance_get(dpo->dpoi_index);
2478 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2479 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2480 "First via 10.10.10.1");
2481 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2482 "Second via 10.10.10.1");
2483
2484 fib_table_entry_path_remove(fib_index,
2485 &bgp_102,
2486 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002487 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002488 &pfx_1_1_1_1_s_32.fp_addr,
2489 ~0, // no index provided.
2490 fib_index, // same as route's FIB
2491 1,
2492 FIB_ROUTE_PATH_FLAG_NONE);
2493 fib_table_entry_path_remove(fib_index,
2494 &bgp_102,
2495 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002496 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002497 &pfx_1_1_1_2_s_32.fp_addr,
2498 ~0, // no index provided.
2499 fib_index, // same as route's FIB
2500 1,
2501 FIB_ROUTE_PATH_FLAG_NONE);
2502 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2503 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2504
2505 /*
2506 * remove the remaining recursives
2507 */
2508 fib_table_entry_path_remove(fib_index,
2509 &bgp_100_pfx,
2510 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002511 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002512 &pfx_1_1_1_1_s_32.fp_addr,
2513 ~0, // no index provided.
2514 fib_index, // same as route's FIB
2515 1,
2516 FIB_ROUTE_PATH_FLAG_NONE);
2517 fib_table_entry_path_remove(fib_index,
2518 &bgp_101_pfx,
2519 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002520 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002521 &pfx_1_1_1_1_s_32.fp_addr,
2522 ~0, // no index provided.
2523 fib_index, // same as route's FIB
2524 1,
2525 FIB_ROUTE_PATH_FLAG_NONE);
2526 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2527 FIB_NODE_INDEX_INVALID),
2528 "100.100.100.100/32 removed");
2529 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2530 FIB_NODE_INDEX_INVALID),
2531 "100.100.100.101/32 removed");
2532
2533 /*
2534 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2535 */
2536 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2537 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002538 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002539 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002540 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002541 fib_entry_pool_size());
2542
2543 /*
2544 * Add a recursive route via a connected cover, using an adj-fib that does exist
2545 */
2546 fib_table_entry_path_add(fib_index,
2547 &bgp_200_pfx,
2548 FIB_SOURCE_API,
2549 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002550 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002551 &nh_10_10_10_1,
2552 ~0, // no index provided.
2553 fib_index, // Same as route's FIB
2554 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002555 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002556 FIB_ROUTE_PATH_FLAG_NONE);
2557
2558 /*
2559 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2560 */
2561 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2562 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002563 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002564 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002565 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002566 fib_entry_pool_size());
2567
2568 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2569 dpo = fib_entry_contribute_ip_forwarding(fei);
2570
2571 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2572 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2573
2574 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2575 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2576
2577 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2578 "Flags set on RR via existing attached");
2579
2580 /*
2581 * Add a recursive route via a connected cover, using and adj-fib that does
2582 * not exist
2583 */
2584 ip46_address_t nh_10_10_10_3 = {
2585 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2586 };
2587 fib_prefix_t pfx_10_10_10_3 = {
2588 .fp_len = 32,
2589 .fp_proto = FIB_PROTOCOL_IP4,
2590 .fp_addr = nh_10_10_10_3,
2591 };
2592
2593 fib_table_entry_path_add(fib_index,
2594 &bgp_201_pfx,
2595 FIB_SOURCE_API,
2596 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002597 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002598 &nh_10_10_10_3,
2599 ~0, // no index provided.
2600 fib_index,
2601 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002602 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002603 FIB_ROUTE_PATH_FLAG_NONE);
2604
2605 /*
2606 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2607 * one unshared non-recursive via 10.10.10.3
2608 */
2609 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2610 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002611 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002612 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002613 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002614 fib_entry_pool_size());
2615
2616 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002617 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002618 &nh_10_10_10_3,
2619 tm->hw[0]->sw_if_index);
2620
2621 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2622 dpo = fib_entry_contribute_ip_forwarding(fei);
2623 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2624 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2625
2626 ai = fib_entry_get_adj(fei);
2627 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2628 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2629 fib_entry_get_flags(fei)),
2630 "Flags set on RR via non-existing attached");
2631
2632 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2633 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2634
2635 adj_unlock(ai_03);
2636
2637 /*
2638 * remove the recursives
2639 */
2640 fib_table_entry_path_remove(fib_index,
2641 &bgp_200_pfx,
2642 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002643 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002644 &nh_10_10_10_1,
2645 ~0, // no index provided.
2646 fib_index, // same as route's FIB
2647 1,
2648 FIB_ROUTE_PATH_FLAG_NONE);
2649 fib_table_entry_path_remove(fib_index,
2650 &bgp_201_pfx,
2651 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002652 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002653 &nh_10_10_10_3,
2654 ~0, // no index provided.
2655 fib_index, // same as route's FIB
2656 1,
2657 FIB_ROUTE_PATH_FLAG_NONE);
2658
2659 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2660 FIB_NODE_INDEX_INVALID),
2661 "200.200.200.201/32 removed");
2662 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2663 FIB_NODE_INDEX_INVALID),
2664 "200.200.200.200/32 removed");
2665 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2666 FIB_NODE_INDEX_INVALID),
2667 "10.10.10.3/32 removed");
2668
2669 /*
2670 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2671 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2672 */
2673 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2674 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002675 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002676 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002677 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002678 fib_entry_pool_size());
2679
2680
2681 /*
2682 * RECURSION LOOPS
2683 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2684 */
2685 fib_prefix_t pfx_5_5_5_5_s_32 = {
2686 .fp_len = 32,
2687 .fp_proto = FIB_PROTOCOL_IP4,
2688 .fp_addr = {
2689 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2690 },
2691 };
2692 fib_prefix_t pfx_5_5_5_6_s_32 = {
2693 .fp_len = 32,
2694 .fp_proto = FIB_PROTOCOL_IP4,
2695 .fp_addr = {
2696 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2697 },
2698 };
2699 fib_prefix_t pfx_5_5_5_7_s_32 = {
2700 .fp_len = 32,
2701 .fp_proto = FIB_PROTOCOL_IP4,
2702 .fp_addr = {
2703 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2704 },
2705 };
2706
2707 fib_table_entry_path_add(fib_index,
2708 &pfx_5_5_5_5_s_32,
2709 FIB_SOURCE_API,
2710 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002711 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002712 &pfx_5_5_5_6_s_32.fp_addr,
2713 ~0, // no index provided.
2714 fib_index,
2715 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002716 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002717 FIB_ROUTE_PATH_FLAG_NONE);
2718 fib_table_entry_path_add(fib_index,
2719 &pfx_5_5_5_6_s_32,
2720 FIB_SOURCE_API,
2721 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002722 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002723 &pfx_5_5_5_7_s_32.fp_addr,
2724 ~0, // no index provided.
2725 fib_index,
2726 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002727 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002728 FIB_ROUTE_PATH_FLAG_NONE);
2729 fib_table_entry_path_add(fib_index,
2730 &pfx_5_5_5_7_s_32,
2731 FIB_SOURCE_API,
2732 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002733 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002734 &pfx_5_5_5_5_s_32.fp_addr,
2735 ~0, // no index provided.
2736 fib_index,
2737 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002738 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002739 FIB_ROUTE_PATH_FLAG_NONE);
2740 /*
2741 * +3 entries, +3 shared path-list
2742 */
2743 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2744 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002745 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002746 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002747 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002748 fib_entry_pool_size());
2749
2750 /*
2751 * All the entries have only looped paths, so they are all drop
2752 */
2753 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2754 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2755 "LB for 5.5.5.7/32 is via adj for DROP");
2756 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2757 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2758 "LB for 5.5.5.5/32 is via adj for DROP");
2759 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2760 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2761 "LB for 5.5.5.6/32 is via adj for DROP");
2762
2763 /*
2764 * provide 5.5.5.6/32 with alternate path.
2765 * this will allow only 5.5.5.6/32 to forward with this path, the others
2766 * are still drop since the loop is still present.
2767 */
2768 fib_table_entry_path_add(fib_index,
2769 &pfx_5_5_5_6_s_32,
2770 FIB_SOURCE_API,
2771 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002772 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002773 &nh_10_10_10_1,
2774 tm->hw[0]->sw_if_index,
2775 ~0,
2776 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002777 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002778 FIB_ROUTE_PATH_FLAG_NONE);
2779
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002780 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2781 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2782
2783 lb = load_balance_get(dpo1->dpoi_index);
2784 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2785
2786 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2787 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2788 FIB_TEST((ai_01 == dpo2->dpoi_index),
2789 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2790
2791 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2792 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2793 "LB for 5.5.5.7/32 is via adj for DROP");
2794 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2795 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2796 "LB for 5.5.5.5/32 is via adj for DROP");
2797
2798 /*
2799 * remove the alternate path for 5.5.5.6/32
2800 * back to all drop
2801 */
2802 fib_table_entry_path_remove(fib_index,
2803 &pfx_5_5_5_6_s_32,
2804 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002805 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002806 &nh_10_10_10_1,
2807 tm->hw[0]->sw_if_index,
2808 ~0,
2809 1,
2810 FIB_ROUTE_PATH_FLAG_NONE);
2811
2812 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2813 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2814 "LB for 5.5.5.7/32 is via adj for DROP");
2815 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2816 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2817 "LB for 5.5.5.5/32 is via adj for DROP");
2818 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2819 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2820 "LB for 5.5.5.6/32 is via adj for DROP");
2821
2822 /*
2823 * break the loop by giving 5.5.5.5/32 a new set of paths
2824 * expect all to forward via this new path.
2825 */
2826 fib_table_entry_update_one_path(fib_index,
2827 &pfx_5_5_5_5_s_32,
2828 FIB_SOURCE_API,
2829 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002830 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002831 &nh_10_10_10_1,
2832 tm->hw[0]->sw_if_index,
2833 ~0, // invalid fib index
2834 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002835 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002836 FIB_ROUTE_PATH_FLAG_NONE);
2837
2838 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2839 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2840 lb = load_balance_get(dpo1->dpoi_index);
2841 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2842
2843 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2844 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2845 FIB_TEST((ai_01 == dpo2->dpoi_index),
2846 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2847
2848 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2849 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2850
2851 lb = load_balance_get(dpo2->dpoi_index);
2852 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2853 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2854 "5.5.5.5.7 via 5.5.5.5");
2855
2856 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2857 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2858
2859 lb = load_balance_get(dpo1->dpoi_index);
2860 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2861 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2862 "5.5.5.5.6 via 5.5.5.7");
2863
2864 /*
2865 * revert back to the loop. so we can remove the prefixes with
2866 * the loop intact
2867 */
2868 fib_table_entry_update_one_path(fib_index,
2869 &pfx_5_5_5_5_s_32,
2870 FIB_SOURCE_API,
2871 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002872 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002873 &pfx_5_5_5_6_s_32.fp_addr,
2874 ~0, // no index provided.
2875 fib_index,
2876 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002877 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002878 FIB_ROUTE_PATH_FLAG_NONE);
2879
2880 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2881 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2882 "LB for 5.5.5.7/32 is via adj for DROP");
2883 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2884 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2885 "LB for 5.5.5.5/32 is via adj for DROP");
2886 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2887 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2888 "LB for 5.5.5.6/32 is via adj for DROP");
2889
2890 /*
2891 * remove all the 5.5.5.x/32 prefixes
2892 */
2893 fib_table_entry_path_remove(fib_index,
2894 &pfx_5_5_5_5_s_32,
2895 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002896 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002897 &pfx_5_5_5_6_s_32.fp_addr,
2898 ~0, // no index provided.
2899 fib_index, // same as route's FIB
2900 1,
2901 FIB_ROUTE_PATH_FLAG_NONE);
2902 fib_table_entry_path_remove(fib_index,
2903 &pfx_5_5_5_6_s_32,
2904 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002905 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002906 &pfx_5_5_5_7_s_32.fp_addr,
2907 ~0, // no index provided.
2908 fib_index, // same as route's FIB
2909 1,
2910 FIB_ROUTE_PATH_FLAG_NONE);
2911 fib_table_entry_path_remove(fib_index,
2912 &pfx_5_5_5_7_s_32,
2913 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002914 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002915 &pfx_5_5_5_5_s_32.fp_addr,
2916 ~0, // no index provided.
2917 fib_index, // same as route's FIB
2918 1,
2919 FIB_ROUTE_PATH_FLAG_NONE);
2920 fib_table_entry_path_remove(fib_index,
2921 &pfx_5_5_5_6_s_32,
2922 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002923 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002924 &nh_10_10_10_2,
2925 ~0, // no index provided.
2926 fib_index, // same as route's FIB
2927 1,
2928 FIB_ROUTE_PATH_FLAG_NONE);
2929
2930 /*
2931 * -3 entries, -3 shared path-list
2932 */
2933 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2934 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002935 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002936 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002937 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002938 fib_entry_pool_size());
2939
2940 /*
2941 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2942 */
2943 fib_table_entry_path_add(fib_index,
2944 &pfx_5_5_5_6_s_32,
2945 FIB_SOURCE_API,
2946 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002947 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002948 &pfx_5_5_5_6_s_32.fp_addr,
2949 ~0, // no index provided.
2950 fib_index,
2951 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002952 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002953 FIB_ROUTE_PATH_FLAG_NONE);
2954 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2955 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2956 "1-level 5.5.5.6/32 loop is via adj for DROP");
2957
2958 fib_table_entry_path_remove(fib_index,
2959 &pfx_5_5_5_6_s_32,
2960 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002961 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002962 &pfx_5_5_5_6_s_32.fp_addr,
2963 ~0, // no index provided.
2964 fib_index, // same as route's FIB
2965 1,
2966 FIB_ROUTE_PATH_FLAG_NONE);
2967 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2968 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2969 "1-level 5.5.5.6/32 loop is removed");
2970
2971 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002972 * A recursive route whose next-hop is covered by the prefix.
2973 * This would mean the via-fib, which inherits forwarding from its
2974 * cover, thus picks up forwarding from the prfix, which is via the
2975 * via-fib, and we have a loop.
2976 */
2977 fib_prefix_t pfx_23_23_23_0_s_24 = {
2978 .fp_len = 24,
2979 .fp_proto = FIB_PROTOCOL_IP4,
2980 .fp_addr = {
2981 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2982 },
2983 };
2984 fib_prefix_t pfx_23_23_23_23_s_32 = {
2985 .fp_len = 32,
2986 .fp_proto = FIB_PROTOCOL_IP4,
2987 .fp_addr = {
2988 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2989 },
2990 };
2991 fei = fib_table_entry_path_add(fib_index,
2992 &pfx_23_23_23_0_s_24,
2993 FIB_SOURCE_API,
2994 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002995 DPO_PROTO_IP4,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002996 &pfx_23_23_23_23_s_32.fp_addr,
2997 ~0, // recursive
2998 fib_index,
2999 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003000 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003001 FIB_ROUTE_PATH_FLAG_NONE);
3002 dpo = fib_entry_contribute_ip_forwarding(fei);
3003 FIB_TEST(load_balance_is_drop(dpo),
3004 "23.23.23.0/24 via covered is DROP");
3005 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3006
3007 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003008 * add-remove test. no change.
3009 */
3010 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3011 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003012 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003013 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003014 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003015 fib_entry_pool_size());
3016
3017 /*
Neale Ranns08b16482017-05-13 05:52:58 -07003018 * Make the default route recursive via a unknown next-hop. Thus the
3019 * next hop's cover would be the default route
3020 */
3021 fei = fib_table_entry_path_add(fib_index,
3022 &pfx_0_0_0_0_s_0,
3023 FIB_SOURCE_API,
3024 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003025 DPO_PROTO_IP4,
Neale Ranns08b16482017-05-13 05:52:58 -07003026 &pfx_23_23_23_23_s_32.fp_addr,
3027 ~0, // recursive
3028 fib_index,
3029 1,
3030 NULL,
3031 FIB_ROUTE_PATH_FLAG_NONE);
3032 dpo = fib_entry_contribute_ip_forwarding(fei);
3033 FIB_TEST(load_balance_is_drop(dpo),
3034 "0.0.0.0.0/0 via is DROP");
3035 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3036 "no resolving interface for looped 0.0.0.0/0");
3037
3038 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3039 dpo = fib_entry_contribute_ip_forwarding(fei);
3040 FIB_TEST(load_balance_is_drop(dpo),
3041 "23.23.23.23/32 via is DROP");
3042 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3043 "no resolving interface for looped 23.23.23.23/32");
3044
3045 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3046
3047 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003048 * A recursive route with recursion constraints.
3049 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3050 */
3051 fib_table_entry_path_add(fib_index,
3052 &bgp_200_pfx,
3053 FIB_SOURCE_API,
3054 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003055 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003056 &nh_1_1_1_1,
3057 ~0,
3058 fib_index,
3059 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003060 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003061 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3062
3063 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3064 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3065
3066 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3067 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3068
3069 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3070 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3071
3072 /*
3073 * save the load-balance. we expect it to be inplace modified
3074 */
3075 lb = load_balance_get(dpo1->dpoi_index);
3076
3077 /*
3078 * add a covering prefix for the via fib that would otherwise serve
3079 * as the resolving route when the host is removed
3080 */
3081 fib_table_entry_path_add(fib_index,
3082 &pfx_1_1_1_0_s_28,
3083 FIB_SOURCE_API,
3084 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003085 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003086 &nh_10_10_10_1,
3087 tm->hw[0]->sw_if_index,
3088 ~0, // invalid fib index
3089 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003090 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003091 FIB_ROUTE_PATH_FLAG_NONE);
3092 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3093 ai = fib_entry_get_adj(fei);
3094 FIB_TEST((ai == ai_01),
3095 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3096
3097 /*
3098 * remove the host via FIB - expect the BGP prefix to be drop
3099 */
3100 fib_table_entry_path_remove(fib_index,
3101 &pfx_1_1_1_1_s_32,
3102 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003103 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003104 &nh_10_10_10_1,
3105 tm->hw[0]->sw_if_index,
3106 ~0, // invalid fib index
3107 1,
3108 FIB_ROUTE_PATH_FLAG_NONE);
3109
3110 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3111 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3112
3113 /*
3114 * add the via-entry host reoute back. expect to resolve again
3115 */
3116 fib_table_entry_path_add(fib_index,
3117 &pfx_1_1_1_1_s_32,
3118 FIB_SOURCE_API,
3119 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003120 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003121 &nh_10_10_10_1,
3122 tm->hw[0]->sw_if_index,
3123 ~0, // invalid fib index
3124 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003125 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003126 FIB_ROUTE_PATH_FLAG_NONE);
3127 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3128 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3129
3130 /*
3131 * add another path for the recursive. it will then have 2.
3132 */
3133 fib_prefix_t pfx_1_1_1_3_s_32 = {
3134 .fp_len = 32,
3135 .fp_proto = FIB_PROTOCOL_IP4,
3136 .fp_addr = {
3137 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3138 },
3139 };
3140 fib_table_entry_path_add(fib_index,
3141 &pfx_1_1_1_3_s_32,
3142 FIB_SOURCE_API,
3143 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003144 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003145 &nh_10_10_10_2,
3146 tm->hw[0]->sw_if_index,
3147 ~0, // invalid fib index
3148 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003149 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003150 FIB_ROUTE_PATH_FLAG_NONE);
3151
3152 fib_table_entry_path_add(fib_index,
3153 &bgp_200_pfx,
3154 FIB_SOURCE_API,
3155 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003156 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003157 &pfx_1_1_1_3_s_32.fp_addr,
3158 ~0,
3159 fib_index,
3160 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003161 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003162 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3163
Neale Rannsf12a83f2017-04-18 09:09:40 -07003164 /*
3165 * add a bunch load more entries using this path combo so that we get
3166 * an LB-map created.
3167 */
3168#define N_P 128
3169 fib_prefix_t bgp_78s[N_P];
3170 for (ii = 0; ii < N_P; ii++)
3171 {
3172 bgp_78s[ii].fp_len = 32;
3173 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3174 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3175
3176
3177 fib_table_entry_path_add(fib_index,
3178 &bgp_78s[ii],
3179 FIB_SOURCE_API,
3180 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003181 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003182 &pfx_1_1_1_3_s_32.fp_addr,
3183 ~0,
3184 fib_index,
3185 1,
3186 NULL,
3187 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3188 fib_table_entry_path_add(fib_index,
3189 &bgp_78s[ii],
3190 FIB_SOURCE_API,
3191 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003192 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003193 &nh_1_1_1_1,
3194 ~0,
3195 fib_index,
3196 1,
3197 NULL,
3198 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3199 }
3200
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003201 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3202 dpo = fib_entry_contribute_ip_forwarding(fei);
3203
3204 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3205 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3206 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3207 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3208 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3209 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3210 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3211 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3212
3213 /*
3214 * expect the lb-map used by the recursive's load-balance is using both buckets
3215 */
3216 load_balance_map_t *lbm;
3217 index_t lbmi;
3218
3219 lb = load_balance_get(dpo->dpoi_index);
3220 lbmi = lb->lb_map;
3221 load_balance_map_lock(lbmi);
3222 lbm = load_balance_map_get(lbmi);
3223
3224 FIB_TEST(lbm->lbm_buckets[0] == 0,
3225 "LB maps's bucket 0 is %d",
3226 lbm->lbm_buckets[0]);
3227 FIB_TEST(lbm->lbm_buckets[1] == 1,
3228 "LB maps's bucket 1 is %d",
3229 lbm->lbm_buckets[1]);
3230
3231 /*
3232 * withdraw one of the /32 via-entrys.
3233 * that ECMP path will be unresolved and forwarding should continue on the
3234 * other available path. this is an iBGP PIC edge failover.
3235 * Test the forwarding changes without re-fetching the adj from the
3236 * recursive entry. this ensures its the same one that is updated; i.e. an
3237 * inplace-modify.
3238 */
3239 fib_table_entry_path_remove(fib_index,
3240 &pfx_1_1_1_1_s_32,
3241 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003242 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003243 &nh_10_10_10_1,
3244 tm->hw[0]->sw_if_index,
3245 ~0, // invalid fib index
3246 1,
3247 FIB_ROUTE_PATH_FLAG_NONE);
3248
Neale Rannsf12a83f2017-04-18 09:09:40 -07003249 /* suspend so the update walk kicks int */
3250 vlib_process_suspend(vlib_get_main(), 1e-5);
3251
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003252 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3253 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3254 "post PIC 200.200.200.200/32 was inplace modified");
3255
3256 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3257 "post PIC adj for 200.200.200.200/32 is recursive"
3258 " via adj for 1.1.1.3");
3259
3260 /*
3261 * the LB maps that was locked above should have been modified to remove
3262 * the path that was down, and thus its bucket points to a path that is
3263 * still up.
3264 */
3265 FIB_TEST(lbm->lbm_buckets[0] == 1,
3266 "LB maps's bucket 0 is %d",
3267 lbm->lbm_buckets[0]);
3268 FIB_TEST(lbm->lbm_buckets[1] == 1,
3269 "LB maps's bucket 1 is %d",
3270 lbm->lbm_buckets[1]);
3271
Neale Ranns994dab42017-04-18 12:56:45 -07003272 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003273
3274 /*
3275 * add it back. again
3276 */
3277 fib_table_entry_path_add(fib_index,
3278 &pfx_1_1_1_1_s_32,
3279 FIB_SOURCE_API,
3280 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003281 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003282 &nh_10_10_10_1,
3283 tm->hw[0]->sw_if_index,
3284 ~0, // invalid fib index
3285 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003286 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003287 FIB_ROUTE_PATH_FLAG_NONE);
3288
Neale Rannsf12a83f2017-04-18 09:09:40 -07003289 /* suspend so the update walk kicks in */
3290 vlib_process_suspend(vlib_get_main(), 1e-5);
3291
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003292 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3293 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3294 "via adj for 1.1.1.1");
3295 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3296 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3297 "via adj for 1.1.1.3");
3298
3299 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3300 dpo = fib_entry_contribute_ip_forwarding(fei);
3301 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3302 "post PIC 200.200.200.200/32 was inplace modified");
3303
3304 /*
3305 * add a 3rd path. this makes the LB 16 buckets.
3306 */
3307 fib_table_entry_path_add(fib_index,
3308 &bgp_200_pfx,
3309 FIB_SOURCE_API,
3310 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003311 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003312 &pfx_1_1_1_2_s_32.fp_addr,
3313 ~0,
3314 fib_index,
3315 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003316 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003317 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003318 for (ii = 0; ii < N_P; ii++)
3319 {
3320 fib_table_entry_path_add(fib_index,
3321 &bgp_78s[ii],
3322 FIB_SOURCE_API,
3323 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003324 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003325 &pfx_1_1_1_2_s_32.fp_addr,
3326 ~0,
3327 fib_index,
3328 1,
3329 NULL,
3330 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3331 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003332
3333 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3334 dpo = fib_entry_contribute_ip_forwarding(fei);
3335 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3336 "200.200.200.200/32 was inplace modified for 3rd path");
3337 FIB_TEST(16 == lb->lb_n_buckets,
3338 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3339
3340 lbmi = lb->lb_map;
3341 load_balance_map_lock(lbmi);
3342 lbm = load_balance_map_get(lbmi);
3343
3344 for (ii = 0; ii < 16; ii++)
3345 {
3346 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3347 "LB Map for 200.200.200.200/32 at %d is %d",
3348 ii, lbm->lbm_buckets[ii]);
3349 }
3350
3351 /*
3352 * trigger PIC by removing the first via-entry
3353 * the first 6 buckets of the map should map to the next 6
3354 */
3355 fib_table_entry_path_remove(fib_index,
3356 &pfx_1_1_1_1_s_32,
3357 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003358 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003359 &nh_10_10_10_1,
3360 tm->hw[0]->sw_if_index,
3361 ~0,
3362 1,
3363 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003364 /* suspend so the update walk kicks int */
3365 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003366
3367 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3368 dpo = fib_entry_contribute_ip_forwarding(fei);
3369 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3370 "200.200.200.200/32 was inplace modified for 3rd path");
3371 FIB_TEST(2 == lb->lb_n_buckets,
3372 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3373
3374 for (ii = 0; ii < 6; ii++)
3375 {
3376 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3377 "LB Map for 200.200.200.200/32 at %d is %d",
3378 ii, lbm->lbm_buckets[ii]);
3379 }
3380 for (ii = 6; ii < 16; ii++)
3381 {
3382 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3383 "LB Map for 200.200.200.200/32 at %d is %d",
3384 ii, lbm->lbm_buckets[ii]);
3385 }
Neale Ranns994dab42017-04-18 12:56:45 -07003386 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003387
3388 /*
3389 * tidy up
3390 */
3391 fib_table_entry_path_add(fib_index,
3392 &pfx_1_1_1_1_s_32,
3393 FIB_SOURCE_API,
3394 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003395 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003396 &nh_10_10_10_1,
3397 tm->hw[0]->sw_if_index,
3398 ~0,
3399 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003400 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003401 FIB_ROUTE_PATH_FLAG_NONE);
3402
Neale Rannsf12a83f2017-04-18 09:09:40 -07003403 for (ii = 0; ii < N_P; ii++)
3404 {
3405 fib_table_entry_delete(fib_index,
3406 &bgp_78s[ii],
3407 FIB_SOURCE_API);
3408 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3409 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3410 "%U removed",
3411 format_fib_prefix, &bgp_78s[ii]);
3412 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003413 fib_table_entry_path_remove(fib_index,
3414 &bgp_200_pfx,
3415 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003416 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003417 &pfx_1_1_1_2_s_32.fp_addr,
3418 ~0,
3419 fib_index,
3420 1,
3421 MPLS_LABEL_INVALID);
3422 fib_table_entry_path_remove(fib_index,
3423 &bgp_200_pfx,
3424 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003425 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003426 &nh_1_1_1_1,
3427 ~0,
3428 fib_index,
3429 1,
3430 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3431 fib_table_entry_path_remove(fib_index,
3432 &bgp_200_pfx,
3433 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003434 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003435 &pfx_1_1_1_3_s_32.fp_addr,
3436 ~0,
3437 fib_index,
3438 1,
3439 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3440 fib_table_entry_delete(fib_index,
3441 &pfx_1_1_1_3_s_32,
3442 FIB_SOURCE_API);
3443 fib_table_entry_delete(fib_index,
3444 &pfx_1_1_1_0_s_28,
3445 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003446 /* suspend so the update walk kicks int */
3447 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003448 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3449 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3450 "1.1.1.1/28 removed");
3451 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3452 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3453 "1.1.1.3/32 removed");
3454 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3455 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3456 "200.200.200.200/32 removed");
3457
3458 /*
3459 * add-remove test. no change.
3460 */
3461 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3462 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003463 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003464 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003465 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003466 fib_entry_pool_size());
3467
3468 /*
3469 * A route whose paths are built up iteratively and then removed
3470 * all at once
3471 */
3472 fib_prefix_t pfx_4_4_4_4_s_32 = {
3473 .fp_len = 32,
3474 .fp_proto = FIB_PROTOCOL_IP4,
3475 .fp_addr = {
3476 /* 4.4.4.4/32 */
3477 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3478 },
3479 };
3480
3481 fib_table_entry_path_add(fib_index,
3482 &pfx_4_4_4_4_s_32,
3483 FIB_SOURCE_API,
3484 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003485 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003486 &nh_10_10_10_1,
3487 tm->hw[0]->sw_if_index,
3488 ~0,
3489 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003490 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003491 FIB_ROUTE_PATH_FLAG_NONE);
3492 fib_table_entry_path_add(fib_index,
3493 &pfx_4_4_4_4_s_32,
3494 FIB_SOURCE_API,
3495 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003496 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003497 &nh_10_10_10_2,
3498 tm->hw[0]->sw_if_index,
3499 ~0,
3500 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003501 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003502 FIB_ROUTE_PATH_FLAG_NONE);
3503 fib_table_entry_path_add(fib_index,
3504 &pfx_4_4_4_4_s_32,
3505 FIB_SOURCE_API,
3506 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003507 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003508 &nh_10_10_10_3,
3509 tm->hw[0]->sw_if_index,
3510 ~0,
3511 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003512 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003513 FIB_ROUTE_PATH_FLAG_NONE);
3514 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3515 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3516 "4.4.4.4/32 present");
3517
3518 fib_table_entry_delete(fib_index,
3519 &pfx_4_4_4_4_s_32,
3520 FIB_SOURCE_API);
3521 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3522 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3523 "4.4.4.4/32 removed");
3524
3525 /*
3526 * add-remove test. no change.
3527 */
3528 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3529 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003530 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003531 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003532 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003533 fib_entry_pool_size());
3534
3535 /*
3536 * A route with multiple paths at once
3537 */
3538 fib_route_path_t *r_paths = NULL;
3539
3540 for (ii = 0; ii < 4; ii++)
3541 {
3542 fib_route_path_t r_path = {
Neale Rannsda78f952017-05-24 09:15:43 -07003543 .frp_proto = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003544 .frp_addr = {
3545 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3546 },
3547 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3548 .frp_weight = 1,
3549 .frp_fib_index = ~0,
3550 };
3551 vec_add1(r_paths, r_path);
3552 }
3553
3554 fib_table_entry_update(fib_index,
3555 &pfx_4_4_4_4_s_32,
3556 FIB_SOURCE_API,
3557 FIB_ENTRY_FLAG_NONE,
3558 r_paths);
3559
3560 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3561 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3562 dpo = fib_entry_contribute_ip_forwarding(fei);
3563
3564 lb = load_balance_get(dpo->dpoi_index);
3565 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3566
3567 fib_table_entry_delete(fib_index,
3568 &pfx_4_4_4_4_s_32,
3569 FIB_SOURCE_API);
3570 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3571 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3572 "4.4.4.4/32 removed");
3573 vec_free(r_paths);
3574
3575 /*
3576 * add-remove test. no change.
3577 */
3578 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3579 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003580 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003581 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003582 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003583 fib_entry_pool_size());
3584
3585 /*
3586 * A route deag route
3587 */
3588 fib_table_entry_path_add(fib_index,
3589 &pfx_4_4_4_4_s_32,
3590 FIB_SOURCE_API,
3591 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003592 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003593 &zero_addr,
3594 ~0,
3595 fib_index,
3596 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003597 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003598 FIB_ROUTE_PATH_FLAG_NONE);
3599
3600 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3601 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3602
3603 dpo = fib_entry_contribute_ip_forwarding(fei);
3604 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3605 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3606
3607 FIB_TEST((fib_index == lkd->lkd_fib_index),
3608 "4.4.4.4/32 is deag in %d %U",
3609 lkd->lkd_fib_index,
3610 format_dpo_id, dpo, 0);
3611
3612 fib_table_entry_delete(fib_index,
3613 &pfx_4_4_4_4_s_32,
3614 FIB_SOURCE_API);
3615 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3616 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3617 "4.4.4.4/32 removed");
3618 vec_free(r_paths);
3619
3620 /*
3621 * add-remove test. no change.
3622 */
3623 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3624 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003625 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003626 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003627 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003628 fib_entry_pool_size());
3629
3630 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003631 * Duplicate paths:
3632 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3633 */
3634 fib_prefix_t pfx_34_1_1_1_s_32 = {
3635 .fp_len = 32,
3636 .fp_proto = FIB_PROTOCOL_IP4,
3637 .fp_addr = {
3638 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3639 },
3640 };
3641 fib_prefix_t pfx_34_34_1_1_s_32 = {
3642 .fp_len = 32,
3643 .fp_proto = FIB_PROTOCOL_IP4,
3644 .fp_addr = {
3645 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3646 },
3647 };
3648 fei = fib_table_entry_path_add(fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -07003649 &pfx_34_34_1_1_s_32,
3650 FIB_SOURCE_API,
3651 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003652 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07003653 &nh_10_10_10_1,
3654 tm->hw[0]->sw_if_index,
3655 0,
3656 1,
3657 NULL,
3658 FIB_ROUTE_PATH_FLAG_NONE);
3659 fei = fib_table_entry_path_add(fib_index,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003660 &pfx_34_1_1_1_s_32,
3661 FIB_SOURCE_API,
3662 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003663 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003664 &pfx_34_34_1_1_s_32.fp_addr,
3665 ~0,
3666 fib_index,
3667 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003668 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003669 FIB_ROUTE_PATH_FLAG_NONE);
3670 fei = fib_table_entry_path_add(fib_index,
3671 &pfx_34_1_1_1_s_32,
3672 FIB_SOURCE_API,
3673 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003674 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003675 &pfx_34_34_1_1_s_32.fp_addr,
3676 ~0,
3677 fib_index,
3678 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003679 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003680 FIB_ROUTE_PATH_FLAG_NONE);
3681 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3682 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
Neale Ranns57b58602017-07-15 07:37:25 -07003683 fib_table_entry_delete(fib_index,
3684 &pfx_34_34_1_1_s_32,
3685 FIB_SOURCE_API);
Neale Rannsbcc889c2016-11-03 14:15:28 -07003686
3687 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003688 * CLEANUP
3689 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3690 * all of which are via 10.10.10.1, Itf1
3691 */
3692 fib_table_entry_path_remove(fib_index,
3693 &pfx_1_1_1_2_s_32,
3694 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003695 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003696 &nh_10_10_10_1,
3697 tm->hw[0]->sw_if_index,
3698 ~0,
3699 1,
3700 FIB_ROUTE_PATH_FLAG_NONE);
3701 fib_table_entry_path_remove(fib_index,
3702 &pfx_1_1_1_1_s_32,
3703 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003704 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003705 &nh_10_10_10_1,
3706 tm->hw[0]->sw_if_index,
3707 ~0,
3708 1,
3709 FIB_ROUTE_PATH_FLAG_NONE);
3710 fib_table_entry_path_remove(fib_index,
3711 &pfx_1_1_2_0_s_24,
3712 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003713 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003714 &nh_10_10_10_1,
3715 tm->hw[0]->sw_if_index,
3716 ~0,
3717 1,
3718 FIB_ROUTE_PATH_FLAG_NONE);
3719
3720 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3721 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3722 "1.1.1.1/32 removed");
3723 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3724 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3725 "1.1.1.2/32 removed");
3726 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3727 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3728 "1.1.2.0/24 removed");
3729
3730 /*
3731 * -3 entries and -1 shared path-list
3732 */
3733 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3734 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003735 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003736 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003737 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003738 fib_entry_pool_size());
3739
3740 /*
3741 * An attached-host route. Expect to link to the incomplete adj
3742 */
3743 fib_prefix_t pfx_4_1_1_1_s_32 = {
3744 .fp_len = 32,
3745 .fp_proto = FIB_PROTOCOL_IP4,
3746 .fp_addr = {
3747 /* 4.1.1.1/32 */
3748 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3749 },
3750 };
3751 fib_table_entry_path_add(fib_index,
3752 &pfx_4_1_1_1_s_32,
3753 FIB_SOURCE_API,
3754 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003755 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003756 &zero_addr,
3757 tm->hw[0]->sw_if_index,
3758 fib_index,
3759 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003760 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003761 FIB_ROUTE_PATH_FLAG_NONE);
3762
3763 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3764 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3765 ai = fib_entry_get_adj(fei);
3766
3767 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003768 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003769 &pfx_4_1_1_1_s_32.fp_addr,
3770 tm->hw[0]->sw_if_index);
3771 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3772 adj_unlock(ai2);
3773
3774 /*
3775 * +1 entry and +1 shared path-list
3776 */
3777 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3778 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003779 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003780 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003781 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003782 fib_entry_pool_size());
3783
3784 fib_table_entry_delete(fib_index,
3785 &pfx_4_1_1_1_s_32,
3786 FIB_SOURCE_API);
3787
3788 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3789 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003790 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003791 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003792 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003793 fib_entry_pool_size());
3794
3795 /*
3796 * add a v6 prefix via v4 next-hops
3797 */
3798 fib_prefix_t pfx_2001_s_64 = {
3799 .fp_len = 64,
3800 .fp_proto = FIB_PROTOCOL_IP6,
3801 .fp_addr = {
3802 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3803 },
3804 };
3805 fei = fib_table_entry_path_add(0, //default v6 table
3806 &pfx_2001_s_64,
3807 FIB_SOURCE_API,
3808 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003809 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003810 &nh_10_10_10_1,
3811 tm->hw[0]->sw_if_index,
3812 fib_index,
3813 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003814 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003815 FIB_ROUTE_PATH_FLAG_NONE);
3816
3817 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3818 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3819 ai = fib_entry_get_adj(fei);
3820 adj = adj_get(ai);
3821 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3822 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003823 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003824 "2001::/64 is link type v6");
3825 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3826 "2001::/64 ADJ-adj is NH proto v4");
3827 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3828
Neale Ranns3ee44042016-10-03 13:05:48 +01003829 /*
3830 * add a uRPF exempt prefix:
3831 * test:
3832 * - it's forwarding is drop
3833 * - it's uRPF list is not empty
3834 * - the uRPF list for the default route (it's cover) is empty
3835 */
3836 fei = fib_table_entry_special_add(fib_index,
3837 &pfx_4_1_1_1_s_32,
3838 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003839 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003840 dpo = fib_entry_contribute_ip_forwarding(fei);
3841 FIB_TEST(load_balance_is_drop(dpo),
3842 "uRPF exempt 4.1.1.1/32 DROP");
3843 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3844 "uRPF list for exempt prefix has itf index 0");
3845 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3846 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3847 "uRPF list for 0.0.0.0/0 empty");
3848
3849 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003850
3851 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003852 * An adj-fib that fails the refinement criteria - no connected cover
3853 */
3854 fib_prefix_t pfx_12_10_10_2_s_32 = {
3855 .fp_len = 32,
3856 .fp_proto = FIB_PROTOCOL_IP4,
3857 .fp_addr = {
3858 /* 12.10.10.2 */
3859 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3860 },
3861 };
3862
Neale Ranns81424992017-05-18 03:03:22 -07003863 fib_table_entry_path_add(fib_index,
3864 &pfx_12_10_10_2_s_32,
3865 FIB_SOURCE_ADJ,
3866 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003867 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003868 &pfx_12_10_10_2_s_32.fp_addr,
3869 tm->hw[0]->sw_if_index,
3870 ~0, // invalid fib index
3871 1,
3872 NULL,
3873 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003874
3875 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3876 dpo = fib_entry_contribute_ip_forwarding(fei);
3877 FIB_TEST(!dpo_id_is_valid(dpo),
3878 "no connected cover adj-fib fails refinement");
3879
3880 fib_table_entry_delete(fib_index,
3881 &pfx_12_10_10_2_s_32,
3882 FIB_SOURCE_ADJ);
3883
3884 /*
3885 * An adj-fib that fails the refinement criteria - cover is connected
3886 * but on a different interface
3887 */
3888 fib_prefix_t pfx_10_10_10_127_s_32 = {
3889 .fp_len = 32,
3890 .fp_proto = FIB_PROTOCOL_IP4,
3891 .fp_addr = {
3892 /* 10.10.10.127 */
3893 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3894 },
3895 };
3896
Neale Ranns81424992017-05-18 03:03:22 -07003897 fib_table_entry_path_add(fib_index,
3898 &pfx_10_10_10_127_s_32,
3899 FIB_SOURCE_ADJ,
3900 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003901 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003902 &pfx_10_10_10_127_s_32.fp_addr,
3903 tm->hw[1]->sw_if_index,
3904 ~0, // invalid fib index
3905 1,
3906 NULL,
3907 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003908
3909 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3910 dpo = fib_entry_contribute_ip_forwarding(fei);
3911 FIB_TEST(!dpo_id_is_valid(dpo),
3912 "wrong interface adj-fib fails refinement");
3913
3914 fib_table_entry_delete(fib_index,
3915 &pfx_10_10_10_127_s_32,
3916 FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07003917
3918 /*
3919 * add a second path to an adj-fib
3920 * this is a sumiluation of another ARP entry created
3921 * on an interface on which the connected prefi does not exist.
3922 * The second path fails refinement. Expect to forward through the
3923 * first.
3924 */
3925 fib_prefix_t pfx_10_10_10_3_s_32 = {
3926 .fp_len = 32,
3927 .fp_proto = FIB_PROTOCOL_IP4,
3928 .fp_addr = {
3929 /* 10.10.10.3 */
3930 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3931 },
3932 };
3933
3934 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3935 VNET_LINK_IP4,
3936 &nh_10_10_10_3,
3937 tm->hw[0]->sw_if_index);
3938
3939 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
3940 .type = FT_LB_ADJ,
3941 .adj = {
3942 .adj = ai_03,
3943 },
3944 };
3945 fei = fib_table_entry_path_add(fib_index,
3946 &pfx_10_10_10_3_s_32,
3947 FIB_SOURCE_ADJ,
3948 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003949 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003950 &nh_10_10_10_3,
3951 tm->hw[0]->sw_if_index,
3952 fib_index,
3953 1,
3954 NULL,
3955 FIB_ROUTE_PATH_FLAG_NONE);
3956 fei = fib_table_entry_path_add(fib_index,
3957 &pfx_10_10_10_3_s_32,
3958 FIB_SOURCE_ADJ,
3959 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003960 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003961 &nh_12_12_12_12,
3962 tm->hw[1]->sw_if_index,
3963 fib_index,
3964 1,
3965 NULL,
3966 FIB_ROUTE_PATH_FLAG_NONE);
3967 FIB_TEST(fib_test_validate_entry(fei,
3968 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3969 1,
3970 &ip_o_10_10_10_3),
3971 "10.10.10.3 via 10.10.10.3/Eth0 only");
3972
3973 /*
3974 * remove the path that refines the cover, should go unresolved
3975 */
3976 fib_table_entry_path_remove(fib_index,
3977 &pfx_10_10_10_3_s_32,
3978 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07003979 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003980 &nh_10_10_10_3,
3981 tm->hw[0]->sw_if_index,
3982 fib_index,
3983 1,
3984 FIB_ROUTE_PATH_FLAG_NONE);
3985 dpo = fib_entry_contribute_ip_forwarding(fei);
3986 FIB_TEST(!dpo_id_is_valid(dpo),
3987 "wrong interface adj-fib fails refinement");
3988
3989 /*
3990 * add back the path that refines the cover
3991 */
3992 fei = fib_table_entry_path_add(fib_index,
3993 &pfx_10_10_10_3_s_32,
3994 FIB_SOURCE_ADJ,
3995 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003996 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003997 &nh_10_10_10_3,
3998 tm->hw[0]->sw_if_index,
3999 fib_index,
4000 1,
4001 NULL,
4002 FIB_ROUTE_PATH_FLAG_NONE);
4003 FIB_TEST(fib_test_validate_entry(fei,
4004 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4005 1,
4006 &ip_o_10_10_10_3),
4007 "10.10.10.3 via 10.10.10.3/Eth0 only");
4008
4009 /*
4010 * remove the path that does not refine the cover
4011 */
4012 fib_table_entry_path_remove(fib_index,
4013 &pfx_10_10_10_3_s_32,
4014 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07004015 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004016 &nh_12_12_12_12,
4017 tm->hw[1]->sw_if_index,
4018 fib_index,
4019 1,
4020 FIB_ROUTE_PATH_FLAG_NONE);
4021 FIB_TEST(fib_test_validate_entry(fei,
4022 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4023 1,
4024 &ip_o_10_10_10_3),
4025 "10.10.10.3 via 10.10.10.3/Eth0 only");
4026
4027 /*
4028 * remove the path that does refine, it's the last path, so
4029 * the entry should be gone
4030 */
4031 fib_table_entry_path_remove(fib_index,
4032 &pfx_10_10_10_3_s_32,
4033 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07004034 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004035 &nh_10_10_10_3,
4036 tm->hw[0]->sw_if_index,
4037 fib_index,
4038 1,
4039 FIB_ROUTE_PATH_FLAG_NONE);
4040 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4041 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4042
4043 adj_unlock(ai_03);
4044
Neale Ranns227038a2017-04-21 01:07:59 -07004045 /*
4046 * change the table's flow-hash config - expect the update to propagete to
4047 * the entries' load-balance objects
4048 */
4049 flow_hash_config_t old_hash_config, new_hash_config;
4050
4051 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4052 FIB_PROTOCOL_IP4);
4053 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4054 IP_FLOW_HASH_DST_ADDR);
4055
4056 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4057 dpo = fib_entry_contribute_ip_forwarding(fei);
4058 lb = load_balance_get(dpo->dpoi_index);
4059 FIB_TEST((lb->lb_hash_config == old_hash_config),
4060 "Table and LB hash config match: %U",
4061 format_ip_flow_hash_config, lb->lb_hash_config);
4062
4063 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4064
4065 FIB_TEST((lb->lb_hash_config == new_hash_config),
4066 "Table and LB newhash config match: %U",
4067 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08004068
4069 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004070 * CLEANUP
4071 * remove adj-fibs:
4072 */
4073 fib_table_entry_delete(fib_index,
4074 &pfx_10_10_10_1_s_32,
4075 FIB_SOURCE_ADJ);
4076 fib_table_entry_delete(fib_index,
4077 &pfx_10_10_10_2_s_32,
4078 FIB_SOURCE_ADJ);
4079 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4080 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4081 "10.10.10.1/32 adj-fib removed");
4082 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4083 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4084 "10.10.10.2/32 adj-fib removed");
4085
4086 /*
4087 * -2 entries and -2 non-shared path-list
4088 */
4089 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4090 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004091 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004092 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004093 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004094 fib_entry_pool_size());
4095
4096 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01004097 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004098 * These are the last locks on these adjs. they should thus go away.
4099 */
4100 adj_unlock(ai_02);
4101 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01004102 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004103
4104 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4105 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00004106
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004107 /*
4108 * CLEANUP
4109 * remove the interface prefixes
4110 */
4111 local_pfx.fp_len = 32;
4112 fib_table_entry_special_remove(fib_index, &local_pfx,
4113 FIB_SOURCE_INTERFACE);
4114 fei = fib_table_lookup(fib_index, &local_pfx);
4115
4116 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4117 fib_table_lookup_exact_match(fib_index, &local_pfx),
4118 "10.10.10.10/32 adj-fib removed");
4119
4120 local_pfx.fp_len = 24;
4121 fib_table_entry_delete(fib_index, &local_pfx,
4122 FIB_SOURCE_INTERFACE);
4123
4124 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4125 fib_table_lookup_exact_match(fib_index, &local_pfx),
4126 "10.10.10.10/24 adj-fib removed");
4127
4128 /*
4129 * -2 entries and -2 non-shared path-list
4130 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07004131 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004132 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004133 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004134 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004135 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004136 fib_entry_pool_size());
4137
4138 /*
4139 * Last but not least, remove the VRF
4140 */
4141 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4142 FIB_PROTOCOL_IP4,
4143 FIB_SOURCE_API)),
4144 "NO API Source'd prefixes");
4145 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4146 FIB_PROTOCOL_IP4,
4147 FIB_SOURCE_RR)),
4148 "NO RR Source'd prefixes");
4149 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4150 FIB_PROTOCOL_IP4,
4151 FIB_SOURCE_INTERFACE)),
4152 "NO INterface Source'd prefixes");
4153
Neale Ranns15002542017-09-10 04:39:11 -07004154 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004155
4156 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4157 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004158 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004159 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004160 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004161 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004162 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01004163 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004164 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07004165 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004166 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4167 pool_elts(load_balance_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004168
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004169 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004170}
4171
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004172static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004173fib_test_v6 (void)
4174{
4175 /*
4176 * In the default table check for the presence and correct forwarding
4177 * of the special entries
4178 */
4179 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4180 const dpo_id_t *dpo, *dpo_drop;
4181 const ip_adjacency_t *adj;
4182 const receive_dpo_t *rd;
4183 test_main_t *tm;
4184 u32 fib_index;
4185 int ii;
4186
4187 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4188 adj_nbr_db_size());
4189
4190 /* via 2001:0:0:1::2 */
4191 ip46_address_t nh_2001_2 = {
4192 .ip6 = {
4193 .as_u64 = {
4194 [0] = clib_host_to_net_u64(0x2001000000000001),
4195 [1] = clib_host_to_net_u64(0x0000000000000002),
4196 },
4197 },
4198 };
4199
4200 tm = &test_main;
4201
4202 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4203
4204 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -07004205 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4206 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004207
4208 for (ii = 0; ii < 4; ii++)
4209 {
4210 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4211 }
4212
4213 fib_prefix_t pfx_0_0 = {
4214 .fp_len = 0,
4215 .fp_proto = FIB_PROTOCOL_IP6,
4216 .fp_addr = {
4217 .ip6 = {
4218 {0, 0},
4219 },
4220 },
4221 };
4222
4223 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4224 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4225 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4226 "Default route is DROP");
4227
4228 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4229 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4230 &ip6_main,
4231 1,
4232 &pfx_0_0.fp_addr.ip6)),
4233 "default-route; fwd and non-fwd tables match");
4234
4235 // FIXME - check specials.
4236
4237 /*
4238 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004239 * each with 2 entries and a v6 mfib with 4 path-lists.
4240 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004241 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004242#define ENPS (5+4)
4243#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004244 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004245 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004246 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004247 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004248 fib_entry_pool_size());
4249
4250 /*
4251 * add interface routes.
4252 * validate presence of /64 attached and /128 recieve.
4253 * test for the presence of the receive address in the glean and local adj
4254 *
4255 * receive on 2001:0:0:1::1/128
4256 */
4257 fib_prefix_t local_pfx = {
4258 .fp_len = 64,
4259 .fp_proto = FIB_PROTOCOL_IP6,
4260 .fp_addr = {
4261 .ip6 = {
4262 .as_u64 = {
4263 [0] = clib_host_to_net_u64(0x2001000000000001),
4264 [1] = clib_host_to_net_u64(0x0000000000000001),
4265 },
4266 },
4267 }
4268 };
4269
4270 fib_table_entry_update_one_path(fib_index, &local_pfx,
4271 FIB_SOURCE_INTERFACE,
4272 (FIB_ENTRY_FLAG_CONNECTED |
4273 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004274 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004275 NULL,
4276 tm->hw[0]->sw_if_index,
4277 ~0,
4278 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004279 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004280 FIB_ROUTE_PATH_FLAG_NONE);
4281 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4282
4283 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4284
4285 ai = fib_entry_get_adj(fei);
4286 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4287 adj = adj_get(ai);
4288 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4289 "attached interface adj is glean");
4290 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4291 &adj->sub_type.glean.receive_addr)),
4292 "attached interface adj is receive ok");
4293 dpo = fib_entry_contribute_ip_forwarding(fei);
4294 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4295 &ip6_main,
4296 1,
4297 &local_pfx.fp_addr.ip6)),
4298 "attached-route; fwd and non-fwd tables match");
4299
4300 local_pfx.fp_len = 128;
4301 fib_table_entry_update_one_path(fib_index, &local_pfx,
4302 FIB_SOURCE_INTERFACE,
4303 (FIB_ENTRY_FLAG_CONNECTED |
4304 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004305 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004306 NULL,
4307 tm->hw[0]->sw_if_index,
4308 ~0, // invalid fib index
4309 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004310 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004311 FIB_ROUTE_PATH_FLAG_NONE);
4312 fei = fib_table_lookup(fib_index, &local_pfx);
4313
4314 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4315
4316 dpo = fib_entry_contribute_ip_forwarding(fei);
4317 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4318 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4319 "local interface adj is local");
4320 rd = receive_dpo_get(dpo->dpoi_index);
4321
4322 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4323 &rd->rd_addr)),
4324 "local interface adj is receive ok");
4325
4326 dpo = fib_entry_contribute_ip_forwarding(fei);
4327 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4328 &ip6_main,
4329 1,
4330 &local_pfx.fp_addr.ip6)),
4331 "local-route; fwd and non-fwd tables match");
4332
4333 /*
4334 * +2 entries. +2 unshared path-lists
4335 */
4336 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004337 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004338 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004339 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004340 fib_entry_pool_size());
4341
4342 /*
4343 * Modify the default route to be via an adj not yet known.
4344 * this sources the defalut route with the API source, which is
4345 * a higher preference to the DEFAULT_ROUTE source
4346 */
4347 fib_table_entry_path_add(fib_index, &pfx_0_0,
4348 FIB_SOURCE_API,
4349 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004350 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004351 &nh_2001_2,
4352 tm->hw[0]->sw_if_index,
4353 ~0,
4354 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004355 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004356 FIB_ROUTE_PATH_FLAG_NONE);
4357 fei = fib_table_lookup(fib_index, &pfx_0_0);
4358
4359 FIB_TEST((fei == dfrt), "default route same index");
4360 ai = fib_entry_get_adj(fei);
4361 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4362 adj = adj_get(ai);
4363 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4364 "adj is incomplete");
4365 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4366 "adj nbr next-hop ok");
4367
4368 /*
4369 * find the adj in the shared db
4370 */
4371 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004372 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004373 &nh_2001_2,
4374 tm->hw[0]->sw_if_index);
4375 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4376 adj_unlock(locked_ai);
4377
4378 /*
4379 * no more entires. +1 shared path-list
4380 */
4381 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4382 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004383 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004384 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004385 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004386 fib_entry_pool_size());
4387
4388 /*
4389 * remove the API source from the default route. We expected
4390 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4391 */
4392 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4393 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07004394 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004395 &nh_2001_2,
4396 tm->hw[0]->sw_if_index,
4397 ~0,
4398 1,
4399 FIB_ROUTE_PATH_FLAG_NONE);
4400 fei = fib_table_lookup(fib_index, &pfx_0_0);
4401
4402 FIB_TEST((fei == dfrt), "default route same index");
4403 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4404 "Default route is DROP");
4405
4406 /*
4407 * no more entires. -1 shared path-list
4408 */
4409 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4410 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004411 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004412 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004413 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004414 fib_entry_pool_size());
4415
4416 /*
4417 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4418 */
4419 fib_prefix_t pfx_2001_1_2_s_128 = {
4420 .fp_len = 128,
4421 .fp_proto = FIB_PROTOCOL_IP6,
4422 .fp_addr = {
4423 .ip6 = {
4424 .as_u64 = {
4425 [0] = clib_host_to_net_u64(0x2001000000000001),
4426 [1] = clib_host_to_net_u64(0x0000000000000002),
4427 },
4428 },
4429 }
4430 };
4431 fib_prefix_t pfx_2001_1_3_s_128 = {
4432 .fp_len = 128,
4433 .fp_proto = FIB_PROTOCOL_IP6,
4434 .fp_addr = {
4435 .ip6 = {
4436 .as_u64 = {
4437 [0] = clib_host_to_net_u64(0x2001000000000001),
4438 [1] = clib_host_to_net_u64(0x0000000000000003),
4439 },
4440 },
4441 }
4442 };
4443 u8 eth_addr[] = {
4444 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4445 };
4446
4447 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004448 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004449 &pfx_2001_1_2_s_128.fp_addr,
4450 tm->hw[0]->sw_if_index);
4451 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4452 adj = adj_get(ai_01);
4453 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4454 "adj is incomplete");
4455 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4456 &adj->sub_type.nbr.next_hop)),
4457 "adj nbr next-hop ok");
4458
Neale Rannsb80c5362016-10-08 13:03:40 +01004459 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4460 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004461 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4462 "adj is complete");
4463 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4464 &adj->sub_type.nbr.next_hop)),
4465 "adj nbr next-hop ok");
4466
Neale Ranns81424992017-05-18 03:03:22 -07004467 fib_table_entry_path_add(fib_index,
4468 &pfx_2001_1_2_s_128,
4469 FIB_SOURCE_ADJ,
4470 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004471 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004472 &pfx_2001_1_2_s_128.fp_addr,
4473 tm->hw[0]->sw_if_index,
4474 ~0,
4475 1,
4476 NULL,
4477 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004478
4479 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4480 ai = fib_entry_get_adj(fei);
4481 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4482
4483 eth_addr[5] = 0xb2;
4484
4485 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004486 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004487 &pfx_2001_1_3_s_128.fp_addr,
4488 tm->hw[0]->sw_if_index);
4489 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4490 adj = adj_get(ai_02);
4491 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4492 "adj is incomplete");
4493 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4494 &adj->sub_type.nbr.next_hop)),
4495 "adj nbr next-hop ok");
4496
Neale Rannsb80c5362016-10-08 13:03:40 +01004497 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4498 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004499 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4500 "adj is complete");
4501 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4502 &adj->sub_type.nbr.next_hop)),
4503 "adj nbr next-hop ok");
4504 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4505
Neale Ranns81424992017-05-18 03:03:22 -07004506 fib_table_entry_path_add(fib_index,
4507 &pfx_2001_1_3_s_128,
4508 FIB_SOURCE_ADJ,
4509 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004510 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004511 &pfx_2001_1_3_s_128.fp_addr,
4512 tm->hw[0]->sw_if_index,
4513 ~0,
4514 1,
4515 NULL,
4516 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004517
4518 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4519 ai = fib_entry_get_adj(fei);
4520 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4521
4522 /*
4523 * +2 entries, +2 unshread path-lists.
4524 */
4525 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4526 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004527 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004528 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004529 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004530 fib_entry_pool_size());
4531
4532 /*
4533 * Add a 2 routes via the first ADJ. ensure path-list sharing
4534 */
4535 fib_prefix_t pfx_2001_a_s_64 = {
4536 .fp_len = 64,
4537 .fp_proto = FIB_PROTOCOL_IP6,
4538 .fp_addr = {
4539 .ip6 = {
4540 .as_u64 = {
4541 [0] = clib_host_to_net_u64(0x200100000000000a),
4542 [1] = clib_host_to_net_u64(0x0000000000000000),
4543 },
4544 },
4545 }
4546 };
4547 fib_prefix_t pfx_2001_b_s_64 = {
4548 .fp_len = 64,
4549 .fp_proto = FIB_PROTOCOL_IP6,
4550 .fp_addr = {
4551 .ip6 = {
4552 .as_u64 = {
4553 [0] = clib_host_to_net_u64(0x200100000000000b),
4554 [1] = clib_host_to_net_u64(0x0000000000000000),
4555 },
4556 },
4557 }
4558 };
4559
4560 fib_table_entry_path_add(fib_index,
4561 &pfx_2001_a_s_64,
4562 FIB_SOURCE_API,
4563 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004564 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004565 &nh_2001_2,
4566 tm->hw[0]->sw_if_index,
4567 ~0,
4568 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004569 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004570 FIB_ROUTE_PATH_FLAG_NONE);
4571 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4572 ai = fib_entry_get_adj(fei);
4573 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4574 fib_table_entry_path_add(fib_index,
4575 &pfx_2001_b_s_64,
4576 FIB_SOURCE_API,
4577 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004578 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004579 &nh_2001_2,
4580 tm->hw[0]->sw_if_index,
4581 ~0,
4582 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004583 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004584 FIB_ROUTE_PATH_FLAG_NONE);
4585 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4586 ai = fib_entry_get_adj(fei);
4587 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4588
4589 /*
4590 * +2 entries, +1 shared path-list.
4591 */
4592 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4593 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004594 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004595 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004596 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004597 fib_entry_pool_size());
4598
4599 /*
4600 * add a v4 prefix via a v6 next-hop
4601 */
4602 fib_prefix_t pfx_1_1_1_1_s_32 = {
4603 .fp_len = 32,
4604 .fp_proto = FIB_PROTOCOL_IP4,
4605 .fp_addr = {
4606 .ip4.as_u32 = 0x01010101,
4607 },
4608 };
4609 fei = fib_table_entry_path_add(0, // default table
4610 &pfx_1_1_1_1_s_32,
4611 FIB_SOURCE_API,
4612 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004613 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004614 &nh_2001_2,
4615 tm->hw[0]->sw_if_index,
4616 ~0,
4617 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004618 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004619 FIB_ROUTE_PATH_FLAG_NONE);
4620 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4621 "1.1.1.1/32 o v6 route present");
4622 ai = fib_entry_get_adj(fei);
4623 adj = adj_get(ai);
4624 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4625 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004626 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004627 "1.1.1.1/32 ADJ-adj is link type v4");
4628 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4629 "1.1.1.1/32 ADJ-adj is NH proto v6");
4630 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4631
4632 /*
4633 * An attached route
4634 */
4635 fib_prefix_t pfx_2001_c_s_64 = {
4636 .fp_len = 64,
4637 .fp_proto = FIB_PROTOCOL_IP6,
4638 .fp_addr = {
4639 .ip6 = {
4640 .as_u64 = {
4641 [0] = clib_host_to_net_u64(0x200100000000000c),
4642 [1] = clib_host_to_net_u64(0x0000000000000000),
4643 },
4644 },
4645 }
4646 };
4647 fib_table_entry_path_add(fib_index,
4648 &pfx_2001_c_s_64,
4649 FIB_SOURCE_CLI,
4650 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004651 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004652 NULL,
4653 tm->hw[0]->sw_if_index,
4654 ~0,
4655 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004656 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004657 FIB_ROUTE_PATH_FLAG_NONE);
4658 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4659 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4660 ai = fib_entry_get_adj(fei);
4661 adj = adj_get(ai);
4662 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4663 "2001:0:0:c/64 attached resolves via glean");
4664
4665 fib_table_entry_path_remove(fib_index,
4666 &pfx_2001_c_s_64,
4667 FIB_SOURCE_CLI,
Neale Rannsda78f952017-05-24 09:15:43 -07004668 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004669 NULL,
4670 tm->hw[0]->sw_if_index,
4671 ~0,
4672 1,
4673 FIB_ROUTE_PATH_FLAG_NONE);
4674 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4675 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4676
4677 /*
4678 * Shutdown the interface on which we have a connected and through
4679 * which the routes are reachable.
4680 * This will result in the connected, adj-fibs, and routes linking to drop
4681 * The local/for-us prefix continues to receive.
4682 */
4683 clib_error_t * error;
4684
4685 error = vnet_sw_interface_set_flags(vnet_get_main(),
4686 tm->hw[0]->sw_if_index,
4687 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4688 FIB_TEST((NULL == error), "Interface shutdown OK");
4689
4690 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4691 dpo = fib_entry_contribute_ip_forwarding(fei);
4692 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4693 "2001::b/64 resolves via drop");
4694
4695 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4696 dpo = fib_entry_contribute_ip_forwarding(fei);
4697 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4698 "2001::a/64 resolves via drop");
4699 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4700 dpo = fib_entry_contribute_ip_forwarding(fei);
4701 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4702 "2001:0:0:1::3/64 resolves via drop");
4703 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4704 dpo = fib_entry_contribute_ip_forwarding(fei);
4705 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4706 "2001:0:0:1::2/64 resolves via drop");
4707 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4708 dpo = fib_entry_contribute_ip_forwarding(fei);
4709 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4710 "2001:0:0:1::1/128 not drop");
4711 local_pfx.fp_len = 64;
4712 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4713 dpo = fib_entry_contribute_ip_forwarding(fei);
4714 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4715 "2001:0:0:1/64 resolves via drop");
4716
4717 /*
4718 * no change
4719 */
4720 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4721 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004722 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004723 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004724 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004725 fib_entry_pool_size());
4726
4727 /*
4728 * shutdown one of the other interfaces, then add a connected.
4729 * and swap one of the routes to it.
4730 */
4731 error = vnet_sw_interface_set_flags(vnet_get_main(),
4732 tm->hw[1]->sw_if_index,
4733 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4734 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4735
4736 fib_prefix_t connected_pfx = {
4737 .fp_len = 64,
4738 .fp_proto = FIB_PROTOCOL_IP6,
4739 .fp_addr = {
4740 .ip6 = {
4741 /* 2001:0:0:2::1/64 */
4742 .as_u64 = {
4743 [0] = clib_host_to_net_u64(0x2001000000000002),
4744 [1] = clib_host_to_net_u64(0x0000000000000001),
4745 },
4746 },
4747 }
4748 };
4749 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4750 FIB_SOURCE_INTERFACE,
4751 (FIB_ENTRY_FLAG_CONNECTED |
4752 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004753 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004754 NULL,
4755 tm->hw[1]->sw_if_index,
4756 ~0,
4757 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004758 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004759 FIB_ROUTE_PATH_FLAG_NONE);
4760 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4761 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4762 dpo = fib_entry_contribute_ip_forwarding(fei);
4763 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4764 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4765 "2001:0:0:2/64 not resolves via drop");
4766
4767 connected_pfx.fp_len = 128;
4768 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4769 FIB_SOURCE_INTERFACE,
4770 (FIB_ENTRY_FLAG_CONNECTED |
4771 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004772 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004773 NULL,
4774 tm->hw[0]->sw_if_index,
4775 ~0, // invalid fib index
4776 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004777 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004778 FIB_ROUTE_PATH_FLAG_NONE);
4779 fei = fib_table_lookup(fib_index, &connected_pfx);
4780
4781 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4782 dpo = fib_entry_contribute_ip_forwarding(fei);
4783 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4784 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4785 "local interface adj is local");
4786 rd = receive_dpo_get(dpo->dpoi_index);
4787 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4788 &rd->rd_addr)),
4789 "local interface adj is receive ok");
4790
4791 /*
4792 * +2 entries, +2 unshared path-lists
4793 */
4794 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4795 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004796 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004797 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004798 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004799 fib_entry_pool_size());
4800
4801
4802 /*
4803 * bring the interface back up. we expected the routes to return
4804 * to normal forwarding.
4805 */
4806 error = vnet_sw_interface_set_flags(vnet_get_main(),
4807 tm->hw[0]->sw_if_index,
4808 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4809 FIB_TEST((NULL == error), "Interface bring-up OK");
4810 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4811 ai = fib_entry_get_adj(fei);
4812 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4813 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4814 ai = fib_entry_get_adj(fei);
4815 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4816 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4817 ai = fib_entry_get_adj(fei);
4818 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4819 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4820 ai = fib_entry_get_adj(fei);
4821 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4822 local_pfx.fp_len = 64;
4823 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4824 ai = fib_entry_get_adj(fei);
4825 adj = adj_get(ai);
4826 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4827 "attached interface adj is glean");
4828
4829 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004830 * Same test as above, but this time the HW interface goes down
4831 */
4832 error = vnet_hw_interface_set_flags(vnet_get_main(),
4833 tm->hw_if_indicies[0],
4834 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4835 FIB_TEST((NULL == error), "Interface shutdown OK");
4836
4837 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4838 dpo = fib_entry_contribute_ip_forwarding(fei);
4839 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4840 "2001::b/64 resolves via drop");
4841 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4842 dpo = fib_entry_contribute_ip_forwarding(fei);
4843 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4844 "2001::a/64 resolves via drop");
4845 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4846 dpo = fib_entry_contribute_ip_forwarding(fei);
4847 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4848 "2001:0:0:1::3/128 resolves via drop");
4849 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4850 dpo = fib_entry_contribute_ip_forwarding(fei);
4851 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4852 "2001:0:0:1::2/128 resolves via drop");
4853 local_pfx.fp_len = 128;
4854 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4855 dpo = fib_entry_contribute_ip_forwarding(fei);
4856 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4857 "2001:0:0:1::1/128 not drop");
4858 local_pfx.fp_len = 64;
4859 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4860 dpo = fib_entry_contribute_ip_forwarding(fei);
4861 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4862 "2001:0:0:1/64 resolves via drop");
4863
4864 error = vnet_hw_interface_set_flags(vnet_get_main(),
4865 tm->hw_if_indicies[0],
4866 VNET_HW_INTERFACE_FLAG_LINK_UP);
4867 FIB_TEST((NULL == error), "Interface bring-up OK");
4868 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4869 ai = fib_entry_get_adj(fei);
4870 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4871 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4872 ai = fib_entry_get_adj(fei);
4873 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4874 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4875 ai = fib_entry_get_adj(fei);
4876 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4877 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4878 ai = fib_entry_get_adj(fei);
4879 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4880 local_pfx.fp_len = 64;
4881 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4882 ai = fib_entry_get_adj(fei);
4883 adj = adj_get(ai);
4884 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4885 "attached interface adj is glean");
4886
4887 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004888 * Delete the interface that the routes reolve through.
4889 * Again no routes are removed. They all point to drop.
4890 *
4891 * This is considered an error case. The control plane should
4892 * not remove interfaces through which routes resolve, but
4893 * such things can happen. ALL affected routes will drop.
4894 */
4895 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4896
4897 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4898 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4899 "2001::b/64 resolves via drop");
4900 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4901 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4902 "2001::b/64 resolves via drop");
4903 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4904 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4905 "2001:0:0:1::3/64 resolves via drop");
4906 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4907 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4908 "2001:0:0:1::2/64 resolves via drop");
4909 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4910 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4911 "2001:0:0:1::1/128 is drop");
4912 local_pfx.fp_len = 64;
4913 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4914 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4915 "2001:0:0:1/64 resolves via drop");
4916
4917 /*
4918 * no change
4919 */
4920 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4921 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004922 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004923 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004924 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004925 fib_entry_pool_size());
4926
4927 /*
4928 * Add the interface back. routes stay unresolved.
4929 */
4930 error = ethernet_register_interface(vnet_get_main(),
4931 test_interface_device_class.index,
4932 0 /* instance */,
4933 hw_address,
4934 &tm->hw_if_indicies[0],
4935 /* flag change */ 0);
4936
4937 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4938 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4939 "2001::b/64 resolves via drop");
4940 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4941 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4942 "2001::b/64 resolves via drop");
4943 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4944 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4945 "2001:0:0:1::3/64 resolves via drop");
4946 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4947 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4948 "2001:0:0:1::2/64 resolves via drop");
4949 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4950 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4951 "2001:0:0:1::1/128 is drop");
4952 local_pfx.fp_len = 64;
4953 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4954 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4955 "2001:0:0:1/64 resolves via drop");
4956
4957 /*
4958 * CLEANUP ALL the routes
4959 */
4960 fib_table_entry_delete(fib_index,
4961 &pfx_2001_c_s_64,
4962 FIB_SOURCE_API);
4963 fib_table_entry_delete(fib_index,
4964 &pfx_2001_a_s_64,
4965 FIB_SOURCE_API);
4966 fib_table_entry_delete(fib_index,
4967 &pfx_2001_b_s_64,
4968 FIB_SOURCE_API);
4969 fib_table_entry_delete(fib_index,
4970 &pfx_2001_1_3_s_128,
4971 FIB_SOURCE_ADJ);
4972 fib_table_entry_delete(fib_index,
4973 &pfx_2001_1_2_s_128,
4974 FIB_SOURCE_ADJ);
4975 local_pfx.fp_len = 64;
4976 fib_table_entry_delete(fib_index, &local_pfx,
4977 FIB_SOURCE_INTERFACE);
4978 local_pfx.fp_len = 128;
4979 fib_table_entry_special_remove(fib_index, &local_pfx,
4980 FIB_SOURCE_INTERFACE);
4981 connected_pfx.fp_len = 64;
4982 fib_table_entry_delete(fib_index, &connected_pfx,
4983 FIB_SOURCE_INTERFACE);
4984 connected_pfx.fp_len = 128;
4985 fib_table_entry_special_remove(fib_index, &connected_pfx,
4986 FIB_SOURCE_INTERFACE);
4987
4988 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4989 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4990 "2001::a/64 removed");
4991 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4992 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4993 "2001::b/64 removed");
4994 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4995 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4996 "2001:0:0:1::3/128 removed");
4997 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4998 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4999 "2001:0:0:1::3/128 removed");
5000 local_pfx.fp_len = 64;
5001 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5002 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5003 "2001:0:0:1/64 removed");
5004 local_pfx.fp_len = 128;
5005 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5006 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5007 "2001:0:0:1::1/128 removed");
5008 connected_pfx.fp_len = 64;
5009 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5010 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5011 "2001:0:0:2/64 removed");
5012 connected_pfx.fp_len = 128;
5013 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5014 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5015 "2001:0:0:2::1/128 removed");
5016
5017 /*
5018 * -8 entries. -7 path-lists (1 was shared).
5019 */
5020 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5021 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005022 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005023 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005024 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005025 fib_entry_pool_size());
5026
5027 /*
5028 * now remove the VRF
5029 */
Neale Ranns15002542017-09-10 04:39:11 -07005030 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005031
5032 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5033 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005034 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005035 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005036 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005037 fib_entry_pool_size());
5038
5039 adj_unlock(ai_02);
5040 adj_unlock(ai_01);
5041
5042 /*
5043 * return the interfaces to up state
5044 */
5045 error = vnet_sw_interface_set_flags(vnet_get_main(),
5046 tm->hw[0]->sw_if_index,
5047 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5048 error = vnet_sw_interface_set_flags(vnet_get_main(),
5049 tm->hw[1]->sw_if_index,
5050 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5051
5052 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5053 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005054
5055 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005056}
5057
5058/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005059 * Test Attached Exports
5060 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005061static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005062fib_test_ae (void)
5063{
5064 const dpo_id_t *dpo, *dpo_drop;
5065 const u32 fib_index = 0;
5066 fib_node_index_t fei;
5067 test_main_t *tm;
5068 ip4_main_t *im;
5069
5070 tm = &test_main;
5071 im = &ip4_main;
5072
5073 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5074 adj_nbr_db_size());
5075
5076 /*
5077 * add interface routes. We'll assume this works. It's more rigorously
5078 * tested elsewhere.
5079 */
5080 fib_prefix_t local_pfx = {
5081 .fp_len = 24,
5082 .fp_proto = FIB_PROTOCOL_IP4,
5083 .fp_addr = {
5084 .ip4 = {
5085 /* 10.10.10.10 */
5086 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5087 },
5088 },
5089 };
5090
5091 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5092 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5093
5094 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5095
5096 fib_table_entry_update_one_path(fib_index, &local_pfx,
5097 FIB_SOURCE_INTERFACE,
5098 (FIB_ENTRY_FLAG_CONNECTED |
5099 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005100 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005101 NULL,
5102 tm->hw[0]->sw_if_index,
5103 ~0,
5104 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005105 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005106 FIB_ROUTE_PATH_FLAG_NONE);
5107 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5108 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5109 "attached interface route present");
5110
5111 local_pfx.fp_len = 32;
5112 fib_table_entry_update_one_path(fib_index, &local_pfx,
5113 FIB_SOURCE_INTERFACE,
5114 (FIB_ENTRY_FLAG_CONNECTED |
5115 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07005116 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005117 NULL,
5118 tm->hw[0]->sw_if_index,
5119 ~0, // invalid fib index
5120 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005121 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005122 FIB_ROUTE_PATH_FLAG_NONE);
5123 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5124
5125 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5126 "local interface route present");
5127
5128 /*
5129 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5130 */
5131 fib_prefix_t pfx_10_10_10_1_s_32 = {
5132 .fp_len = 32,
5133 .fp_proto = FIB_PROTOCOL_IP4,
5134 .fp_addr = {
5135 /* 10.10.10.1 */
5136 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5137 },
5138 };
5139 fib_node_index_t ai;
5140
Neale Ranns81424992017-05-18 03:03:22 -07005141 fib_table_entry_path_add(fib_index,
5142 &pfx_10_10_10_1_s_32,
5143 FIB_SOURCE_ADJ,
5144 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005145 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005146 &pfx_10_10_10_1_s_32.fp_addr,
5147 tm->hw[0]->sw_if_index,
5148 ~0, // invalid fib index
5149 1,
5150 NULL,
5151 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005152
5153 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5154 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5155 ai = fib_entry_get_adj(fei);
5156
5157 /*
5158 * create another FIB table into which routes will be imported
5159 */
5160 u32 import_fib_index1;
5161
Neale Ranns15002542017-09-10 04:39:11 -07005162 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5163 11,
5164 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005165
5166 /*
5167 * Add an attached route in the import FIB
5168 */
5169 local_pfx.fp_len = 24;
5170 fib_table_entry_update_one_path(import_fib_index1,
5171 &local_pfx,
5172 FIB_SOURCE_API,
5173 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005174 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005175 NULL,
5176 tm->hw[0]->sw_if_index,
5177 ~0, // invalid fib index
5178 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005179 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005180 FIB_ROUTE_PATH_FLAG_NONE);
5181 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5182 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5183
5184 /*
5185 * check for the presence of the adj-fibs in the import table
5186 */
5187 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5188 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5189 FIB_TEST((ai == fib_entry_get_adj(fei)),
5190 "adj-fib1 Import uses same adj as export");
5191
5192 /*
5193 * check for the presence of the local in the import table
5194 */
5195 local_pfx.fp_len = 32;
5196 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5197 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5198
5199 /*
5200 * Add another adj-fin in the export table. Expect this
5201 * to get magically exported;
5202 */
5203 fib_prefix_t pfx_10_10_10_2_s_32 = {
5204 .fp_len = 32,
5205 .fp_proto = FIB_PROTOCOL_IP4,
5206 .fp_addr = {
5207 /* 10.10.10.2 */
5208 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5209 },
5210 };
5211
Neale Ranns81424992017-05-18 03:03:22 -07005212 fib_table_entry_path_add(fib_index,
5213 &pfx_10_10_10_2_s_32,
5214 FIB_SOURCE_ADJ,
5215 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005216 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005217 &pfx_10_10_10_2_s_32.fp_addr,
5218 tm->hw[0]->sw_if_index,
5219 ~0, // invalid fib index
5220 1,
5221 NULL,
5222 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005223 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5224 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5225 ai = fib_entry_get_adj(fei);
5226
5227 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5228 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5229 FIB_TEST((ai == fib_entry_get_adj(fei)),
5230 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005231 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5232 "ADJ-fib2 imported flags %d",
5233 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005234
5235 /*
5236 * create a 2nd FIB table into which routes will be imported
5237 */
5238 u32 import_fib_index2;
5239
Neale Ranns15002542017-09-10 04:39:11 -07005240 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5241 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005242
5243 /*
5244 * Add an attached route in the import FIB
5245 */
5246 local_pfx.fp_len = 24;
5247 fib_table_entry_update_one_path(import_fib_index2,
5248 &local_pfx,
5249 FIB_SOURCE_API,
5250 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005251 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005252 NULL,
5253 tm->hw[0]->sw_if_index,
5254 ~0, // invalid fib index
5255 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005256 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005257 FIB_ROUTE_PATH_FLAG_NONE);
5258 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5259 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5260
5261 /*
5262 * check for the presence of all the adj-fibs and local in the import table
5263 */
5264 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5265 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5266 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5267 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5268 local_pfx.fp_len = 32;
5269 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5270 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5271
5272 /*
5273 * add a 3rd adj-fib. expect it to be exported to both tables.
5274 */
5275 fib_prefix_t pfx_10_10_10_3_s_32 = {
5276 .fp_len = 32,
5277 .fp_proto = FIB_PROTOCOL_IP4,
5278 .fp_addr = {
5279 /* 10.10.10.3 */
5280 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5281 },
5282 };
5283
Neale Ranns81424992017-05-18 03:03:22 -07005284 fib_table_entry_path_add(fib_index,
5285 &pfx_10_10_10_3_s_32,
5286 FIB_SOURCE_ADJ,
5287 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005288 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005289 &pfx_10_10_10_3_s_32.fp_addr,
5290 tm->hw[0]->sw_if_index,
5291 ~0, // invalid fib index
5292 1,
5293 NULL,
5294 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005295 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5296 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5297 ai = fib_entry_get_adj(fei);
5298
5299 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5300 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5301 FIB_TEST((ai == fib_entry_get_adj(fei)),
5302 "Import uses same adj as export");
5303 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5304 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5305 FIB_TEST((ai == fib_entry_get_adj(fei)),
5306 "Import uses same adj as export");
5307
5308 /*
5309 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5310 */
5311 fib_table_entry_delete(fib_index,
5312 &pfx_10_10_10_3_s_32,
5313 FIB_SOURCE_ADJ);
5314
5315 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5316 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5317
5318 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5319 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5320
5321 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5322 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5323
5324 /*
5325 * remove the attached route from the 2nd FIB. expect the imported
5326 * entires to be removed
5327 */
5328 local_pfx.fp_len = 24;
5329 fib_table_entry_delete(import_fib_index2,
5330 &local_pfx,
5331 FIB_SOURCE_API);
5332 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5333 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5334
5335 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5336 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5337 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5338 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5339 local_pfx.fp_len = 32;
5340 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5341 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5342
5343 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5344 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5345 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5346 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5347 local_pfx.fp_len = 32;
5348 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5349 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5350
5351 /*
5352 * modify the route in FIB1 so it is no longer attached. expect the imported
5353 * entires to be removed
5354 */
5355 local_pfx.fp_len = 24;
5356 fib_table_entry_update_one_path(import_fib_index1,
5357 &local_pfx,
5358 FIB_SOURCE_API,
5359 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005360 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005361 &pfx_10_10_10_2_s_32.fp_addr,
5362 tm->hw[0]->sw_if_index,
5363 ~0, // invalid fib index
5364 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005365 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005366 FIB_ROUTE_PATH_FLAG_NONE);
5367 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5368 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5369 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5370 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5371 local_pfx.fp_len = 32;
5372 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5373 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5374
5375 /*
5376 * modify it back to attached. expect the adj-fibs back
5377 */
5378 local_pfx.fp_len = 24;
5379 fib_table_entry_update_one_path(import_fib_index1,
5380 &local_pfx,
5381 FIB_SOURCE_API,
5382 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005383 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005384 NULL,
5385 tm->hw[0]->sw_if_index,
5386 ~0, // invalid fib index
5387 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005388 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005389 FIB_ROUTE_PATH_FLAG_NONE);
5390 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5391 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5392 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5393 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5394 local_pfx.fp_len = 32;
5395 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5396 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5397
5398 /*
5399 * add a covering attached next-hop for the interface address, so we have
5400 * a valid adj to find when we check the forwarding tables
5401 */
5402 fib_prefix_t pfx_10_0_0_0_s_8 = {
5403 .fp_len = 8,
5404 .fp_proto = FIB_PROTOCOL_IP4,
5405 .fp_addr = {
5406 /* 10.0.0.0 */
5407 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5408 },
5409 };
5410
5411 fei = fib_table_entry_update_one_path(fib_index,
5412 &pfx_10_0_0_0_s_8,
5413 FIB_SOURCE_API,
5414 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005415 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005416 &pfx_10_10_10_3_s_32.fp_addr,
5417 tm->hw[0]->sw_if_index,
5418 ~0, // invalid fib index
5419 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005420 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005421 FIB_ROUTE_PATH_FLAG_NONE);
5422 dpo = fib_entry_contribute_ip_forwarding(fei);
5423
5424 /*
5425 * remove the route in the export fib. expect the adj-fibs to be removed
5426 */
5427 local_pfx.fp_len = 24;
5428 fib_table_entry_delete(fib_index,
5429 &local_pfx,
5430 FIB_SOURCE_INTERFACE);
5431
5432 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5433 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5434 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5435 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5436 local_pfx.fp_len = 32;
5437 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5438 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5439
5440 /*
5441 * the adj-fibs in the export VRF are present in the FIB table,
5442 * but not installed in forwarding, since they have no attached cover.
5443 * Consequently a lookup in the MTRIE gives the adj for the covering
5444 * route 10.0.0.0/8.
5445 */
5446 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5447 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5448
5449 index_t lbi;
5450 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5451 FIB_TEST(lbi == dpo->dpoi_index,
5452 "10.10.10.1 forwards on \n%U not \n%U",
5453 format_load_balance, lbi, 0,
5454 format_dpo_id, dpo, 0);
5455 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5456 FIB_TEST(lbi == dpo->dpoi_index,
5457 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5458 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5459 FIB_TEST(lbi == dpo->dpoi_index,
5460 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5461
5462 /*
5463 * add the export prefix back, but not as attached.
5464 * No adj-fibs in export nor import tables
5465 */
5466 local_pfx.fp_len = 24;
5467 fei = fib_table_entry_update_one_path(fib_index,
5468 &local_pfx,
5469 FIB_SOURCE_API,
5470 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005471 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005472 &pfx_10_10_10_1_s_32.fp_addr,
5473 tm->hw[0]->sw_if_index,
5474 ~0, // invalid fib index
5475 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005476 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005477 FIB_ROUTE_PATH_FLAG_NONE);
5478 dpo = fib_entry_contribute_ip_forwarding(fei);
5479
5480 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5481 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5482 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5483 FIB_TEST(lbi == dpo->dpoi_index,
5484 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5485 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5486 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5487 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5488 FIB_TEST(lbi == dpo->dpoi_index,
5489 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5490
5491 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5492 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5493 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5494 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5495 local_pfx.fp_len = 32;
5496 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5497 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5498
5499 /*
5500 * modify the export prefix so it is attached. expect all covereds to return
5501 */
5502 local_pfx.fp_len = 24;
5503 fib_table_entry_update_one_path(fib_index,
5504 &local_pfx,
5505 FIB_SOURCE_API,
5506 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005507 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005508 NULL,
5509 tm->hw[0]->sw_if_index,
5510 ~0, // invalid fib index
5511 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005512 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005513 FIB_ROUTE_PATH_FLAG_NONE);
5514
5515 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5516 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5517 dpo = fib_entry_contribute_ip_forwarding(fei);
5518 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5519 "Adj-fib1 is not drop in export");
5520 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5521 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5522 local_pfx.fp_len = 32;
5523 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5524 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5525 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5526 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5527 dpo = fib_entry_contribute_ip_forwarding(fei);
5528 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5529 "Adj-fib1 is not drop in export");
5530 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5531 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5532 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5533 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5534 local_pfx.fp_len = 32;
5535 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5536 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5537
5538 /*
5539 * modify the export prefix so connected. no change.
5540 */
5541 local_pfx.fp_len = 24;
5542 fib_table_entry_update_one_path(fib_index, &local_pfx,
5543 FIB_SOURCE_INTERFACE,
5544 (FIB_ENTRY_FLAG_CONNECTED |
5545 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005546 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005547 NULL,
5548 tm->hw[0]->sw_if_index,
5549 ~0,
5550 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005551 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005552 FIB_ROUTE_PATH_FLAG_NONE);
5553
5554 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5555 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5556 dpo = fib_entry_contribute_ip_forwarding(fei);
5557 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5558 "Adj-fib1 is not drop in export");
5559 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5560 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5561 local_pfx.fp_len = 32;
5562 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5563 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5564 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5565 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5566 dpo = fib_entry_contribute_ip_forwarding(fei);
5567 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5568 "Adj-fib1 is not drop in export");
5569 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5570 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5571 local_pfx.fp_len = 32;
5572 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5573 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5574
5575 /*
5576 * CLEANUP
5577 */
5578 fib_table_entry_delete(fib_index,
5579 &pfx_10_0_0_0_s_8,
5580 FIB_SOURCE_API);
5581 fib_table_entry_delete(fib_index,
5582 &pfx_10_10_10_1_s_32,
5583 FIB_SOURCE_ADJ);
5584 fib_table_entry_delete(fib_index,
5585 &pfx_10_10_10_2_s_32,
5586 FIB_SOURCE_ADJ);
5587 local_pfx.fp_len = 32;
5588 fib_table_entry_delete(fib_index,
5589 &local_pfx,
5590 FIB_SOURCE_INTERFACE);
5591 local_pfx.fp_len = 24;
5592 fib_table_entry_delete(fib_index,
5593 &local_pfx,
5594 FIB_SOURCE_API);
5595 fib_table_entry_delete(fib_index,
5596 &local_pfx,
5597 FIB_SOURCE_INTERFACE);
5598 local_pfx.fp_len = 24;
5599 fib_table_entry_delete(import_fib_index1,
5600 &local_pfx,
5601 FIB_SOURCE_API);
5602
Neale Ranns15002542017-09-10 04:39:11 -07005603 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5604 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005605
5606 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5607 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005608
5609 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005610}
5611
Neale Ranns57b58602017-07-15 07:37:25 -07005612/*
5613 * Test Path Preference
5614 */
5615static int
5616fib_test_pref (void)
5617{
5618 test_main_t *tm = &test_main;
5619
5620 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5621 .fp_len = 32,
5622 .fp_proto = FIB_PROTOCOL_IP4,
5623 .fp_addr = {
5624 .ip4 = {
5625 .as_u32 = clib_host_to_net_u32(0x01010101),
5626 },
5627 },
5628 };
5629
5630 /*
5631 * 2 high, 2 medium and 2 low preference non-recursive paths
5632 */
5633 fib_route_path_t nr_path_hi_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005634 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005635 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5636 .frp_fib_index = ~0,
5637 .frp_weight = 1,
5638 .frp_preference = 0,
5639 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5640 .frp_addr = {
5641 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5642 },
5643 };
5644 fib_route_path_t nr_path_hi_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005645 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005646 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5647 .frp_fib_index = ~0,
5648 .frp_weight = 1,
5649 .frp_preference = 0,
5650 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5651 .frp_addr = {
5652 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5653 },
5654 };
5655 fib_route_path_t nr_path_med_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005656 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005657 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5658 .frp_fib_index = ~0,
5659 .frp_weight = 1,
5660 .frp_preference = 1,
5661 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5662 .frp_addr = {
5663 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5664 },
5665 };
5666 fib_route_path_t nr_path_med_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005667 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005668 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5669 .frp_fib_index = ~0,
5670 .frp_weight = 1,
5671 .frp_preference = 1,
5672 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5673 .frp_addr = {
5674 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5675 },
5676 };
5677 fib_route_path_t nr_path_low_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005678 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005679 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5680 .frp_fib_index = ~0,
5681 .frp_weight = 1,
5682 .frp_preference = 2,
5683 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5684 .frp_addr = {
5685 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5686 },
5687 };
5688 fib_route_path_t nr_path_low_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005689 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005690 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5691 .frp_fib_index = ~0,
5692 .frp_weight = 1,
5693 .frp_preference = 2,
5694 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5695 .frp_addr = {
5696 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5697 },
5698 };
5699 fib_route_path_t *nr_paths = NULL;
5700
5701 vec_add1(nr_paths, nr_path_hi_1);
5702 vec_add1(nr_paths, nr_path_hi_2);
5703 vec_add1(nr_paths, nr_path_med_1);
5704 vec_add1(nr_paths, nr_path_med_2);
5705 vec_add1(nr_paths, nr_path_low_1);
5706 vec_add1(nr_paths, nr_path_low_2);
5707
5708 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5709 VNET_LINK_IP4,
5710 &nr_path_hi_1.frp_addr,
5711 nr_path_hi_1.frp_sw_if_index);
5712 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5713 VNET_LINK_IP4,
5714 &nr_path_hi_2.frp_addr,
5715 nr_path_hi_2.frp_sw_if_index);
5716 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5717 VNET_LINK_IP4,
5718 &nr_path_med_1.frp_addr,
5719 nr_path_med_1.frp_sw_if_index);
5720 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5721 VNET_LINK_IP4,
5722 &nr_path_med_2.frp_addr,
5723 nr_path_med_2.frp_sw_if_index);
5724 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5725 VNET_LINK_IP4,
5726 &nr_path_low_1.frp_addr,
5727 nr_path_low_1.frp_sw_if_index);
5728 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5729 VNET_LINK_IP4,
5730 &nr_path_low_2.frp_addr,
5731 nr_path_low_2.frp_sw_if_index);
5732
5733 fib_test_lb_bucket_t ip_hi_1 = {
5734 .type = FT_LB_ADJ,
5735 .adj = {
5736 .adj = ai_hi_1,
5737 },
5738 };
5739 fib_test_lb_bucket_t ip_hi_2 = {
5740 .type = FT_LB_ADJ,
5741 .adj = {
5742 .adj = ai_hi_2,
5743 },
5744 };
5745 fib_test_lb_bucket_t ip_med_1 = {
5746 .type = FT_LB_ADJ,
5747 .adj = {
5748 .adj = ai_med_1,
5749 },
5750 };
5751 fib_test_lb_bucket_t ip_med_2 = {
5752 .type = FT_LB_ADJ,
5753 .adj = {
5754 .adj = ai_med_2,
5755 },
5756 };
5757 fib_test_lb_bucket_t ip_low_1 = {
5758 .type = FT_LB_ADJ,
5759 .adj = {
5760 .adj = ai_low_1,
5761 },
5762 };
5763 fib_test_lb_bucket_t ip_low_2 = {
5764 .type = FT_LB_ADJ,
5765 .adj = {
5766 .adj = ai_low_2,
5767 },
5768 };
5769
5770 fib_node_index_t fei;
5771
5772 fei = fib_table_entry_path_add2(0,
5773 &pfx_1_1_1_1_s_32,
5774 FIB_SOURCE_API,
5775 FIB_ENTRY_FLAG_NONE,
5776 nr_paths);
5777
5778 FIB_TEST(fib_test_validate_entry(fei,
5779 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5780 2,
5781 &ip_hi_1,
5782 &ip_hi_2),
5783 "1.1.1.1/32 via high preference paths");
5784
5785 /*
5786 * bring down the interface on which the high preference path lie
5787 */
5788 vnet_sw_interface_set_flags(vnet_get_main(),
5789 tm->hw[0]->sw_if_index,
5790 0);
5791
5792 FIB_TEST(fib_test_validate_entry(fei,
5793 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5794 2,
5795 &ip_med_1,
5796 &ip_med_2),
5797 "1.1.1.1/32 via medium preference paths");
5798
5799 /*
5800 * bring down the interface on which the medium preference path lie
5801 */
5802 vnet_sw_interface_set_flags(vnet_get_main(),
5803 tm->hw[1]->sw_if_index,
5804 0);
5805
5806 FIB_TEST(fib_test_validate_entry(fei,
5807 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5808 2,
5809 &ip_low_1,
5810 &ip_low_2),
5811 "1.1.1.1/32 via low preference paths");
5812
5813 /*
5814 * bring up the interface on which the high preference path lie
5815 */
5816 vnet_sw_interface_set_flags(vnet_get_main(),
5817 tm->hw[0]->sw_if_index,
5818 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5819
5820 FIB_TEST(fib_test_validate_entry(fei,
5821 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5822 2,
5823 &ip_hi_1,
5824 &ip_hi_2),
5825 "1.1.1.1/32 via high preference paths");
5826
5827 /*
5828 * bring up the interface on which the medium preference path lie
5829 */
5830 vnet_sw_interface_set_flags(vnet_get_main(),
5831 tm->hw[1]->sw_if_index,
5832 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5833
5834 FIB_TEST(fib_test_validate_entry(fei,
5835 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5836 2,
5837 &ip_hi_1,
5838 &ip_hi_2),
5839 "1.1.1.1/32 via high preference paths");
5840
5841 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5842 fib_entry_contribute_forwarding(fei,
5843 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5844 &ip_1_1_1_1);
5845
5846 /*
5847 * 3 recursive paths of different preference
5848 */
5849 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5850 .fp_len = 32,
5851 .fp_proto = FIB_PROTOCOL_IP4,
5852 .fp_addr = {
5853 .ip4 = {
5854 .as_u32 = clib_host_to_net_u32(0x01010102),
5855 },
5856 },
5857 };
5858 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5859 .fp_len = 32,
5860 .fp_proto = FIB_PROTOCOL_IP4,
5861 .fp_addr = {
5862 .ip4 = {
5863 .as_u32 = clib_host_to_net_u32(0x01010103),
5864 },
5865 },
5866 };
5867 fei = fib_table_entry_path_add2(0,
5868 &pfx_1_1_1_2_s_32,
5869 FIB_SOURCE_API,
5870 FIB_ENTRY_FLAG_NONE,
5871 nr_paths);
5872 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5873 fib_entry_contribute_forwarding(fei,
5874 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5875 &ip_1_1_1_2);
5876 fei = fib_table_entry_path_add2(0,
5877 &pfx_1_1_1_3_s_32,
5878 FIB_SOURCE_API,
5879 FIB_ENTRY_FLAG_NONE,
5880 nr_paths);
5881 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
5882 fib_entry_contribute_forwarding(fei,
5883 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5884 &ip_1_1_1_3);
5885
5886 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
5887 .type = FT_LB_O_LB,
5888 .lb = {
5889 .lb = ip_1_1_1_1.dpoi_index,
5890 },
5891 };
5892 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
5893 .type = FT_LB_O_LB,
5894 .lb = {
5895 .lb = ip_1_1_1_2.dpoi_index,
5896 },
5897 };
5898 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
5899 .type = FT_LB_O_LB,
5900 .lb = {
5901 .lb = ip_1_1_1_3.dpoi_index,
5902 },
5903 };
5904 fib_route_path_t r_path_hi = {
Neale Rannsda78f952017-05-24 09:15:43 -07005905 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005906 .frp_sw_if_index = ~0,
5907 .frp_fib_index = 0,
5908 .frp_weight = 1,
5909 .frp_preference = 0,
5910 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5911 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
5912 };
5913 fib_route_path_t r_path_med = {
Neale Rannsda78f952017-05-24 09:15:43 -07005914 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005915 .frp_sw_if_index = ~0,
5916 .frp_fib_index = 0,
5917 .frp_weight = 1,
5918 .frp_preference = 10,
5919 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5920 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
5921 };
5922 fib_route_path_t r_path_low = {
Neale Rannsda78f952017-05-24 09:15:43 -07005923 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005924 .frp_sw_if_index = ~0,
5925 .frp_fib_index = 0,
5926 .frp_weight = 1,
Neale Rannsa0a908f2017-08-01 11:40:03 -07005927 .frp_preference = 255,
Neale Ranns57b58602017-07-15 07:37:25 -07005928 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5929 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
5930 };
5931 fib_route_path_t *r_paths = NULL;
5932
5933 vec_add1(r_paths, r_path_hi);
5934 vec_add1(r_paths, r_path_low);
5935 vec_add1(r_paths, r_path_med);
5936
5937 /*
5938 * add many recursive so we get the LB MAp created
5939 */
5940 #define N_PFXS 64
5941 fib_prefix_t pfx_r[N_PFXS];
Marek Gradzkiaf095512017-08-15 07:38:26 +02005942 unsigned int n_pfxs;
Neale Ranns57b58602017-07-15 07:37:25 -07005943 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
5944 {
5945 pfx_r[n_pfxs].fp_len = 32;
5946 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
5947 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
5948 clib_host_to_net_u32(0x02000000 + n_pfxs);
5949
5950 fei = fib_table_entry_path_add2(0,
5951 &pfx_r[n_pfxs],
5952 FIB_SOURCE_API,
5953 FIB_ENTRY_FLAG_NONE,
5954 r_paths);
5955
5956 FIB_TEST(fib_test_validate_entry(fei,
5957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5958 1,
5959 &ip_o_1_1_1_1),
5960 "recursive via high preference paths");
5961
5962 /*
5963 * withdraw hig pref resolving entry
5964 */
5965 fib_table_entry_delete(0,
5966 &pfx_1_1_1_1_s_32,
5967 FIB_SOURCE_API);
5968
5969 /* suspend so the update walk kicks int */
5970 vlib_process_suspend(vlib_get_main(), 1e-5);
5971
5972 FIB_TEST(fib_test_validate_entry(fei,
5973 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5974 1,
5975 &ip_o_1_1_1_2),
5976 "recursive via medium preference paths");
5977
5978 /*
5979 * withdraw medium pref resolving entry
5980 */
5981 fib_table_entry_delete(0,
5982 &pfx_1_1_1_2_s_32,
5983 FIB_SOURCE_API);
5984
5985 /* suspend so the update walk kicks int */
5986 vlib_process_suspend(vlib_get_main(), 1e-5);
5987
5988 FIB_TEST(fib_test_validate_entry(fei,
5989 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5990 1,
5991 &ip_o_1_1_1_3),
5992 "recursive via low preference paths");
5993
5994 /*
5995 * add back paths for next iteration
5996 */
5997 fei = fib_table_entry_update(0,
5998 &pfx_1_1_1_2_s_32,
5999 FIB_SOURCE_API,
6000 FIB_ENTRY_FLAG_NONE,
6001 nr_paths);
6002 fei = fib_table_entry_update(0,
6003 &pfx_1_1_1_1_s_32,
6004 FIB_SOURCE_API,
6005 FIB_ENTRY_FLAG_NONE,
6006 nr_paths);
6007
6008 /* suspend so the update walk kicks int */
6009 vlib_process_suspend(vlib_get_main(), 1e-5);
6010
6011 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6012 FIB_TEST(fib_test_validate_entry(fei,
6013 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6014 1,
6015 &ip_o_1_1_1_1),
6016 "recursive via high preference paths");
6017 }
6018
6019
6020 fib_table_entry_delete(0,
6021 &pfx_1_1_1_1_s_32,
6022 FIB_SOURCE_API);
6023
6024 /* suspend so the update walk kicks int */
6025 vlib_process_suspend(vlib_get_main(), 1e-5);
6026
6027 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6028 {
6029 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6030
6031 FIB_TEST(fib_test_validate_entry(fei,
6032 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6033 1,
6034 &ip_o_1_1_1_2),
6035 "recursive via medium preference paths");
6036 }
6037 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6038 {
6039 fib_table_entry_delete(0,
6040 &pfx_r[n_pfxs],
6041 FIB_SOURCE_API);
6042 }
6043
6044 /*
6045 * Cleanup
6046 */
6047 fib_table_entry_delete(0,
6048 &pfx_1_1_1_2_s_32,
6049 FIB_SOURCE_API);
6050 fib_table_entry_delete(0,
6051 &pfx_1_1_1_3_s_32,
6052 FIB_SOURCE_API);
6053
6054 dpo_reset(&ip_1_1_1_1);
6055 dpo_reset(&ip_1_1_1_2);
6056 dpo_reset(&ip_1_1_1_3);
6057 adj_unlock(ai_low_2);
6058 adj_unlock(ai_low_1);
6059 adj_unlock(ai_med_2);
6060 adj_unlock(ai_med_1);
6061 adj_unlock(ai_hi_2);
6062 adj_unlock(ai_hi_1);
6063 return (0);
6064}
Neale Rannsad422ed2016-11-02 14:20:04 +00006065
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006066/*
6067 * Test the recursive route route handling for GRE tunnels
6068 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006069static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006070fib_test_label (void)
6071{
6072 fib_node_index_t fei, ai_mpls_10_10_10_1, ai_v4_10_10_11_1, ai_v4_10_10_11_2, ai_mpls_10_10_11_2, ai_mpls_10_10_11_1;
6073 const u32 fib_index = 0;
6074 test_main_t *tm;
6075 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00006076 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006077
6078 lb_count = pool_elts(load_balance_pool);
6079 tm = &test_main;
6080 im = &ip4_main;
6081
6082 /*
6083 * add interface routes. We'll assume this works. It's more rigorously
6084 * tested elsewhere.
6085 */
6086 fib_prefix_t local0_pfx = {
6087 .fp_len = 24,
6088 .fp_proto = FIB_PROTOCOL_IP4,
6089 .fp_addr = {
6090 .ip4 = {
6091 /* 10.10.10.10 */
6092 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6093 },
6094 },
6095 };
6096
6097 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6098 adj_nbr_db_size());
6099
6100 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6101 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6102
6103 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6104 FIB_SOURCE_INTERFACE,
6105 (FIB_ENTRY_FLAG_CONNECTED |
6106 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006107 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006108 NULL,
6109 tm->hw[0]->sw_if_index,
6110 ~0,
6111 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006112 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006113 FIB_ROUTE_PATH_FLAG_NONE);
6114 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6115 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6116 "attached interface route present");
6117
6118 local0_pfx.fp_len = 32;
6119 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6120 FIB_SOURCE_INTERFACE,
6121 (FIB_ENTRY_FLAG_CONNECTED |
6122 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006123 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006124 NULL,
6125 tm->hw[0]->sw_if_index,
6126 ~0, // invalid fib index
6127 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006128 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006129 FIB_ROUTE_PATH_FLAG_NONE);
6130 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6131
6132 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6133 "local interface route present");
6134
6135 fib_prefix_t local1_pfx = {
6136 .fp_len = 24,
6137 .fp_proto = FIB_PROTOCOL_IP4,
6138 .fp_addr = {
6139 .ip4 = {
6140 /* 10.10.11.10 */
6141 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6142 },
6143 },
6144 };
6145
6146 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6147 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6148
6149 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6150 FIB_SOURCE_INTERFACE,
6151 (FIB_ENTRY_FLAG_CONNECTED |
6152 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006153 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006154 NULL,
6155 tm->hw[1]->sw_if_index,
6156 ~0,
6157 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006158 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006159 FIB_ROUTE_PATH_FLAG_NONE);
6160 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6161 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6162 "attached interface route present");
6163
6164 local1_pfx.fp_len = 32;
6165 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6166 FIB_SOURCE_INTERFACE,
6167 (FIB_ENTRY_FLAG_CONNECTED |
6168 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006169 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006170 NULL,
6171 tm->hw[1]->sw_if_index,
6172 ~0, // invalid fib index
6173 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006174 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006175 FIB_ROUTE_PATH_FLAG_NONE);
6176 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6177
6178 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6179 "local interface route present");
6180
6181 ip46_address_t nh_10_10_10_1 = {
6182 .ip4 = {
6183 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6184 },
6185 };
6186 ip46_address_t nh_10_10_11_1 = {
6187 .ip4 = {
6188 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6189 },
6190 };
6191 ip46_address_t nh_10_10_11_2 = {
6192 .ip4 = {
6193 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6194 },
6195 };
6196
6197 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006198 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006199 &nh_10_10_11_1,
6200 tm->hw[1]->sw_if_index);
6201 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006202 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006203 &nh_10_10_11_2,
6204 tm->hw[1]->sw_if_index);
6205 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006206 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006207 &nh_10_10_10_1,
6208 tm->hw[0]->sw_if_index);
6209 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006210 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006211 &nh_10_10_11_2,
6212 tm->hw[1]->sw_if_index);
6213 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006214 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006215 &nh_10_10_11_1,
6216 tm->hw[1]->sw_if_index);
6217
6218 /*
6219 * Add an etry with one path with a real out-going label
6220 */
6221 fib_prefix_t pfx_1_1_1_1_s_32 = {
6222 .fp_len = 32,
6223 .fp_proto = FIB_PROTOCOL_IP4,
6224 .fp_addr = {
6225 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6226 },
6227 };
6228 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6229 .type = FT_LB_LABEL_O_ADJ,
6230 .label_o_adj = {
6231 .adj = ai_mpls_10_10_10_1,
6232 .label = 99,
6233 .eos = MPLS_EOS,
6234 },
6235 };
6236 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6237 .type = FT_LB_LABEL_O_ADJ,
6238 .label_o_adj = {
6239 .adj = ai_mpls_10_10_10_1,
6240 .label = 99,
6241 .eos = MPLS_NON_EOS,
6242 },
6243 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006244 mpls_label_t *l99 = NULL;
6245 vec_add1(l99, 99);
6246
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006247 fib_table_entry_update_one_path(fib_index,
6248 &pfx_1_1_1_1_s_32,
6249 FIB_SOURCE_API,
6250 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006251 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006252 &nh_10_10_10_1,
6253 tm->hw[0]->sw_if_index,
6254 ~0, // invalid fib index
6255 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006256 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006257 FIB_ROUTE_PATH_FLAG_NONE);
6258
6259 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6260 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6261
6262 FIB_TEST(fib_test_validate_entry(fei,
6263 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6264 1,
6265 &l99_eos_o_10_10_10_1),
6266 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6267
6268 /*
6269 * add a path with an implicit NULL label
6270 */
6271 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6272 .type = FT_LB_ADJ,
6273 .adj = {
6274 .adj = ai_v4_10_10_11_1,
6275 },
6276 };
6277 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6278 .type = FT_LB_ADJ,
6279 .adj = {
6280 .adj = ai_mpls_10_10_11_1,
6281 },
6282 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006283 mpls_label_t *l_imp_null = NULL;
6284 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006285
6286 fei = fib_table_entry_path_add(fib_index,
6287 &pfx_1_1_1_1_s_32,
6288 FIB_SOURCE_API,
6289 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006290 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006291 &nh_10_10_11_1,
6292 tm->hw[1]->sw_if_index,
6293 ~0, // invalid fib index
6294 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006295 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006296 FIB_ROUTE_PATH_FLAG_NONE);
6297
6298 FIB_TEST(fib_test_validate_entry(fei,
6299 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6300 2,
6301 &l99_eos_o_10_10_10_1,
6302 &a_o_10_10_11_1),
6303 "1.1.1.1/32 LB 2 buckets via: "
6304 "label 99 over 10.10.10.1, "
6305 "adj over 10.10.11.1");
6306
6307 /*
6308 * assign the route a local label
6309 */
6310 fib_table_entry_local_label_add(fib_index,
6311 &pfx_1_1_1_1_s_32,
6312 24001);
6313
6314 fib_prefix_t pfx_24001_eos = {
6315 .fp_proto = FIB_PROTOCOL_MPLS,
6316 .fp_label = 24001,
6317 .fp_eos = MPLS_EOS,
6318 };
6319 fib_prefix_t pfx_24001_neos = {
6320 .fp_proto = FIB_PROTOCOL_MPLS,
6321 .fp_label = 24001,
6322 .fp_eos = MPLS_NON_EOS,
6323 };
6324
6325 /*
6326 * The EOS entry should link to both the paths,
6327 * and use an ip adj for the imp-null
6328 * The NON-EOS entry should link to both the paths,
6329 * and use an mpls adj for the imp-null
6330 */
6331 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6332 &pfx_24001_eos);
6333 FIB_TEST(fib_test_validate_entry(fei,
6334 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6335 2,
6336 &l99_eos_o_10_10_10_1,
6337 &a_o_10_10_11_1),
6338 "24001/eos LB 2 buckets via: "
6339 "label 99 over 10.10.10.1, "
6340 "adj over 10.10.11.1");
6341
6342
6343 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6344 &pfx_24001_neos);
6345 FIB_TEST(fib_test_validate_entry(fei,
6346 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6347 2,
6348 &l99_neos_o_10_10_10_1,
6349 &a_mpls_o_10_10_11_1),
6350 "24001/neos LB 1 bucket via: "
6351 "label 99 over 10.10.10.1 ",
6352 "mpls-adj via 10.10.11.1");
6353
6354 /*
6355 * add an unlabelled path, this is excluded from the neos chains,
6356 */
6357 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6358 .type = FT_LB_ADJ,
6359 .adj = {
6360 .adj = ai_v4_10_10_11_2,
6361 },
6362 };
6363
6364 fei = fib_table_entry_path_add(fib_index,
6365 &pfx_1_1_1_1_s_32,
6366 FIB_SOURCE_API,
6367 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006368 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006369 &nh_10_10_11_2,
6370 tm->hw[1]->sw_if_index,
6371 ~0, // invalid fib index
6372 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006373 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006374 FIB_ROUTE_PATH_FLAG_NONE);
6375
6376 FIB_TEST(fib_test_validate_entry(fei,
6377 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6378 16, // 3 choices spread over 16 buckets
6379 &l99_eos_o_10_10_10_1,
6380 &l99_eos_o_10_10_10_1,
6381 &l99_eos_o_10_10_10_1,
6382 &l99_eos_o_10_10_10_1,
6383 &l99_eos_o_10_10_10_1,
6384 &l99_eos_o_10_10_10_1,
6385 &a_o_10_10_11_1,
6386 &a_o_10_10_11_1,
6387 &a_o_10_10_11_1,
6388 &a_o_10_10_11_1,
6389 &a_o_10_10_11_1,
6390 &adj_o_10_10_11_2,
6391 &adj_o_10_10_11_2,
6392 &adj_o_10_10_11_2,
6393 &adj_o_10_10_11_2,
6394 &adj_o_10_10_11_2),
6395 "1.1.1.1/32 LB 16 buckets via: "
6396 "label 99 over 10.10.10.1, "
6397 "adj over 10.10.11.1",
6398 "adj over 10.10.11.2");
6399
6400 /*
6401 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6402 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006403 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006404 fib_entry_contribute_forwarding(fei,
6405 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6406 &non_eos_1_1_1_1);
6407
6408 /*
6409 * n-eos has only the 2 labelled paths
6410 */
6411 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6412 &pfx_24001_neos);
6413
6414 FIB_TEST(fib_test_validate_entry(fei,
6415 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6416 2,
6417 &l99_neos_o_10_10_10_1,
6418 &a_mpls_o_10_10_11_1),
6419 "24001/neos LB 2 buckets via: "
6420 "label 99 over 10.10.10.1, "
6421 "adj-mpls over 10.10.11.2");
6422
6423 /*
6424 * A labelled recursive
6425 */
6426 fib_prefix_t pfx_2_2_2_2_s_32 = {
6427 .fp_len = 32,
6428 .fp_proto = FIB_PROTOCOL_IP4,
6429 .fp_addr = {
6430 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6431 },
6432 };
6433 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6434 .type = FT_LB_LABEL_O_LB,
6435 .label_o_lb = {
6436 .lb = non_eos_1_1_1_1.dpoi_index,
6437 .label = 1600,
6438 .eos = MPLS_EOS,
6439 },
6440 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006441 mpls_label_t *l1600 = NULL;
6442 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006443
6444 fib_table_entry_update_one_path(fib_index,
6445 &pfx_2_2_2_2_s_32,
6446 FIB_SOURCE_API,
6447 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006448 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006449 &pfx_1_1_1_1_s_32.fp_addr,
6450 ~0,
6451 fib_index,
6452 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006453 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006454 FIB_ROUTE_PATH_FLAG_NONE);
6455
6456 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6457 FIB_TEST(fib_test_validate_entry(fei,
6458 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6459 1,
6460 &l1600_eos_o_1_1_1_1),
6461 "2.2.2.2.2/32 LB 1 buckets via: "
6462 "label 1600 over 1.1.1.1");
6463
Neale Ranns948e00f2016-10-20 13:39:34 +01006464 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01006465 index_t urpfi;
6466
6467 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6468 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6469
6470 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6471 "uRPF check for 2.2.2.2/32 on %d OK",
6472 tm->hw[0]->sw_if_index);
6473 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6474 "uRPF check for 2.2.2.2/32 on %d OK",
6475 tm->hw[1]->sw_if_index);
6476 FIB_TEST(!fib_urpf_check(urpfi, 99),
6477 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6478 99);
6479
6480 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6481 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6482 "Shared uRPF on IP and non-EOS chain");
6483
6484 dpo_reset(&dpo_44);
6485
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006486 /*
6487 * we are holding a lock on the non-eos LB of the via-entry.
6488 * do a PIC-core failover by shutting the link of the via-entry.
6489 *
6490 * shut down the link with the valid label
6491 */
6492 vnet_sw_interface_set_flags(vnet_get_main(),
6493 tm->hw[0]->sw_if_index,
6494 0);
6495
6496 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6497 FIB_TEST(fib_test_validate_entry(fei,
6498 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6499 2,
6500 &a_o_10_10_11_1,
6501 &adj_o_10_10_11_2),
6502 "1.1.1.1/32 LB 2 buckets via: "
6503 "adj over 10.10.11.1, ",
6504 "adj-v4 over 10.10.11.2");
6505
6506 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6507 &pfx_24001_eos);
6508 FIB_TEST(fib_test_validate_entry(fei,
6509 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6510 2,
6511 &a_o_10_10_11_1,
6512 &adj_o_10_10_11_2),
6513 "24001/eos LB 2 buckets via: "
6514 "adj over 10.10.11.1, ",
6515 "adj-v4 over 10.10.11.2");
6516
6517 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6518 &pfx_24001_neos);
6519 FIB_TEST(fib_test_validate_entry(fei,
6520 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6521 1,
6522 &a_mpls_o_10_10_11_1),
6523 "24001/neos LB 1 buckets via: "
6524 "adj-mpls over 10.10.11.2");
6525
6526 /*
6527 * test that the pre-failover load-balance has been in-place
6528 * modified
6529 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006530 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006531 fib_entry_contribute_forwarding(fei,
6532 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6533 &current);
6534
6535 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6536 &current),
6537 "PIC-core LB inplace modified %U %U",
6538 format_dpo_id, &non_eos_1_1_1_1, 0,
6539 format_dpo_id, &current, 0);
6540
6541 dpo_reset(&non_eos_1_1_1_1);
6542 dpo_reset(&current);
6543
6544 /*
6545 * no-shut the link with the valid label
6546 */
6547 vnet_sw_interface_set_flags(vnet_get_main(),
6548 tm->hw[0]->sw_if_index,
6549 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6550
6551 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6552 FIB_TEST(fib_test_validate_entry(fei,
6553 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6554 16, // 3 choices spread over 16 buckets
6555 &l99_eos_o_10_10_10_1,
6556 &l99_eos_o_10_10_10_1,
6557 &l99_eos_o_10_10_10_1,
6558 &l99_eos_o_10_10_10_1,
6559 &l99_eos_o_10_10_10_1,
6560 &l99_eos_o_10_10_10_1,
6561 &a_o_10_10_11_1,
6562 &a_o_10_10_11_1,
6563 &a_o_10_10_11_1,
6564 &a_o_10_10_11_1,
6565 &a_o_10_10_11_1,
6566 &adj_o_10_10_11_2,
6567 &adj_o_10_10_11_2,
6568 &adj_o_10_10_11_2,
6569 &adj_o_10_10_11_2,
6570 &adj_o_10_10_11_2),
6571 "1.1.1.1/32 LB 16 buckets via: "
6572 "label 99 over 10.10.10.1, "
6573 "adj over 10.10.11.1",
6574 "adj-v4 over 10.10.11.2");
6575
6576
6577 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6578 &pfx_24001_eos);
6579 FIB_TEST(fib_test_validate_entry(fei,
6580 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6581 16, // 3 choices spread over 16 buckets
6582 &l99_eos_o_10_10_10_1,
6583 &l99_eos_o_10_10_10_1,
6584 &l99_eos_o_10_10_10_1,
6585 &l99_eos_o_10_10_10_1,
6586 &l99_eos_o_10_10_10_1,
6587 &l99_eos_o_10_10_10_1,
6588 &a_o_10_10_11_1,
6589 &a_o_10_10_11_1,
6590 &a_o_10_10_11_1,
6591 &a_o_10_10_11_1,
6592 &a_o_10_10_11_1,
6593 &adj_o_10_10_11_2,
6594 &adj_o_10_10_11_2,
6595 &adj_o_10_10_11_2,
6596 &adj_o_10_10_11_2,
6597 &adj_o_10_10_11_2),
6598 "24001/eos LB 16 buckets via: "
6599 "label 99 over 10.10.10.1, "
6600 "adj over 10.10.11.1",
6601 "adj-v4 over 10.10.11.2");
6602
6603 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6604 &pfx_24001_neos);
6605 FIB_TEST(fib_test_validate_entry(fei,
6606 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6607 2,
6608 &l99_neos_o_10_10_10_1,
6609 &a_mpls_o_10_10_11_1),
6610 "24001/neos LB 2 buckets via: "
6611 "label 99 over 10.10.10.1, "
6612 "adj-mpls over 10.10.11.2");
6613
6614 /*
6615 * remove the first path with the valid label
6616 */
6617 fib_table_entry_path_remove(fib_index,
6618 &pfx_1_1_1_1_s_32,
6619 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006620 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006621 &nh_10_10_10_1,
6622 tm->hw[0]->sw_if_index,
6623 ~0, // invalid fib index
6624 1,
6625 FIB_ROUTE_PATH_FLAG_NONE);
6626
6627 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6628 FIB_TEST(fib_test_validate_entry(fei,
6629 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6630 2,
6631 &a_o_10_10_11_1,
6632 &adj_o_10_10_11_2),
6633 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006634 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006635 "adj-v4 over 10.10.11.2");
6636
6637 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6638 &pfx_24001_eos);
6639 FIB_TEST(fib_test_validate_entry(fei,
6640 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6641 2,
6642 &a_o_10_10_11_1,
6643 &adj_o_10_10_11_2),
6644 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006645 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006646 "adj-v4 over 10.10.11.2");
6647
6648 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6649 &pfx_24001_neos);
6650
6651 FIB_TEST(fib_test_validate_entry(fei,
6652 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6653 1,
6654 &a_mpls_o_10_10_11_1),
6655 "24001/neos LB 1 buckets via: "
6656 "adj-mpls over 10.10.11.2");
6657
6658 /*
6659 * remove the other path with a valid label
6660 */
6661 fib_test_lb_bucket_t bucket_drop = {
6662 .type = FT_LB_SPECIAL,
6663 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00006664 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006665 },
6666 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006667 fib_test_lb_bucket_t mpls_bucket_drop = {
6668 .type = FT_LB_SPECIAL,
6669 .special = {
6670 .adj = DPO_PROTO_MPLS,
6671 },
6672 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006673
6674 fib_table_entry_path_remove(fib_index,
6675 &pfx_1_1_1_1_s_32,
6676 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006677 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006678 &nh_10_10_11_1,
6679 tm->hw[1]->sw_if_index,
6680 ~0, // invalid fib index
6681 1,
6682 FIB_ROUTE_PATH_FLAG_NONE);
6683
6684 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6685 FIB_TEST(fib_test_validate_entry(fei,
6686 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6687 1,
6688 &adj_o_10_10_11_2),
6689 "1.1.1.1/32 LB 1 buckets via: "
6690 "adj over 10.10.11.2");
6691
6692 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6693 &pfx_24001_eos);
6694 FIB_TEST(fib_test_validate_entry(fei,
6695 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6696 1,
6697 &adj_o_10_10_11_2),
6698 "24001/eos LB 1 buckets via: "
6699 "adj over 10.10.11.2");
6700
6701 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6702 &pfx_24001_neos);
6703 FIB_TEST(fib_test_validate_entry(fei,
6704 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006705 1,
6706 &mpls_bucket_drop),
6707 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006708
6709 /*
6710 * add back the path with the valid label
6711 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006712 l99 = NULL;
6713 vec_add1(l99, 99);
6714
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006715 fib_table_entry_path_add(fib_index,
6716 &pfx_1_1_1_1_s_32,
6717 FIB_SOURCE_API,
6718 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006719 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006720 &nh_10_10_10_1,
6721 tm->hw[0]->sw_if_index,
6722 ~0, // invalid fib index
6723 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006724 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006725 FIB_ROUTE_PATH_FLAG_NONE);
6726
6727 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6728 FIB_TEST(fib_test_validate_entry(fei,
6729 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6730 2,
6731 &l99_eos_o_10_10_10_1,
6732 &adj_o_10_10_11_2),
6733 "1.1.1.1/32 LB 2 buckets via: "
6734 "label 99 over 10.10.10.1, "
6735 "adj over 10.10.11.2");
6736
6737 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6738 &pfx_24001_eos);
6739 FIB_TEST(fib_test_validate_entry(fei,
6740 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6741 2,
6742 &l99_eos_o_10_10_10_1,
6743 &adj_o_10_10_11_2),
6744 "24001/eos LB 2 buckets via: "
6745 "label 99 over 10.10.10.1, "
6746 "adj over 10.10.11.2");
6747
6748 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6749 &pfx_24001_neos);
6750 FIB_TEST(fib_test_validate_entry(fei,
6751 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6752 1,
6753 &l99_neos_o_10_10_10_1),
6754 "24001/neos LB 1 buckets via: "
6755 "label 99 over 10.10.10.1");
6756
6757 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006758 * change the local label
6759 */
6760 fib_table_entry_local_label_add(fib_index,
6761 &pfx_1_1_1_1_s_32,
6762 25005);
6763
6764 fib_prefix_t pfx_25005_eos = {
6765 .fp_proto = FIB_PROTOCOL_MPLS,
6766 .fp_label = 25005,
6767 .fp_eos = MPLS_EOS,
6768 };
6769 fib_prefix_t pfx_25005_neos = {
6770 .fp_proto = FIB_PROTOCOL_MPLS,
6771 .fp_label = 25005,
6772 .fp_eos = MPLS_NON_EOS,
6773 };
6774
6775 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6776 fib_table_lookup(fib_index, &pfx_24001_eos)),
6777 "24001/eos removed after label change");
6778 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6779 fib_table_lookup(fib_index, &pfx_24001_neos)),
6780 "24001/eos removed after label change");
6781
6782 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6783 &pfx_25005_eos);
6784 FIB_TEST(fib_test_validate_entry(fei,
6785 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6786 2,
6787 &l99_eos_o_10_10_10_1,
6788 &adj_o_10_10_11_2),
6789 "25005/eos LB 2 buckets via: "
6790 "label 99 over 10.10.10.1, "
6791 "adj over 10.10.11.2");
6792
6793 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6794 &pfx_25005_neos);
6795 FIB_TEST(fib_test_validate_entry(fei,
6796 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6797 1,
6798 &l99_neos_o_10_10_10_1),
6799 "25005/neos LB 1 buckets via: "
6800 "label 99 over 10.10.10.1");
6801
6802 /*
6803 * remove the local label.
6804 * the check that the MPLS entries are gone is done by the fact the
6805 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006806 */
6807 fib_table_entry_local_label_remove(fib_index,
6808 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006809 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006810
6811 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6812 FIB_TEST(fib_test_validate_entry(fei,
6813 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6814 2,
6815 &l99_eos_o_10_10_10_1,
6816 &adj_o_10_10_11_2),
6817 "24001/eos LB 2 buckets via: "
6818 "label 99 over 10.10.10.1, "
6819 "adj over 10.10.11.2");
6820
6821 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6822 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6823 "No more MPLS FIB entries => table removed");
6824
6825 /*
6826 * add another via-entry for the recursive
6827 */
6828 fib_prefix_t pfx_1_1_1_2_s_32 = {
6829 .fp_len = 32,
6830 .fp_proto = FIB_PROTOCOL_IP4,
6831 .fp_addr = {
6832 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6833 },
6834 };
6835 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6836 .type = FT_LB_LABEL_O_ADJ,
6837 .label_o_adj = {
6838 .adj = ai_mpls_10_10_10_1,
6839 .label = 101,
6840 .eos = MPLS_EOS,
6841 },
6842 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006843 mpls_label_t *l101 = NULL;
6844 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006845
6846 fei = fib_table_entry_update_one_path(fib_index,
6847 &pfx_1_1_1_2_s_32,
6848 FIB_SOURCE_API,
6849 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006850 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006851 &nh_10_10_10_1,
6852 tm->hw[0]->sw_if_index,
6853 ~0, // invalid fib index
6854 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006855 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006856 FIB_ROUTE_PATH_FLAG_NONE);
6857
6858 FIB_TEST(fib_test_validate_entry(fei,
6859 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6860 1,
6861 &l101_eos_o_10_10_10_1),
6862 "1.1.1.2/32 LB 1 buckets via: "
6863 "label 101 over 10.10.10.1");
6864
Neale Ranns948e00f2016-10-20 13:39:34 +01006865 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006866 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6867 &pfx_1_1_1_1_s_32),
6868 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6869 &non_eos_1_1_1_1);
6870 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6871 &pfx_1_1_1_2_s_32),
6872 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6873 &non_eos_1_1_1_2);
6874
6875 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6876 .type = FT_LB_LABEL_O_LB,
6877 .label_o_lb = {
6878 .lb = non_eos_1_1_1_2.dpoi_index,
6879 .label = 1601,
6880 .eos = MPLS_EOS,
6881 },
6882 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006883 mpls_label_t *l1601 = NULL;
6884 vec_add1(l1601, 1601);
6885
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006886 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6887
6888 fei = fib_table_entry_path_add(fib_index,
6889 &pfx_2_2_2_2_s_32,
6890 FIB_SOURCE_API,
6891 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006892 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006893 &pfx_1_1_1_2_s_32.fp_addr,
6894 ~0,
6895 fib_index,
6896 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006897 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006898 FIB_ROUTE_PATH_FLAG_NONE);
6899
6900 FIB_TEST(fib_test_validate_entry(fei,
6901 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6902 2,
6903 &l1600_eos_o_1_1_1_1,
6904 &l1601_eos_o_1_1_1_2),
6905 "2.2.2.2/32 LB 2 buckets via: "
6906 "label 1600 via 1.1,1.1, "
6907 "label 16001 via 1.1.1.2");
6908
6909 /*
6910 * update the via-entry so it no longer has an imp-null path.
6911 * the LB for the recursive can use an imp-null
6912 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006913 l_imp_null = NULL;
6914 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6915
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006916 fei = fib_table_entry_update_one_path(fib_index,
6917 &pfx_1_1_1_2_s_32,
6918 FIB_SOURCE_API,
6919 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006920 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006921 &nh_10_10_11_1,
6922 tm->hw[1]->sw_if_index,
6923 ~0, // invalid fib index
6924 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006925 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006926 FIB_ROUTE_PATH_FLAG_NONE);
6927
6928 FIB_TEST(fib_test_validate_entry(fei,
6929 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6930 1,
6931 &a_o_10_10_11_1),
6932 "1.1.1.2/32 LB 1 buckets via: "
6933 "adj 10.10.11.1");
6934
6935 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6936 FIB_TEST(fib_test_validate_entry(fei,
6937 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6938 2,
6939 &l1600_eos_o_1_1_1_1,
6940 &l1601_eos_o_1_1_1_2),
6941 "2.2.2.2/32 LB 2 buckets via: "
6942 "label 1600 via 1.1,1.1, "
6943 "label 16001 via 1.1.1.2");
6944
6945 /*
6946 * update the via-entry so it no longer has labelled paths.
6947 * the LB for the recursive should exclue this via form its LB
6948 */
6949 fei = fib_table_entry_update_one_path(fib_index,
6950 &pfx_1_1_1_2_s_32,
6951 FIB_SOURCE_API,
6952 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006953 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006954 &nh_10_10_11_1,
6955 tm->hw[1]->sw_if_index,
6956 ~0, // invalid fib index
6957 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006958 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006959 FIB_ROUTE_PATH_FLAG_NONE);
6960
6961 FIB_TEST(fib_test_validate_entry(fei,
6962 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6963 1,
6964 &a_o_10_10_11_1),
6965 "1.1.1.2/32 LB 1 buckets via: "
6966 "adj 10.10.11.1");
6967
6968 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6969 FIB_TEST(fib_test_validate_entry(fei,
6970 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6971 1,
6972 &l1600_eos_o_1_1_1_1),
6973 "2.2.2.2/32 LB 1 buckets via: "
6974 "label 1600 via 1.1,1.1");
6975
6976 dpo_reset(&non_eos_1_1_1_1);
6977 dpo_reset(&non_eos_1_1_1_2);
6978
6979 /*
6980 * Add a recursive with no out-labels. We expect to use the IP of the via
6981 */
6982 fib_prefix_t pfx_2_2_2_3_s_32 = {
6983 .fp_len = 32,
6984 .fp_proto = FIB_PROTOCOL_IP4,
6985 .fp_addr = {
6986 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6987 },
6988 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006989 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006990
6991 fib_table_entry_update_one_path(fib_index,
6992 &pfx_2_2_2_3_s_32,
6993 FIB_SOURCE_API,
6994 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006995 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006996 &pfx_1_1_1_1_s_32.fp_addr,
6997 ~0,
6998 fib_index,
6999 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007000 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007001 FIB_ROUTE_PATH_FLAG_NONE);
7002
7003 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7004 &pfx_1_1_1_1_s_32),
7005 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7006 &ip_1_1_1_1);
7007
7008 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7009 .type = FT_LB_O_LB,
7010 .lb = {
7011 .lb = ip_1_1_1_1.dpoi_index,
7012 },
7013 };
7014
7015 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7016 FIB_TEST(fib_test_validate_entry(fei,
7017 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7018 1,
7019 &ip_o_1_1_1_1),
7020 "2.2.2.2.3/32 LB 1 buckets via: "
7021 "ip 1.1.1.1");
7022
7023 /*
7024 * Add a recursive with an imp-null out-label.
7025 * We expect to use the IP of the via
7026 */
7027 fib_prefix_t pfx_2_2_2_4_s_32 = {
7028 .fp_len = 32,
7029 .fp_proto = FIB_PROTOCOL_IP4,
7030 .fp_addr = {
7031 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7032 },
7033 };
7034
7035 fib_table_entry_update_one_path(fib_index,
7036 &pfx_2_2_2_4_s_32,
7037 FIB_SOURCE_API,
7038 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007039 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007040 &pfx_1_1_1_1_s_32.fp_addr,
7041 ~0,
7042 fib_index,
7043 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007044 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007045 FIB_ROUTE_PATH_FLAG_NONE);
7046
7047 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7048 FIB_TEST(fib_test_validate_entry(fei,
7049 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7050 1,
7051 &ip_o_1_1_1_1),
7052 "2.2.2.2.4/32 LB 1 buckets via: "
7053 "ip 1.1.1.1");
7054
7055 dpo_reset(&ip_1_1_1_1);
7056
7057 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00007058 * Create an entry with a deep label stack
7059 */
7060 fib_prefix_t pfx_2_2_5_5_s_32 = {
7061 .fp_len = 32,
7062 .fp_proto = FIB_PROTOCOL_IP4,
7063 .fp_addr = {
7064 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7065 },
7066 };
7067 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7068 .type = FT_LB_LABEL_STACK_O_ADJ,
7069 .label_stack_o_adj = {
7070 .adj = ai_mpls_10_10_11_1,
7071 .label_stack_size = 8,
7072 .label_stack = {
7073 200, 201, 202, 203, 204, 205, 206, 207
7074 },
7075 .eos = MPLS_EOS,
7076 },
7077 };
7078 mpls_label_t *label_stack = NULL;
7079 vec_validate(label_stack, 7);
7080 for (ii = 0; ii < 8; ii++)
7081 {
7082 label_stack[ii] = ii + 200;
7083 }
7084
7085 fei = fib_table_entry_update_one_path(fib_index,
7086 &pfx_2_2_5_5_s_32,
7087 FIB_SOURCE_API,
7088 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007089 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00007090 &nh_10_10_11_1,
7091 tm->hw[1]->sw_if_index,
7092 ~0, // invalid fib index
7093 1,
7094 label_stack,
7095 FIB_ROUTE_PATH_FLAG_NONE);
7096
7097 FIB_TEST(fib_test_validate_entry(fei,
7098 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7099 1,
7100 &ls_eos_o_10_10_10_1),
7101 "2.2.5.5/32 LB 1 buckets via: "
7102 "adj 10.10.11.1");
7103 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7104
7105 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007106 * cleanup
7107 */
7108 fib_table_entry_delete(fib_index,
7109 &pfx_1_1_1_2_s_32,
7110 FIB_SOURCE_API);
7111
7112 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7113 FIB_TEST(fib_test_validate_entry(fei,
7114 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7115 1,
7116 &l1600_eos_o_1_1_1_1),
7117 "2.2.2.2/32 LB 1 buckets via: "
7118 "label 1600 via 1.1,1.1");
7119
7120 fib_table_entry_delete(fib_index,
7121 &pfx_1_1_1_1_s_32,
7122 FIB_SOURCE_API);
7123
7124 FIB_TEST(fib_test_validate_entry(fei,
7125 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7126 1,
7127 &bucket_drop),
7128 "2.2.2.2/32 LB 1 buckets via: DROP");
7129
7130 fib_table_entry_delete(fib_index,
7131 &pfx_2_2_2_2_s_32,
7132 FIB_SOURCE_API);
7133 fib_table_entry_delete(fib_index,
7134 &pfx_2_2_2_3_s_32,
7135 FIB_SOURCE_API);
7136 fib_table_entry_delete(fib_index,
7137 &pfx_2_2_2_4_s_32,
7138 FIB_SOURCE_API);
7139
7140 adj_unlock(ai_mpls_10_10_10_1);
7141 adj_unlock(ai_mpls_10_10_11_2);
7142 adj_unlock(ai_v4_10_10_11_1);
7143 adj_unlock(ai_v4_10_10_11_2);
7144 adj_unlock(ai_mpls_10_10_11_1);
7145
7146 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7147 adj_nbr_db_size());
7148
7149 local0_pfx.fp_len = 32;
7150 fib_table_entry_delete(fib_index,
7151 &local0_pfx,
7152 FIB_SOURCE_INTERFACE);
7153 local0_pfx.fp_len = 24;
7154 fib_table_entry_delete(fib_index,
7155 &local0_pfx,
7156 FIB_SOURCE_INTERFACE);
7157 local1_pfx.fp_len = 32;
7158 fib_table_entry_delete(fib_index,
7159 &local1_pfx,
7160 FIB_SOURCE_INTERFACE);
7161 local1_pfx.fp_len = 24;
7162 fib_table_entry_delete(fib_index,
7163 &local1_pfx,
7164 FIB_SOURCE_INTERFACE);
7165
7166 /*
7167 * +1 for the drop LB in the MPLS tables.
7168 */
7169 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7170 "Load-balance resources freed %d of %d",
7171 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007172
7173 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007174}
7175
7176#define N_TEST_CHILDREN 4
7177#define PARENT_INDEX 0
7178
7179typedef struct fib_node_test_t_
7180{
7181 fib_node_t node;
7182 u32 sibling;
7183 u32 index;
7184 fib_node_back_walk_ctx_t *ctxs;
7185 u32 destroyed;
7186} fib_node_test_t;
7187
7188static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7189
7190#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7191
7192#define FOR_EACH_TEST_CHILD(_tc) \
7193 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7194 ii < N_TEST_CHILDREN+1; \
7195 ii++, (_tc) = &fib_test_nodes[ii])
7196
7197static fib_node_t *
7198fib_test_child_get_node (fib_node_index_t index)
7199{
7200 return (&fib_test_nodes[index].node);
7201}
7202
7203static int fib_test_walk_spawns_walks;
7204
7205static fib_node_back_walk_rc_t
7206fib_test_child_back_walk_notify (fib_node_t *node,
7207 fib_node_back_walk_ctx_t *ctx)
7208{
7209 fib_node_test_t *tc = (fib_node_test_t*) node;
7210
7211 vec_add1(tc->ctxs, *ctx);
7212
7213 if (1 == fib_test_walk_spawns_walks)
7214 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7215 if (2 == fib_test_walk_spawns_walks)
7216 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7217 FIB_WALK_PRIORITY_HIGH, ctx);
7218
7219 return (FIB_NODE_BACK_WALK_CONTINUE);
7220}
7221
7222static void
7223fib_test_child_last_lock_gone (fib_node_t *node)
7224{
7225 fib_node_test_t *tc = (fib_node_test_t *)node;
7226
7227 tc->destroyed = 1;
7228}
7229
7230/**
7231 * The FIB walk's graph node virtual function table
7232 */
7233static const fib_node_vft_t fib_test_child_vft = {
7234 .fnv_get = fib_test_child_get_node,
7235 .fnv_last_lock = fib_test_child_last_lock_gone,
7236 .fnv_back_walk = fib_test_child_back_walk_notify,
7237};
7238
7239/*
7240 * the function (that should have been static but isn't so I can do this)
7241 * that processes the walk from the async queue,
7242 */
7243f64 fib_walk_process_queues(vlib_main_t * vm,
7244 const f64 quota);
7245u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7246
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007247static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007248fib_test_walk (void)
7249{
7250 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7251 fib_node_test_t *tc;
7252 vlib_main_t *vm;
7253 u32 ii;
7254
7255 vm = vlib_get_main();
7256 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7257
7258 /*
7259 * init a fake node on which we will add children
7260 */
7261 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7262 FIB_NODE_TYPE_TEST);
7263
7264 FOR_EACH_TEST_CHILD(tc)
7265 {
7266 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7267 fib_node_lock(&tc->node);
7268 tc->ctxs = NULL;
7269 tc->index = ii;
7270 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7271 PARENT_INDEX,
7272 FIB_NODE_TYPE_TEST, ii);
7273 }
7274
7275 /*
7276 * enqueue a walk across the parents children.
7277 */
Neale Ranns450cd302016-11-09 17:49:42 +00007278 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007279
7280 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7281 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7282 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7283 "Parent has %d children pre-walk",
7284 fib_node_list_get_size(PARENT()->fn_children));
7285
7286 /*
7287 * give the walk a large amount of time so it gets to the end
7288 */
7289 fib_walk_process_queues(vm, 1);
7290
7291 FOR_EACH_TEST_CHILD(tc)
7292 {
7293 FIB_TEST(1 == vec_len(tc->ctxs),
7294 "%d child visitsed %d times",
7295 ii, vec_len(tc->ctxs));
7296 vec_free(tc->ctxs);
7297 }
7298 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7299 "Queue is empty post walk");
7300 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7301 "Parent has %d children post walk",
7302 fib_node_list_get_size(PARENT()->fn_children));
7303
7304 /*
7305 * walk again. should be no increase in the number of visits, since
7306 * the walk will have terminated.
7307 */
7308 fib_walk_process_queues(vm, 1);
7309
7310 FOR_EACH_TEST_CHILD(tc)
7311 {
7312 FIB_TEST(0 == vec_len(tc->ctxs),
7313 "%d child visitsed %d times",
7314 ii, vec_len(tc->ctxs));
7315 }
7316
7317 /*
7318 * schedule a low and hig priority walk. expect the high to be performed
7319 * before the low.
7320 * schedule the high prio walk first so that it is further from the head
7321 * of the dependency list. that way it won't merge with the low one.
7322 */
7323 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7324 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7325
7326 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7327 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7328 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7329 FIB_WALK_PRIORITY_LOW, &low_ctx);
7330
7331 fib_walk_process_queues(vm, 1);
7332
7333 FOR_EACH_TEST_CHILD(tc)
7334 {
7335 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7336 "%d child visitsed by high prio walk", ii);
7337 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7338 "%d child visitsed by low prio walk", ii);
7339 vec_free(tc->ctxs);
7340 }
7341 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7342 "Queue is empty post prio walk");
7343 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7344 "Parent has %d children post prio walk",
7345 fib_node_list_get_size(PARENT()->fn_children));
7346
7347 /*
7348 * schedule 2 walks of the same priority that can be megred.
7349 * expect that each child is thus visited only once.
7350 */
7351 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7352 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7353
7354 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7355 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7356 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7357 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7358
7359 fib_walk_process_queues(vm, 1);
7360
7361 FOR_EACH_TEST_CHILD(tc)
7362 {
7363 FIB_TEST(1 == vec_len(tc->ctxs),
7364 "%d child visitsed %d times during merge walk",
7365 ii, vec_len(tc->ctxs));
7366 vec_free(tc->ctxs);
7367 }
7368 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7369 "Queue is empty post merge walk");
7370 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7371 "Parent has %d children post merge walk",
7372 fib_node_list_get_size(PARENT()->fn_children));
7373
7374 /*
7375 * schedule 2 walks of the same priority that cannot be megred.
7376 * expect that each child is thus visited twice and in the order
7377 * in which the walks were scheduled.
7378 */
7379 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7380 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7381
7382 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7383 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7384 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7385 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7386
7387 fib_walk_process_queues(vm, 1);
7388
7389 FOR_EACH_TEST_CHILD(tc)
7390 {
7391 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7392 "%d child visitsed by high prio walk", ii);
7393 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7394 "%d child visitsed by low prio walk", ii);
7395 vec_free(tc->ctxs);
7396 }
7397 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7398 "Queue is empty post no-merge walk");
7399 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7400 "Parent has %d children post no-merge walk",
7401 fib_node_list_get_size(PARENT()->fn_children));
7402
7403 /*
7404 * schedule a walk that makes one one child progress.
7405 * we do this by giving the queue draining process zero
7406 * time quanta. it's a do..while loop, so it does something.
7407 */
Neale Ranns450cd302016-11-09 17:49:42 +00007408 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007409
7410 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7411 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7412 fib_walk_process_queues(vm, 0);
7413
7414 FOR_EACH_TEST_CHILD(tc)
7415 {
7416 if (ii == N_TEST_CHILDREN)
7417 {
7418 FIB_TEST(1 == vec_len(tc->ctxs),
7419 "%d child visitsed %d times in zero quanta walk",
7420 ii, vec_len(tc->ctxs));
7421 }
7422 else
7423 {
7424 FIB_TEST(0 == vec_len(tc->ctxs),
7425 "%d child visitsed %d times in 0 quanta walk",
7426 ii, vec_len(tc->ctxs));
7427 }
7428 }
7429 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7430 "Queue is not empty post zero quanta walk");
7431 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7432 "Parent has %d children post zero qunta walk",
7433 fib_node_list_get_size(PARENT()->fn_children));
7434
7435 /*
7436 * another one step
7437 */
7438 fib_walk_process_queues(vm, 0);
7439
7440 FOR_EACH_TEST_CHILD(tc)
7441 {
7442 if (ii >= N_TEST_CHILDREN-1)
7443 {
7444 FIB_TEST(1 == vec_len(tc->ctxs),
7445 "%d child visitsed %d times in 2nd zero quanta walk",
7446 ii, vec_len(tc->ctxs));
7447 }
7448 else
7449 {
7450 FIB_TEST(0 == vec_len(tc->ctxs),
7451 "%d child visitsed %d times in 2nd 0 quanta walk",
7452 ii, vec_len(tc->ctxs));
7453 }
7454 }
7455 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7456 "Queue is not empty post zero quanta walk");
7457 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7458 "Parent has %d children post zero qunta walk",
7459 fib_node_list_get_size(PARENT()->fn_children));
7460
7461 /*
7462 * schedule another walk that will catch-up and merge.
7463 */
7464 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7465 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7466 fib_walk_process_queues(vm, 1);
7467
7468 FOR_EACH_TEST_CHILD(tc)
7469 {
7470 if (ii >= N_TEST_CHILDREN-1)
7471 {
7472 FIB_TEST(2 == vec_len(tc->ctxs),
7473 "%d child visitsed %d times in 2nd zero quanta merge walk",
7474 ii, vec_len(tc->ctxs));
7475 vec_free(tc->ctxs);
7476 }
7477 else
7478 {
7479 FIB_TEST(1 == vec_len(tc->ctxs),
7480 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7481 ii, vec_len(tc->ctxs));
7482 vec_free(tc->ctxs);
7483 }
7484 }
7485 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7486 "Queue is not empty post 2nd zero quanta merge walk");
7487 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7488 "Parent has %d children post 2nd zero qunta merge walk",
7489 fib_node_list_get_size(PARENT()->fn_children));
7490
7491 /*
7492 * park a async walk in the middle of the list, then have an sync walk catch
7493 * it. same expectations as async catches async.
7494 */
Neale Ranns450cd302016-11-09 17:49:42 +00007495 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007496
7497 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7498 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7499
7500 fib_walk_process_queues(vm, 0);
7501 fib_walk_process_queues(vm, 0);
7502
7503 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7504
7505 FOR_EACH_TEST_CHILD(tc)
7506 {
7507 if (ii >= N_TEST_CHILDREN-1)
7508 {
7509 FIB_TEST(2 == vec_len(tc->ctxs),
7510 "%d child visitsed %d times in sync catches async walk",
7511 ii, vec_len(tc->ctxs));
7512 vec_free(tc->ctxs);
7513 }
7514 else
7515 {
7516 FIB_TEST(1 == vec_len(tc->ctxs),
7517 "%d child visitsed %d times in sync catches async walk",
7518 ii, vec_len(tc->ctxs));
7519 vec_free(tc->ctxs);
7520 }
7521 }
7522 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7523 "Queue is not empty post 2nd zero quanta merge walk");
7524 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7525 "Parent has %d children post 2nd zero qunta merge walk",
7526 fib_node_list_get_size(PARENT()->fn_children));
7527
7528 /*
7529 * make the parent a child of one of its children, thus inducing a routing loop.
7530 */
7531 fib_test_nodes[PARENT_INDEX].sibling =
7532 fib_node_child_add(FIB_NODE_TYPE_TEST,
7533 1, // the first child
7534 FIB_NODE_TYPE_TEST,
7535 PARENT_INDEX);
7536
7537 /*
7538 * execute a sync walk from the parent. each child visited spawns more sync
7539 * walks. we expect the walk to terminate.
7540 */
7541 fib_test_walk_spawns_walks = 1;
7542
7543 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7544
7545 FOR_EACH_TEST_CHILD(tc)
7546 {
7547 /*
7548 * child 1 - which is last in the list - has the loop.
7549 * the other children a re thus visitsed first. the we meet
7550 * child 1. we go round the loop again, visting the other children.
7551 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7552 * again.
7553 */
7554 if (1 == ii)
7555 {
7556 FIB_TEST(1 == vec_len(tc->ctxs),
7557 "child %d visitsed %d times during looped sync walk",
7558 ii, vec_len(tc->ctxs));
7559 }
7560 else
7561 {
7562 FIB_TEST(2 == vec_len(tc->ctxs),
7563 "child %d visitsed %d times during looped sync walk",
7564 ii, vec_len(tc->ctxs));
7565 }
7566 vec_free(tc->ctxs);
7567 }
7568 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7569 "Parent has %d children post sync loop walk",
7570 fib_node_list_get_size(PARENT()->fn_children));
7571
7572 /*
7573 * the walk doesn't reach the max depth because the infra knows that sync
7574 * meets sync implies a loop and bails early.
7575 */
7576 FIB_TEST(high_ctx.fnbw_depth == 9,
7577 "Walk context depth %d post sync loop walk",
7578 high_ctx.fnbw_depth);
7579
7580 /*
7581 * execute an async walk of the graph loop, with each child spawns sync walks
7582 */
7583 high_ctx.fnbw_depth = 0;
7584 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7585 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7586
7587 fib_walk_process_queues(vm, 1);
7588
7589 FOR_EACH_TEST_CHILD(tc)
7590 {
7591 /*
7592 * we don't really care how many times the children are visisted, as long as
7593 * it is more than once.
7594 */
7595 FIB_TEST(1 <= vec_len(tc->ctxs),
7596 "child %d visitsed %d times during looped aync spawns sync walk",
7597 ii, vec_len(tc->ctxs));
7598 vec_free(tc->ctxs);
7599 }
7600
7601 /*
7602 * execute an async walk of the graph loop, with each child spawns async walks
7603 */
7604 fib_test_walk_spawns_walks = 2;
7605 high_ctx.fnbw_depth = 0;
7606 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7607 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7608
7609 fib_walk_process_queues(vm, 1);
7610
7611 FOR_EACH_TEST_CHILD(tc)
7612 {
7613 /*
7614 * we don't really care how many times the children are visisted, as long as
7615 * it is more than once.
7616 */
7617 FIB_TEST(1 <= vec_len(tc->ctxs),
7618 "child %d visitsed %d times during looped async spawns async walk",
7619 ii, vec_len(tc->ctxs));
7620 vec_free(tc->ctxs);
7621 }
7622
7623
7624 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7625 1, // the first child
7626 fib_test_nodes[PARENT_INDEX].sibling);
7627
7628 /*
7629 * cleanup
7630 */
7631 FOR_EACH_TEST_CHILD(tc)
7632 {
7633 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7634 tc->sibling);
7635 fib_node_deinit(&tc->node);
7636 fib_node_unlock(&tc->node);
7637 }
7638 fib_node_deinit(PARENT());
7639
7640 /*
7641 * The parent will be destroyed when the last lock on it goes.
7642 * this test ensures all the walk objects are unlocking it.
7643 */
7644 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7645 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007646
7647 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007648}
7649
Neale Ranns88fc83e2017-04-05 08:11:14 -07007650/*
7651 * declaration of the otherwise static callback functions
7652 */
7653void fib_bfd_notify (bfd_listen_event_e event,
7654 const bfd_session_t *session);
7655void adj_bfd_notify (bfd_listen_event_e event,
7656 const bfd_session_t *session);
7657
7658/**
7659 * Test BFD session interaction with FIB
7660 */
7661static int
7662fib_test_bfd (void)
7663{
7664 fib_node_index_t fei;
7665 test_main_t *tm;
7666 int n_feis;
7667
7668 /* via 10.10.10.1 */
7669 ip46_address_t nh_10_10_10_1 = {
7670 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7671 };
7672 /* via 10.10.10.2 */
7673 ip46_address_t nh_10_10_10_2 = {
7674 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7675 };
7676 /* via 10.10.10.10 */
7677 ip46_address_t nh_10_10_10_10 = {
7678 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7679 };
7680 n_feis = fib_entry_pool_size();
7681
7682 tm = &test_main;
7683
7684 /*
7685 * add interface routes. we'll assume this works. it's tested elsewhere
7686 */
7687 fib_prefix_t pfx_10_10_10_10_s_24 = {
7688 .fp_len = 24,
7689 .fp_proto = FIB_PROTOCOL_IP4,
7690 .fp_addr = nh_10_10_10_10,
7691 };
7692
7693 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7694 FIB_SOURCE_INTERFACE,
7695 (FIB_ENTRY_FLAG_CONNECTED |
7696 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07007697 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007698 NULL,
7699 tm->hw[0]->sw_if_index,
7700 ~0, // invalid fib index
7701 1, // weight
7702 NULL,
7703 FIB_ROUTE_PATH_FLAG_NONE);
7704
7705 fib_prefix_t pfx_10_10_10_10_s_32 = {
7706 .fp_len = 32,
7707 .fp_proto = FIB_PROTOCOL_IP4,
7708 .fp_addr = nh_10_10_10_10,
7709 };
7710 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7711 FIB_SOURCE_INTERFACE,
7712 (FIB_ENTRY_FLAG_CONNECTED |
7713 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07007714 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007715 NULL,
7716 tm->hw[0]->sw_if_index,
7717 ~0, // invalid fib index
7718 1, // weight
7719 NULL,
7720 FIB_ROUTE_PATH_FLAG_NONE);
7721
7722 /*
7723 * A BFD session via a neighbour we do not yet know
7724 */
7725 bfd_session_t bfd_10_10_10_1 = {
7726 .udp = {
7727 .key = {
7728 .fib_index = 0,
7729 .peer_addr = nh_10_10_10_1,
7730 },
7731 },
7732 .hop_type = BFD_HOP_TYPE_MULTI,
7733 .local_state = BFD_STATE_init,
7734 };
7735
7736 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7737
7738 /*
7739 * A new entry will be created that forwards via the adj
7740 */
7741 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7742 VNET_LINK_IP4,
7743 &nh_10_10_10_1,
7744 tm->hw[0]->sw_if_index);
7745 fib_prefix_t pfx_10_10_10_1_s_32 = {
7746 .fp_addr = nh_10_10_10_1,
7747 .fp_len = 32,
7748 .fp_proto = FIB_PROTOCOL_IP4,
7749 };
7750 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7751 .type = FT_LB_ADJ,
7752 .adj = {
7753 .adj = ai_10_10_10_1,
7754 },
7755 };
7756
7757 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7758 FIB_TEST(fib_test_validate_entry(fei,
7759 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7760 1,
7761 &adj_o_10_10_10_1),
7762 "BFD sourced %U via %U",
7763 format_fib_prefix, &pfx_10_10_10_1_s_32,
7764 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7765
7766 /*
7767 * Delete the BFD session. Expect the fib_entry to be removed
7768 */
7769 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7770
7771 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7772 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7773 "BFD sourced %U removed",
7774 format_fib_prefix, &pfx_10_10_10_1_s_32);
7775
7776 /*
7777 * Add the BFD source back
7778 */
7779 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7780
7781 /*
7782 * source the entry via the ADJ fib
7783 */
Neale Ranns81424992017-05-18 03:03:22 -07007784 fei = fib_table_entry_path_add(0,
7785 &pfx_10_10_10_1_s_32,
7786 FIB_SOURCE_ADJ,
7787 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007788 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007789 &nh_10_10_10_1,
7790 tm->hw[0]->sw_if_index,
7791 ~0, // invalid fib index
7792 1,
7793 NULL,
7794 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007795
7796 /*
7797 * Delete the BFD session. Expect the fib_entry to remain
7798 */
7799 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7800
7801 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7802 FIB_TEST(fib_test_validate_entry(fei,
7803 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7804 1,
7805 &adj_o_10_10_10_1),
7806 "BFD sourced %U remains via %U",
7807 format_fib_prefix, &pfx_10_10_10_1_s_32,
7808 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7809
7810 /*
7811 * Add the BFD source back
7812 */
7813 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7814
7815 /*
7816 * Create another ADJ FIB
7817 */
7818 fib_prefix_t pfx_10_10_10_2_s_32 = {
7819 .fp_addr = nh_10_10_10_2,
7820 .fp_len = 32,
7821 .fp_proto = FIB_PROTOCOL_IP4,
7822 };
Neale Ranns81424992017-05-18 03:03:22 -07007823 fib_table_entry_path_add(0,
7824 &pfx_10_10_10_2_s_32,
7825 FIB_SOURCE_ADJ,
7826 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007827 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007828 &nh_10_10_10_2,
7829 tm->hw[0]->sw_if_index,
7830 ~0, // invalid fib index
7831 1,
7832 NULL,
7833 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007834 /*
7835 * A BFD session for the new ADJ FIB
7836 */
7837 bfd_session_t bfd_10_10_10_2 = {
7838 .udp = {
7839 .key = {
7840 .fib_index = 0,
7841 .peer_addr = nh_10_10_10_2,
7842 },
7843 },
7844 .hop_type = BFD_HOP_TYPE_MULTI,
7845 .local_state = BFD_STATE_init,
7846 };
7847
7848 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7849
7850 /*
7851 * remove the adj-fib source whilst the session is present
7852 * then add it back
7853 */
7854 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07007855 fib_table_entry_path_add(0,
7856 &pfx_10_10_10_2_s_32,
7857 FIB_SOURCE_ADJ,
7858 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007859 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007860 &nh_10_10_10_2,
7861 tm->hw[0]->sw_if_index,
7862 ~0, // invalid fib index
7863 1,
7864 NULL,
7865 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007866
7867 /*
7868 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7869 * bring one of the sessions UP, leave the other down
7870 */
7871 bfd_10_10_10_1.local_state = BFD_STATE_up;
7872 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7873 bfd_10_10_10_2.local_state = BFD_STATE_down;
7874 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7875
7876 /*
7877 * A recursive prefix via both of the ADJ FIBs
7878 */
7879 fib_prefix_t pfx_200_0_0_0_s_24 = {
7880 .fp_proto = FIB_PROTOCOL_IP4,
7881 .fp_len = 32,
7882 .fp_addr = {
7883 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7884 },
7885 };
7886 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7887
7888 dpo_10_10_10_1 =
7889 fib_entry_contribute_ip_forwarding(
7890 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7891 dpo_10_10_10_2 =
7892 fib_entry_contribute_ip_forwarding(
7893 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7894
7895 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7896 .type = FT_LB_O_LB,
7897 .lb = {
7898 .lb = dpo_10_10_10_1->dpoi_index,
7899 },
7900 };
7901 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7902 .type = FT_LB_O_LB,
7903 .lb = {
7904 .lb = dpo_10_10_10_2->dpoi_index,
7905 },
7906 };
7907
7908 /*
7909 * A prefix via the adj-fib that is BFD down => DROP
7910 */
7911 fei = fib_table_entry_path_add(0,
7912 &pfx_200_0_0_0_s_24,
7913 FIB_SOURCE_API,
7914 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007915 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007916 &nh_10_10_10_2,
7917 ~0, // recursive
7918 0, // default fib index
7919 1,
7920 NULL,
7921 FIB_ROUTE_PATH_FLAG_NONE);
7922 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7923 "%U resolves via drop",
7924 format_fib_prefix, &pfx_200_0_0_0_s_24);
7925
7926 /*
7927 * add a path via the UP BFD adj-fib.
7928 * we expect that the DOWN BFD ADJ FIB is not used.
7929 */
7930 fei = fib_table_entry_path_add(0,
7931 &pfx_200_0_0_0_s_24,
7932 FIB_SOURCE_API,
7933 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007934 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007935 &nh_10_10_10_1,
7936 ~0, // recursive
7937 0, // default fib index
7938 1,
7939 NULL,
7940 FIB_ROUTE_PATH_FLAG_NONE);
7941
7942 FIB_TEST(fib_test_validate_entry(fei,
7943 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7944 1,
7945 &lb_o_10_10_10_1),
7946 "Recursive %U only UP BFD adj-fibs",
7947 format_fib_prefix, &pfx_200_0_0_0_s_24);
7948
7949 /*
7950 * Send a BFD state change to UP - both sessions are now up
7951 * the recursive prefix should LB over both
7952 */
7953 bfd_10_10_10_2.local_state = BFD_STATE_up;
7954 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7955
7956
7957 FIB_TEST(fib_test_validate_entry(fei,
7958 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7959 2,
7960 &lb_o_10_10_10_1,
7961 &lb_o_10_10_10_2),
7962 "Recursive %U via both UP BFD adj-fibs",
7963 format_fib_prefix, &pfx_200_0_0_0_s_24);
7964
7965 /*
7966 * Send a BFD state change to DOWN
7967 * the recursive prefix should exclude the down
7968 */
7969 bfd_10_10_10_2.local_state = BFD_STATE_down;
7970 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7971
7972
7973 FIB_TEST(fib_test_validate_entry(fei,
7974 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7975 1,
7976 &lb_o_10_10_10_1),
7977 "Recursive %U via only UP",
7978 format_fib_prefix, &pfx_200_0_0_0_s_24);
7979
7980 /*
7981 * Delete the BFD session while it is in the DOWN state.
7982 * FIB should consider the entry's state as back up
7983 */
7984 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
7985
7986 FIB_TEST(fib_test_validate_entry(fei,
7987 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7988 2,
7989 &lb_o_10_10_10_1,
7990 &lb_o_10_10_10_2),
7991 "Recursive %U via both UP BFD adj-fibs post down session delete",
7992 format_fib_prefix, &pfx_200_0_0_0_s_24);
7993
7994 /*
7995 * Delete the BFD other session while it is in the UP state.
7996 */
7997 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7998
7999 FIB_TEST(fib_test_validate_entry(fei,
8000 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8001 2,
8002 &lb_o_10_10_10_1,
8003 &lb_o_10_10_10_2),
8004 "Recursive %U via both UP BFD adj-fibs post up session delete",
8005 format_fib_prefix, &pfx_200_0_0_0_s_24);
8006
8007 /*
8008 * cleaup
8009 */
8010 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8011 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8012 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8013
8014 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8015 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8016
8017 adj_unlock(ai_10_10_10_1);
8018 /*
8019 * test no-one left behind
8020 */
8021 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8022 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8023
8024 /*
8025 * Single-hop BFD tests
8026 */
8027 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8028 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8029
8030 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8031
8032 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8033 VNET_LINK_IP4,
8034 &nh_10_10_10_1,
8035 tm->hw[0]->sw_if_index);
8036 /*
8037 * whilst the BFD session is not signalled, the adj is up
8038 */
8039 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8040
8041 /*
8042 * bring the BFD session up
8043 */
8044 bfd_10_10_10_1.local_state = BFD_STATE_up;
8045 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8046 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8047
8048 /*
8049 * bring the BFD session down
8050 */
8051 bfd_10_10_10_1.local_state = BFD_STATE_down;
8052 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8053 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8054
8055
8056 /*
8057 * add an attached next hop FIB entry via the down adj
8058 */
8059 fib_prefix_t pfx_5_5_5_5_s_32 = {
8060 .fp_addr = {
8061 .ip4 = {
8062 .as_u32 = clib_host_to_net_u32(0x05050505),
8063 },
8064 },
8065 .fp_len = 32,
8066 .fp_proto = FIB_PROTOCOL_IP4,
8067 };
8068
8069 fei = fib_table_entry_path_add(0,
8070 &pfx_5_5_5_5_s_32,
8071 FIB_SOURCE_CLI,
8072 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008073 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008074 &nh_10_10_10_1,
8075 tm->hw[0]->sw_if_index,
8076 ~0, // invalid fib index
8077 1,
8078 NULL,
8079 FIB_ROUTE_PATH_FLAG_NONE);
8080 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8081 "%U resolves via drop",
8082 format_fib_prefix, &pfx_5_5_5_5_s_32);
8083
8084 /*
8085 * Add a path via an ADJ that is up
8086 */
8087 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8088 VNET_LINK_IP4,
8089 &nh_10_10_10_2,
8090 tm->hw[0]->sw_if_index);
8091
8092 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8093 .type = FT_LB_ADJ,
8094 .adj = {
8095 .adj = ai_10_10_10_2,
8096 },
8097 };
8098 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8099
8100 fei = fib_table_entry_path_add(0,
8101 &pfx_5_5_5_5_s_32,
8102 FIB_SOURCE_CLI,
8103 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008104 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008105 &nh_10_10_10_2,
8106 tm->hw[0]->sw_if_index,
8107 ~0, // invalid fib index
8108 1,
8109 NULL,
8110 FIB_ROUTE_PATH_FLAG_NONE);
8111
8112 FIB_TEST(fib_test_validate_entry(fei,
8113 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8114 1,
8115 &adj_o_10_10_10_2),
8116 "BFD sourced %U via %U",
8117 format_fib_prefix, &pfx_5_5_5_5_s_32,
8118 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8119
8120 /*
8121 * Bring up the down session - should now LB
8122 */
8123 bfd_10_10_10_1.local_state = BFD_STATE_up;
8124 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8125 FIB_TEST(fib_test_validate_entry(fei,
8126 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8127 2,
8128 &adj_o_10_10_10_1,
8129 &adj_o_10_10_10_2),
8130 "BFD sourced %U via noth adjs",
8131 format_fib_prefix, &pfx_5_5_5_5_s_32);
8132
8133 /*
8134 * remove the BFD session state from the adj
8135 */
8136 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8137
8138 /*
8139 * clean-up
8140 */
8141 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8142 adj_unlock(ai_10_10_10_1);
8143 adj_unlock(ai_10_10_10_2);
8144
8145 /*
8146 * test no-one left behind
8147 */
8148 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8149 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8150 return (0);
8151}
8152
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008153static int
8154lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008155{
8156 const mpls_label_t deag_label = 50;
8157 const u32 lfib_index = 0;
8158 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01008159 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008160 const dpo_id_t *dpo1;
8161 fib_node_index_t lfe;
8162 lookup_dpo_t *lkd;
8163 test_main_t *tm;
8164 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00008165 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008166
8167 tm = &test_main;
8168 lb_count = pool_elts(load_balance_pool);
8169
8170 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8171 adj_nbr_db_size());
8172
8173 /*
8174 * MPLS enable an interface so we get the MPLS table created
8175 */
Neale Ranns2297af02017-09-12 09:45:04 -07008176 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008177 mpls_sw_interface_enable_disable(&mpls_main,
8178 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008179 1, 1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008180
Neale Rannsad422ed2016-11-02 14:20:04 +00008181 ip46_address_t nh_10_10_10_1 = {
8182 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8183 };
8184 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8185 VNET_LINK_MPLS,
8186 &nh_10_10_10_1,
8187 tm->hw[0]->sw_if_index);
8188
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008189 /*
8190 * Test the specials stack properly.
8191 */
8192 fib_prefix_t exp_null_v6_pfx = {
8193 .fp_proto = FIB_PROTOCOL_MPLS,
8194 .fp_eos = MPLS_EOS,
8195 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8196 .fp_payload_proto = DPO_PROTO_IP6,
8197 };
8198 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8199 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8200 "%U/%U present",
8201 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8202 format_mpls_eos_bit, MPLS_EOS);
8203 fib_entry_contribute_forwarding(lfe,
8204 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8205 &dpo);
8206 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8207 lkd = lookup_dpo_get(dpo1->dpoi_index);
8208
8209 FIB_TEST((fib_index == lkd->lkd_fib_index),
8210 "%U/%U is deag in %d %U",
8211 format_mpls_unicast_label, deag_label,
8212 format_mpls_eos_bit, MPLS_EOS,
8213 lkd->lkd_fib_index,
8214 format_dpo_id, &dpo, 0);
8215 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8216 "%U/%U is dst deag",
8217 format_mpls_unicast_label, deag_label,
8218 format_mpls_eos_bit, MPLS_EOS);
8219 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8220 "%U/%U is lookup in interface's table",
8221 format_mpls_unicast_label, deag_label,
8222 format_mpls_eos_bit, MPLS_EOS);
8223 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8224 "%U/%U is %U dst deag",
8225 format_mpls_unicast_label, deag_label,
8226 format_mpls_eos_bit, MPLS_EOS,
8227 format_dpo_proto, lkd->lkd_proto);
8228
8229
8230 /*
8231 * A route deag route for EOS
8232 */
8233 fib_prefix_t pfx = {
8234 .fp_proto = FIB_PROTOCOL_MPLS,
8235 .fp_eos = MPLS_EOS,
8236 .fp_label = deag_label,
8237 .fp_payload_proto = DPO_PROTO_IP4,
8238 };
8239 lfe = fib_table_entry_path_add(lfib_index,
8240 &pfx,
8241 FIB_SOURCE_CLI,
8242 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008243 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008244 &zero_addr,
8245 ~0,
8246 fib_index,
8247 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008248 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008249 FIB_ROUTE_PATH_FLAG_NONE);
8250
8251 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8252 "%U/%U present",
8253 format_mpls_unicast_label, deag_label,
8254 format_mpls_eos_bit, MPLS_EOS);
8255
8256 fib_entry_contribute_forwarding(lfe,
8257 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8258 &dpo);
8259 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8260 lkd = lookup_dpo_get(dpo1->dpoi_index);
8261
8262 FIB_TEST((fib_index == lkd->lkd_fib_index),
8263 "%U/%U is deag in %d %U",
8264 format_mpls_unicast_label, deag_label,
8265 format_mpls_eos_bit, MPLS_EOS,
8266 lkd->lkd_fib_index,
8267 format_dpo_id, &dpo, 0);
8268 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8269 "%U/%U is dst deag",
8270 format_mpls_unicast_label, deag_label,
8271 format_mpls_eos_bit, MPLS_EOS);
8272 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8273 "%U/%U is %U dst deag",
8274 format_mpls_unicast_label, deag_label,
8275 format_mpls_eos_bit, MPLS_EOS,
8276 format_dpo_proto, lkd->lkd_proto);
8277
8278 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8279
8280 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8281 &pfx)),
8282 "%U/%U not present",
8283 format_mpls_unicast_label, deag_label,
8284 format_mpls_eos_bit, MPLS_EOS);
8285
8286 /*
8287 * A route deag route for non-EOS
8288 */
8289 pfx.fp_eos = MPLS_NON_EOS;
8290 lfe = fib_table_entry_path_add(lfib_index,
8291 &pfx,
8292 FIB_SOURCE_CLI,
8293 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008294 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008295 &zero_addr,
8296 ~0,
8297 lfib_index,
8298 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008299 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008300 FIB_ROUTE_PATH_FLAG_NONE);
8301
8302 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8303 "%U/%U present",
8304 format_mpls_unicast_label, deag_label,
8305 format_mpls_eos_bit, MPLS_NON_EOS);
8306
8307 fib_entry_contribute_forwarding(lfe,
8308 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8309 &dpo);
8310 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8311 lkd = lookup_dpo_get(dpo1->dpoi_index);
8312
8313 FIB_TEST((fib_index == lkd->lkd_fib_index),
8314 "%U/%U is deag in %d %U",
8315 format_mpls_unicast_label, deag_label,
8316 format_mpls_eos_bit, MPLS_NON_EOS,
8317 lkd->lkd_fib_index,
8318 format_dpo_id, &dpo, 0);
8319 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8320 "%U/%U is dst deag",
8321 format_mpls_unicast_label, deag_label,
8322 format_mpls_eos_bit, MPLS_NON_EOS);
8323
8324 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8325 "%U/%U is %U dst deag",
8326 format_mpls_unicast_label, deag_label,
8327 format_mpls_eos_bit, MPLS_NON_EOS,
8328 format_dpo_proto, lkd->lkd_proto);
8329
8330 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8331
8332 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8333 &pfx)),
8334 "%U/%U not present",
8335 format_mpls_unicast_label, deag_label,
8336 format_mpls_eos_bit, MPLS_EOS);
8337
Neale Rannsad422ed2016-11-02 14:20:04 +00008338 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008339
Neale Rannsad422ed2016-11-02 14:20:04 +00008340 /*
8341 * An MPLS x-connect
8342 */
8343 fib_prefix_t pfx_1200 = {
8344 .fp_len = 21,
8345 .fp_proto = FIB_PROTOCOL_MPLS,
8346 .fp_label = 1200,
8347 .fp_eos = MPLS_NON_EOS,
8348 };
8349 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8350 .type = FT_LB_LABEL_STACK_O_ADJ,
8351 .label_stack_o_adj = {
8352 .adj = ai_mpls_10_10_10_1,
8353 .label_stack_size = 4,
8354 .label_stack = {
8355 200, 300, 400, 500,
8356 },
8357 .eos = MPLS_NON_EOS,
8358 },
8359 };
8360 dpo_id_t neos_1200 = DPO_INVALID;
8361 dpo_id_t ip_1200 = DPO_INVALID;
8362 mpls_label_t *l200 = NULL;
8363 vec_add1(l200, 200);
8364 vec_add1(l200, 300);
8365 vec_add1(l200, 400);
8366 vec_add1(l200, 500);
8367
8368 lfe = fib_table_entry_update_one_path(fib_index,
8369 &pfx_1200,
8370 FIB_SOURCE_API,
8371 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008372 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00008373 &nh_10_10_10_1,
8374 tm->hw[0]->sw_if_index,
8375 ~0, // invalid fib index
8376 1,
8377 l200,
8378 FIB_ROUTE_PATH_FLAG_NONE);
8379
8380 FIB_TEST(fib_test_validate_entry(lfe,
8381 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8382 1,
8383 &neos_o_10_10_10_1),
8384 "1200/0 LB 1 buckets via: "
8385 "adj 10.10.11.1");
8386
8387 /*
8388 * A recursive route via the MPLS x-connect
8389 */
8390 fib_prefix_t pfx_2_2_2_3_s_32 = {
8391 .fp_len = 32,
8392 .fp_proto = FIB_PROTOCOL_IP4,
8393 .fp_addr = {
8394 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8395 },
8396 };
8397 fib_route_path_t *rpaths = NULL, rpath = {
Neale Rannsda78f952017-05-24 09:15:43 -07008398 .frp_proto = DPO_PROTO_MPLS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008399 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008400 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008401 .frp_sw_if_index = ~0, // recurive
8402 .frp_fib_index = 0, // Default MPLS fib
8403 .frp_weight = 1,
8404 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8405 .frp_label_stack = NULL,
8406 };
8407 vec_add1(rpaths, rpath);
8408
8409 fib_table_entry_path_add2(fib_index,
8410 &pfx_2_2_2_3_s_32,
8411 FIB_SOURCE_API,
8412 FIB_ENTRY_FLAG_NONE,
8413 rpaths);
8414
8415 /*
8416 * A labelled recursive route via the MPLS x-connect
8417 */
8418 fib_prefix_t pfx_2_2_2_4_s_32 = {
8419 .fp_len = 32,
8420 .fp_proto = FIB_PROTOCOL_IP4,
8421 .fp_addr = {
8422 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8423 },
8424 };
8425 mpls_label_t *l999 = NULL;
8426 vec_add1(l999, 999);
8427 rpaths[0].frp_label_stack = l999,
8428
8429 fib_table_entry_path_add2(fib_index,
8430 &pfx_2_2_2_4_s_32,
8431 FIB_SOURCE_API,
8432 FIB_ENTRY_FLAG_NONE,
8433 rpaths);
8434
8435 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8436 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8437 &ip_1200);
8438 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8439 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8440 &neos_1200);
8441
8442 fib_test_lb_bucket_t ip_o_1200 = {
8443 .type = FT_LB_O_LB,
8444 .lb = {
8445 .lb = ip_1200.dpoi_index,
8446 },
8447 };
8448 fib_test_lb_bucket_t mpls_o_1200 = {
8449 .type = FT_LB_LABEL_O_LB,
8450 .label_o_lb = {
8451 .lb = neos_1200.dpoi_index,
8452 .label = 999,
8453 .eos = MPLS_EOS,
8454 },
8455 };
8456
8457 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8458 FIB_TEST(fib_test_validate_entry(lfe,
8459 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8460 1,
8461 &ip_o_1200),
8462 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8463 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8464 FIB_TEST(fib_test_validate_entry(lfe,
8465 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8466 1,
8467 &mpls_o_1200),
8468 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8469
8470 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8471 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8472 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8473
8474 dpo_reset(&neos_1200);
8475 dpo_reset(&ip_1200);
8476
8477 /*
8478 * A recursive via a label that does not exist
8479 */
8480 fib_test_lb_bucket_t bucket_drop = {
8481 .type = FT_LB_SPECIAL,
8482 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07008483 .adj = DPO_PROTO_IP4,
8484 },
8485 };
8486 fib_test_lb_bucket_t mpls_bucket_drop = {
8487 .type = FT_LB_SPECIAL,
8488 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00008489 .adj = DPO_PROTO_MPLS,
8490 },
8491 };
8492
8493 rpaths[0].frp_label_stack = NULL;
8494 lfe = fib_table_entry_path_add2(fib_index,
8495 &pfx_2_2_2_4_s_32,
8496 FIB_SOURCE_API,
8497 FIB_ENTRY_FLAG_NONE,
8498 rpaths);
8499
8500 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8501 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8502 &ip_1200);
8503 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8504
8505 FIB_TEST(fib_test_validate_entry(lfe,
8506 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8507 1,
Neale Ranns57b58602017-07-15 07:37:25 -07008508 &bucket_drop),
8509 "2.2.2.2.4/32 LB 1 buckets via: drop");
Neale Rannsad422ed2016-11-02 14:20:04 +00008510 lfe = fib_table_lookup(fib_index, &pfx_1200);
8511 FIB_TEST(fib_test_validate_entry(lfe,
8512 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8513 1,
8514 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07008515 "1200/neos LB 1 buckets via: ip4-DROP");
8516 FIB_TEST(fib_test_validate_entry(lfe,
8517 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8518 1,
8519 &mpls_bucket_drop),
8520 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00008521
8522 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8523
8524 dpo_reset(&ip_1200);
8525
8526 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008527 * An rx-interface route.
8528 * like the tail of an mcast LSP
8529 */
8530 dpo_id_t idpo = DPO_INVALID;
8531
Neale Ranns43161a82017-08-12 02:12:00 -07008532 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008533 tm->hw[0]->sw_if_index,
8534 &idpo);
8535
8536 fib_prefix_t pfx_2500 = {
8537 .fp_len = 21,
8538 .fp_proto = FIB_PROTOCOL_MPLS,
8539 .fp_label = 2500,
8540 .fp_eos = MPLS_EOS,
8541 .fp_payload_proto = DPO_PROTO_IP4,
8542 };
8543 fib_test_lb_bucket_t rx_intf_0 = {
8544 .type = FT_LB_INTF,
8545 .adj = {
8546 .adj = idpo.dpoi_index,
8547 },
8548 };
8549
8550 lfe = fib_table_entry_update_one_path(fib_index,
8551 &pfx_2500,
8552 FIB_SOURCE_API,
8553 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008554 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008555 NULL,
8556 tm->hw[0]->sw_if_index,
8557 ~0, // invalid fib index
8558 0,
8559 NULL,
8560 FIB_ROUTE_PATH_INTF_RX);
8561 FIB_TEST(fib_test_validate_entry(lfe,
8562 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8563 1,
8564 &rx_intf_0),
8565 "2500 rx-interface 0");
8566 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8567
8568 /*
8569 * An MPLS mulicast entry
8570 */
8571 fib_prefix_t pfx_3500 = {
8572 .fp_len = 21,
8573 .fp_proto = FIB_PROTOCOL_MPLS,
8574 .fp_label = 3500,
8575 .fp_eos = MPLS_EOS,
8576 .fp_payload_proto = DPO_PROTO_IP4,
8577 };
8578 fib_test_rep_bucket_t mc_0 = {
8579 .type = FT_REP_LABEL_O_ADJ,
8580 .label_o_adj = {
8581 .adj = ai_mpls_10_10_10_1,
8582 .label = 3300,
8583 .eos = MPLS_EOS,
8584 },
8585 };
8586 fib_test_rep_bucket_t mc_intf_0 = {
8587 .type = FT_REP_INTF,
8588 .adj = {
8589 .adj = idpo.dpoi_index,
8590 },
8591 };
8592 mpls_label_t *l3300 = NULL;
8593 vec_add1(l3300, 3300);
8594
8595 lfe = fib_table_entry_update_one_path(lfib_index,
8596 &pfx_3500,
8597 FIB_SOURCE_API,
8598 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008599 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008600 &nh_10_10_10_1,
8601 tm->hw[0]->sw_if_index,
8602 ~0, // invalid fib index
8603 1,
8604 l3300,
8605 FIB_ROUTE_PATH_FLAG_NONE);
8606 FIB_TEST(fib_test_validate_entry(lfe,
8607 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8608 1,
8609 &mc_0),
8610 "3500 via replicate over 10.10.10.1");
8611
8612 /*
8613 * MPLS Bud-node. Add a replication via an interface-receieve path
8614 */
8615 lfe = fib_table_entry_path_add(lfib_index,
8616 &pfx_3500,
8617 FIB_SOURCE_API,
8618 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008619 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008620 NULL,
8621 tm->hw[0]->sw_if_index,
8622 ~0, // invalid fib index
8623 0,
8624 NULL,
8625 FIB_ROUTE_PATH_INTF_RX);
8626 FIB_TEST(fib_test_validate_entry(lfe,
8627 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8628 2,
8629 &mc_0,
8630 &mc_intf_0),
8631 "3500 via replicate over 10.10.10.1 and interface-rx");
8632
8633 /*
8634 * Add a replication via an interface-free for-us path
8635 */
8636 fib_test_rep_bucket_t mc_disp = {
8637 .type = FT_REP_DISP_MFIB_LOOKUP,
8638 .adj = {
8639 .adj = idpo.dpoi_index,
8640 },
8641 };
8642 lfe = fib_table_entry_path_add(lfib_index,
8643 &pfx_3500,
8644 FIB_SOURCE_API,
8645 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008646 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008647 NULL,
8648 5, // rpf-id
8649 0, // default table
8650 0,
8651 NULL,
8652 FIB_ROUTE_PATH_RPF_ID);
8653 FIB_TEST(fib_test_validate_entry(lfe,
8654 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8655 3,
8656 &mc_0,
8657 &mc_disp,
8658 &mc_intf_0),
8659 "3500 via replicate over 10.10.10.1 and interface-rx");
8660
8661
8662
8663 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8664 dpo_reset(&idpo);
8665
8666 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008667 * cleanup
8668 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008669 mpls_sw_interface_enable_disable(&mpls_main,
8670 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008671 0, 1);
8672 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008673
Neale Rannsad422ed2016-11-02 14:20:04 +00008674 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008675 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008676 lb_count, pool_elts(load_balance_pool));
Neale Ranns43161a82017-08-12 02:12:00 -07008677 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
8678 "interface_rx_dpo resources freed %d of %d",
8679 0, pool_elts(interface_rx_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008680
8681 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008682}
8683
8684static clib_error_t *
8685fib_test (vlib_main_t * vm,
8686 unformat_input_t * input,
8687 vlib_cli_command_t * cmd_arg)
8688{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008689 int res;
8690
8691 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008692 fib_test_mk_intf(4);
8693
Neale Ranns88fc83e2017-04-05 08:11:14 -07008694 if (unformat (input, "debug"))
8695 {
8696 fib_test_do_debug = 1;
8697 }
8698
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008699 if (unformat (input, "ip"))
8700 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008701 res += fib_test_v4();
8702 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008703 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008704 else if (unformat (input, "label"))
8705 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008706 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008707 }
8708 else if (unformat (input, "ae"))
8709 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008710 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008711 }
Neale Ranns57b58602017-07-15 07:37:25 -07008712 else if (unformat (input, "pref"))
8713 {
8714 res += fib_test_pref();
8715 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008716 else if (unformat (input, "lfib"))
8717 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008718 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008719 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008720 else if (unformat (input, "walk"))
8721 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008722 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008723 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008724 else if (unformat (input, "bfd"))
8725 {
8726 res += fib_test_bfd();
8727 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008728 else
8729 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008730 res += fib_test_v4();
8731 res += fib_test_v6();
8732 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008733 res += fib_test_bfd();
Neale Ranns57b58602017-07-15 07:37:25 -07008734 res += fib_test_pref();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008735 res += fib_test_label();
8736 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008737
8738 /*
8739 * fib-walk process must be disabled in order for the walk tests to work
8740 */
8741 fib_walk_process_disable();
8742 res += fib_test_walk();
8743 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008744 }
8745
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008746 if (res)
8747 {
8748 return clib_error_return(0, "FIB Unit Test Failed");
8749 }
8750 else
8751 {
8752 return (NULL);
8753 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008754}
8755
8756VLIB_CLI_COMMAND (test_fib_command, static) = {
8757 .path = "test fib",
8758 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8759 .function = fib_test,
8760};
8761
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008762clib_error_t *
8763fib_test_init (vlib_main_t *vm)
8764{
8765 return 0;
8766}
8767
8768VLIB_INIT_FUNCTION (fib_test_init);