blob: 720f54e7039d39e7d09710e12a99664e56bb5089 [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 Ranns0f26c5a2017-03-01 15:12:11 -080028#include <vnet/dpo/interface_dpo.h>
29#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:
410 FIB_TEST_LB((DPO_INTERFACE == dpo->dpoi_type),
411 "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:
592 FIB_TEST_I((DPO_INTERFACE == dpo->dpoi_type),
593 "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 */
742 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
743
744 for (ii = 0; ii < 4; ii++)
745 {
746 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
747 }
748
749 fib_prefix_t pfx_0_0_0_0_s_0 = {
750 .fp_len = 0,
751 .fp_proto = FIB_PROTOCOL_IP4,
752 .fp_addr = {
753 .ip4 = {
754 {0}
755 },
756 },
757 };
758
759 fib_prefix_t pfx = {
760 .fp_len = 0,
761 .fp_proto = FIB_PROTOCOL_IP4,
762 .fp_addr = {
763 .ip4 = {
764 {0}
765 },
766 },
767 };
768
769 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
770
771 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
772 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
773 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
774 "Default route is DROP");
775
776 pfx.fp_len = 32;
777 fei = fib_table_lookup(fib_index, &pfx);
778 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
779 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
780 "all 0s route is DROP");
781
782 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
783 pfx.fp_len = 32;
784 fei = fib_table_lookup(fib_index, &pfx);
785 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
786 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
787 "all 1s route is DROP");
788
789 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
790 pfx.fp_len = 8;
791 fei = fib_table_lookup(fib_index, &pfx);
792 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
793 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
794 "all-mcast route is DROP");
795
796 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
797 pfx.fp_len = 8;
798 fei = fib_table_lookup(fib_index, &pfx);
799 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
800 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
801 "class-e route is DROP");
802
803 /*
804 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
805 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000806 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
807 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100808 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000809#define ENBR (5+5+2)
810#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100811 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000812 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100813 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000814 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100815 fib_entry_pool_size());
816
817 /*
818 * add interface routes.
819 * validate presence of /24 attached and /32 recieve.
820 * test for the presence of the receive address in the glean and local adj
821 */
822 fib_prefix_t local_pfx = {
823 .fp_len = 24,
824 .fp_proto = FIB_PROTOCOL_IP4,
825 .fp_addr = {
826 .ip4 = {
827 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
828 },
829 },
830 };
831
832 fib_table_entry_update_one_path(fib_index, &local_pfx,
833 FIB_SOURCE_INTERFACE,
834 (FIB_ENTRY_FLAG_CONNECTED |
835 FIB_ENTRY_FLAG_ATTACHED),
836 FIB_PROTOCOL_IP4,
837 NULL,
838 tm->hw[0]->sw_if_index,
839 ~0, // invalid fib index
840 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000841 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100842 FIB_ROUTE_PATH_FLAG_NONE);
843 fei = fib_table_lookup(fib_index, &local_pfx);
844 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
845 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
846 fib_entry_get_flags(fei)),
847 "Flags set on attached interface");
848
849 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -0700850 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
851 "attached interface route adj present %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100852 adj = adj_get(ai);
853 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
854 "attached interface adj is glean");
855 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
856 &adj->sub_type.glean.receive_addr)),
857 "attached interface adj is receive ok");
858
859 local_pfx.fp_len = 32;
860 fib_table_entry_update_one_path(fib_index, &local_pfx,
861 FIB_SOURCE_INTERFACE,
862 (FIB_ENTRY_FLAG_CONNECTED |
863 FIB_ENTRY_FLAG_LOCAL),
864 FIB_PROTOCOL_IP4,
865 NULL,
866 tm->hw[0]->sw_if_index,
867 ~0, // invalid fib index
868 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000869 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100870 FIB_ROUTE_PATH_FLAG_NONE);
871 fei = fib_table_lookup(fib_index, &local_pfx);
872 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
873 fib_entry_get_flags(fei)),
874 "Flags set on local interface");
875
876 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
877
878 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100879 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
880 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100881 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
882 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
883 "local interface adj is local");
884 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
885
886 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
887 &rd->rd_addr)),
888 "local interface adj is receive ok");
889
890 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
891 FIB_PROTOCOL_IP4,
892 FIB_SOURCE_INTERFACE)),
893 "2 Interface Source'd prefixes");
894
895 /*
896 * +2 interface routes +2 non-shared path-lists
897 */
898 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000899 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100900 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000901 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100902 fib_entry_pool_size());
903
904 /*
905 * Modify the default route to be via an adj not yet known.
906 * this sources the defalut route with the API source, which is
907 * a higher preference to the DEFAULT_ROUTE source
908 */
909 pfx.fp_addr.ip4.as_u32 = 0;
910 pfx.fp_len = 0;
911 fib_table_entry_path_add(fib_index, &pfx,
912 FIB_SOURCE_API,
913 FIB_ENTRY_FLAG_NONE,
914 FIB_PROTOCOL_IP4,
915 &nh_10_10_10_1,
916 tm->hw[0]->sw_if_index,
917 ~0, // invalid fib index
918 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000919 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100920 FIB_ROUTE_PATH_FLAG_NONE);
921 fei = fib_table_lookup(fib_index, &pfx);
922 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
923 "Flags set on API route");
924
925 FIB_TEST((fei == dfrt), "default route same index");
926 ai = fib_entry_get_adj(fei);
927 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
928 adj = adj_get(ai);
929 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
930 "adj is incomplete");
931 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
932 "adj nbr next-hop ok");
933 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
934 FIB_PROTOCOL_IP4,
935 FIB_SOURCE_API)),
936 "1 API Source'd prefixes");
937
938 /*
939 * find the adj in the shared db
940 */
941 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100942 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100943 &nh_10_10_10_1,
944 tm->hw[0]->sw_if_index);
945 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
946 adj_unlock(locked_ai);
947
948 /*
949 * +1 shared path-list
950 */
951 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
952 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000953 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100954 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000955 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100956 fib_entry_pool_size());
957
958 /*
959 * remove the API source from the default route. We expected
960 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
961 */
962 pfx.fp_addr.ip4.as_u32 = 0;
963 pfx.fp_len = 0;
964 fib_table_entry_path_remove(fib_index, &pfx,
965 FIB_SOURCE_API,
966 FIB_PROTOCOL_IP4,
967 &nh_10_10_10_1,
968 tm->hw[0]->sw_if_index,
969 ~0, // non-recursive path, so no FIB index
970 1,
971 FIB_ROUTE_PATH_FLAG_NONE);
972
973 fei = fib_table_lookup(fib_index, &pfx);
974
975 FIB_TEST((fei == dfrt), "default route same index");
976 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
977 "Default route is DROP");
978
979 /*
980 * -1 shared-path-list
981 */
982 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000983 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100984 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000985 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100986 fib_entry_pool_size());
987
988 /*
989 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
990 */
991 fib_prefix_t pfx_10_10_10_1_s_32 = {
992 .fp_len = 32,
993 .fp_proto = FIB_PROTOCOL_IP4,
994 .fp_addr = {
995 /* 10.10.10.1 */
996 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
997 },
998 };
999 fib_prefix_t pfx_10_10_10_2_s_32 = {
1000 .fp_len = 32,
1001 .fp_proto = FIB_PROTOCOL_IP4,
1002 .fp_addr = {
1003 /* 10.10.10.2 */
1004 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1005 },
1006 };
1007 fib_prefix_t pfx_11_11_11_11_s_32 = {
1008 .fp_len = 32,
1009 .fp_proto = FIB_PROTOCOL_IP4,
1010 .fp_addr = {
1011 /* 11.11.11.11 */
1012 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1013 },
1014 };
1015 u8 eth_addr[] = {
1016 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1017 };
Neale Rannsb80c5362016-10-08 13:03:40 +01001018
Neale Ranns3ee44042016-10-03 13:05:48 +01001019 ip46_address_t nh_12_12_12_12 = {
1020 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1021 };
1022 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001023
1024 /*
1025 * Add a route via an incomplete ADJ. then complete the ADJ
1026 * Expect the route LB is updated to use complete adj type.
1027 */
1028 fei = fib_table_entry_update_one_path(fib_index,
1029 &pfx_11_11_11_11_s_32,
1030 FIB_SOURCE_API,
1031 FIB_ENTRY_FLAG_ATTACHED,
1032 FIB_PROTOCOL_IP4,
1033 &pfx_10_10_10_1_s_32.fp_addr,
1034 tm->hw[0]->sw_if_index,
1035 ~0, // invalid fib index
1036 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001037 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001038 FIB_ROUTE_PATH_FLAG_NONE);
1039
1040 dpo = fib_entry_contribute_ip_forwarding(fei);
1041 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1042 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1043 "11.11.11.11/32 via incomplete adj");
1044
1045 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001046 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001047 &pfx_10_10_10_1_s_32.fp_addr,
1048 tm->hw[0]->sw_if_index);
1049 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1050 adj = adj_get(ai_01);
1051 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1052 "adj is incomplete");
1053 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1054 &adj->sub_type.nbr.next_hop)),
1055 "adj nbr next-hop ok");
1056
Neale Rannsb80c5362016-10-08 13:03:40 +01001057 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1058 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001059 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1060 "adj is complete");
1061 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1062 &adj->sub_type.nbr.next_hop)),
1063 "adj nbr next-hop ok");
1064 ai = fib_entry_get_adj(fei);
1065 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1066
1067 dpo = fib_entry_contribute_ip_forwarding(fei);
1068 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1069 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1070 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001071 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1072 tm->hw[0]->sw_if_index),
1073 "RPF list for adj-fib contains adj");
1074
1075 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001076 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001077 &nh_12_12_12_12,
1078 tm->hw[1]->sw_if_index);
1079 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1080 adj = adj_get(ai_12_12_12_12);
1081 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1082 "adj is incomplete");
1083 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1084 &adj->sub_type.nbr.next_hop)),
1085 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001086 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1087 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001088 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1089 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001090
1091 /*
1092 * add the adj fib
1093 */
Neale Ranns81424992017-05-18 03:03:22 -07001094 fei = fib_table_entry_path_add(fib_index,
1095 &pfx_10_10_10_1_s_32,
1096 FIB_SOURCE_ADJ,
1097 FIB_ENTRY_FLAG_ATTACHED,
1098 FIB_PROTOCOL_IP4,
1099 &pfx_10_10_10_1_s_32.fp_addr,
1100 tm->hw[0]->sw_if_index,
1101 ~0, // invalid fib index
1102 1,
1103 NULL,
1104 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001105 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1106 "Flags set on adj-fib");
1107 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -07001108 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001109
1110 fib_table_entry_path_remove(fib_index,
1111 &pfx_11_11_11_11_s_32,
1112 FIB_SOURCE_API,
1113 FIB_PROTOCOL_IP4,
1114 &pfx_10_10_10_1_s_32.fp_addr,
1115 tm->hw[0]->sw_if_index,
1116 ~0, // invalid fib index
1117 1,
1118 FIB_ROUTE_PATH_FLAG_NONE);
1119
1120 eth_addr[5] = 0xb2;
1121
1122 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001123 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001124 &pfx_10_10_10_2_s_32.fp_addr,
1125 tm->hw[0]->sw_if_index);
1126 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1127 adj = adj_get(ai_02);
1128 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1129 "adj is incomplete");
1130 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1131 &adj->sub_type.nbr.next_hop)),
1132 "adj nbr next-hop ok");
1133
Neale Rannsb80c5362016-10-08 13:03:40 +01001134 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1135 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001136 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1137 "adj is complete");
1138 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1139 &adj->sub_type.nbr.next_hop)),
1140 "adj nbr next-hop ok");
1141 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1142
Neale Ranns81424992017-05-18 03:03:22 -07001143 fib_table_entry_path_add(fib_index,
1144 &pfx_10_10_10_2_s_32,
1145 FIB_SOURCE_ADJ,
1146 FIB_ENTRY_FLAG_ATTACHED,
1147 FIB_PROTOCOL_IP4,
1148 &pfx_10_10_10_2_s_32.fp_addr,
1149 tm->hw[0]->sw_if_index,
1150 ~0, // invalid fib index
1151 1,
1152 NULL,
1153 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001154
1155 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1156 ai = fib_entry_get_adj(fei);
1157 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1158
1159 /*
1160 * +2 adj-fibs, and their non-shared path-lists
1161 */
1162 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001163 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001164 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001165 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001166 fib_entry_pool_size());
1167
1168 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001169 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001170 */
1171 fib_prefix_t pfx_1_1_1_1_s_32 = {
1172 .fp_len = 32,
1173 .fp_proto = FIB_PROTOCOL_IP4,
1174 .fp_addr = {
1175 /* 1.1.1.1/32 */
1176 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1177 },
1178 };
1179
1180 fib_table_entry_path_add(fib_index,
1181 &pfx_1_1_1_1_s_32,
1182 FIB_SOURCE_API,
1183 FIB_ENTRY_FLAG_NONE,
1184 FIB_PROTOCOL_IP4,
1185 &nh_10_10_10_1,
1186 tm->hw[0]->sw_if_index,
1187 ~0, // invalid fib index
1188 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001189 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001190 FIB_ROUTE_PATH_FLAG_NONE);
1191 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1192 ai = fib_entry_get_adj(fei);
1193 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1194
1195 /*
1196 * +1 entry and a shared path-list
1197 */
1198 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001199 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001200 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001201 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001202 fib_entry_pool_size());
1203
1204 /* 1.1.2.0/24 */
1205 fib_prefix_t pfx_1_1_2_0_s_24 = {
1206 .fp_len = 24,
1207 .fp_proto = FIB_PROTOCOL_IP4,
1208 .fp_addr = {
1209 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1210 }
1211 };
1212
1213 fib_table_entry_path_add(fib_index,
1214 &pfx_1_1_2_0_s_24,
1215 FIB_SOURCE_API,
1216 FIB_ENTRY_FLAG_NONE,
1217 FIB_PROTOCOL_IP4,
1218 &nh_10_10_10_1,
1219 tm->hw[0]->sw_if_index,
1220 ~0, // invalid fib index
1221 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001222 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001223 FIB_ROUTE_PATH_FLAG_NONE);
1224 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1225 ai = fib_entry_get_adj(fei);
1226 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1227
1228 /*
1229 * +1 entry only
1230 */
1231 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001232 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001233 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001234 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001235 fib_entry_pool_size());
1236
1237 /*
1238 * modify 1.1.2.0/24 to use multipath.
1239 */
1240 fib_table_entry_path_add(fib_index,
1241 &pfx_1_1_2_0_s_24,
1242 FIB_SOURCE_API,
1243 FIB_ENTRY_FLAG_NONE,
1244 FIB_PROTOCOL_IP4,
1245 &nh_10_10_10_2,
1246 tm->hw[0]->sw_if_index,
1247 ~0, // invalid fib index
1248 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001249 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001250 FIB_ROUTE_PATH_FLAG_NONE);
1251 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1252 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001253 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1254 1, tm->hw[0]->sw_if_index),
1255 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001256
1257 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1258 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1259 FIB_TEST((ai_01 == dpo1->dpoi_index),
1260 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1261 ai_01, dpo1->dpoi_index);
1262
1263 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1264 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1265 FIB_TEST((ai_02 == dpo1->dpoi_index),
1266 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1267
1268 /*
1269 * +1 shared-pathlist
1270 */
1271 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001272 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001273 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001274 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001275 fib_entry_pool_size());
1276
1277 /*
1278 * revert the modify
1279 */
1280 fib_table_entry_path_remove(fib_index,
1281 &pfx_1_1_2_0_s_24,
1282 FIB_SOURCE_API,
1283 FIB_PROTOCOL_IP4,
1284 &nh_10_10_10_2,
1285 tm->hw[0]->sw_if_index,
1286 ~0,
1287 1,
1288 FIB_ROUTE_PATH_FLAG_NONE);
1289 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001290 dpo = fib_entry_contribute_ip_forwarding(fei);
1291 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1292 1, tm->hw[0]->sw_if_index),
1293 "RPF list for 1.1.2.0/24 contains one adj");
1294
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001295 ai = fib_entry_get_adj(fei);
1296 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1297
1298 /*
1299 * +1 shared-pathlist
1300 */
1301 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1302 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001303 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001304 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001305 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001306 fib_entry_pool_size());
1307
1308 /*
1309 * Add 2 recursive routes:
1310 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1311 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1312 */
1313 fib_prefix_t bgp_100_pfx = {
1314 .fp_len = 32,
1315 .fp_proto = FIB_PROTOCOL_IP4,
1316 .fp_addr = {
1317 /* 100.100.100.100/32 */
1318 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1319 },
1320 };
1321 /* via 1.1.1.1 */
1322 ip46_address_t nh_1_1_1_1 = {
1323 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1324 };
1325
Neale Ranns3ee44042016-10-03 13:05:48 +01001326 fei = fib_table_entry_path_add(fib_index,
1327 &bgp_100_pfx,
1328 FIB_SOURCE_API,
1329 FIB_ENTRY_FLAG_NONE,
1330 FIB_PROTOCOL_IP4,
1331 &nh_1_1_1_1,
1332 ~0, // no index provided.
1333 fib_index, // nexthop in same fib as route
1334 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001335 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001336 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001337
Neale Ranns3ee44042016-10-03 13:05:48 +01001338 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1339 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1340 tm->hw[0]->sw_if_index),
1341 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001342
1343 /*
1344 * +1 entry and +1 shared-path-list
1345 */
1346 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1347 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001348 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001349 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001350 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001351 fib_entry_pool_size());
1352
1353 fib_prefix_t bgp_101_pfx = {
1354 .fp_len = 32,
1355 .fp_proto = FIB_PROTOCOL_IP4,
1356 .fp_addr = {
1357 /* 100.100.100.101/32 */
1358 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1359 },
1360 };
1361
1362 fib_table_entry_path_add(fib_index,
1363 &bgp_101_pfx,
1364 FIB_SOURCE_API,
1365 FIB_ENTRY_FLAG_NONE,
1366 FIB_PROTOCOL_IP4,
1367 &nh_1_1_1_1,
1368 ~0, // no index provided.
1369 fib_index, // nexthop in same fib as route
1370 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001371 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001372 FIB_ROUTE_PATH_FLAG_NONE);
1373
Neale Ranns3ee44042016-10-03 13:05:48 +01001374 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1375 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1376 tm->hw[0]->sw_if_index),
1377 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001378
1379 /*
1380 * +1 entry, but the recursive path-list is shared.
1381 */
1382 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1383 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001384 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001385 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001386 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001387 fib_entry_pool_size());
1388
1389 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001390 * An special route; one where the user (me) provides the
1391 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001392 */
1393 fib_prefix_t ex_pfx = {
1394 .fp_len = 32,
1395 .fp_proto = FIB_PROTOCOL_IP4,
1396 .fp_addr = {
1397 /* 4.4.4.4/32 */
1398 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1399 },
1400 };
1401
1402 fib_table_entry_special_add(fib_index,
1403 &ex_pfx,
1404 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001405 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001406 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001407 dpo = fib_entry_contribute_ip_forwarding(fei);
1408 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1409 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1410 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001411
1412 fib_table_entry_special_remove(fib_index,
1413 &ex_pfx,
1414 FIB_SOURCE_SPECIAL);
1415 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1416 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1417 "Exclusive reoute removed");
1418
1419 /*
1420 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1421 * adjacency through which the route will resovle
1422 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001423 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001424
1425 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1426 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001427 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001428 LOOKUP_INPUT_DST_ADDR,
1429 LOOKUP_TABLE_FROM_CONFIG,
1430 &ex_dpo);
1431
1432 fib_table_entry_special_dpo_add(fib_index,
1433 &ex_pfx,
1434 FIB_SOURCE_SPECIAL,
1435 FIB_ENTRY_FLAG_EXCLUSIVE,
1436 &ex_dpo);
1437 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1438 dpo = fib_entry_contribute_ip_forwarding(fei);
1439 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1440 "exclusive remote uses lookup DPO");
1441
Neale Ranns948e00f2016-10-20 13:39:34 +01001442 /*
1443 * update the exclusive to use a different DPO
1444 */
Neale Ranns450cd302016-11-09 17:49:42 +00001445 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001446 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1447 &ex_dpo);
1448 fib_table_entry_special_dpo_update(fib_index,
1449 &ex_pfx,
1450 FIB_SOURCE_SPECIAL,
1451 FIB_ENTRY_FLAG_EXCLUSIVE,
1452 &ex_dpo);
1453 dpo = fib_entry_contribute_ip_forwarding(fei);
1454 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1455 "exclusive remote uses now uses NULL DPO");
1456
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001457 fib_table_entry_special_remove(fib_index,
1458 &ex_pfx,
1459 FIB_SOURCE_SPECIAL);
1460 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1461 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1462 "Exclusive reoute removed");
1463 dpo_reset(&ex_dpo);
1464
1465 /*
1466 * Add a recursive route:
1467 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1468 */
1469 fib_prefix_t bgp_200_pfx = {
1470 .fp_len = 32,
1471 .fp_proto = FIB_PROTOCOL_IP4,
1472 .fp_addr = {
1473 /* 200.200.200.200/32 */
1474 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1475 },
1476 };
1477 /* via 1.1.1.2 */
1478 fib_prefix_t pfx_1_1_1_2_s_32 = {
1479 .fp_len = 32,
1480 .fp_proto = FIB_PROTOCOL_IP4,
1481 .fp_addr = {
1482 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1483 },
1484 };
1485
Neale Ranns57b58602017-07-15 07:37:25 -07001486 fei = fib_table_entry_path_add(fib_index,
1487 &bgp_200_pfx,
1488 FIB_SOURCE_API,
1489 FIB_ENTRY_FLAG_NONE,
1490 FIB_PROTOCOL_IP4,
1491 &pfx_1_1_1_2_s_32.fp_addr,
1492 ~0, // no index provided.
1493 fib_index, // nexthop in same fib as route
1494 1,
1495 NULL,
1496 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001497
Neale Ranns57b58602017-07-15 07:37:25 -07001498 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1499 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001500
1501 /*
1502 * the adj should be recursive via drop, since the route resolves via
1503 * the default route, which is itself a DROP
1504 */
1505 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1506 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1507 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001508 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1509 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001510
1511 /*
1512 * +2 entry and +1 shared-path-list
1513 */
1514 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1515 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001516 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001517 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001518 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001519 fib_entry_pool_size());
1520
1521 /*
1522 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001523 * The paths are sort by NH first. in this case the the path with greater
1524 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001525 */
1526 fib_prefix_t pfx_1_2_3_4_s_32 = {
1527 .fp_len = 32,
1528 .fp_proto = FIB_PROTOCOL_IP4,
1529 .fp_addr = {
1530 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1531 },
1532 };
1533 fib_table_entry_path_add(fib_index,
1534 &pfx_1_2_3_4_s_32,
1535 FIB_SOURCE_API,
1536 FIB_ENTRY_FLAG_NONE,
1537 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001538 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001539 tm->hw[0]->sw_if_index,
1540 ~0,
1541 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001542 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001543 FIB_ROUTE_PATH_FLAG_NONE);
1544 fei = fib_table_entry_path_add(fib_index,
1545 &pfx_1_2_3_4_s_32,
1546 FIB_SOURCE_API,
1547 FIB_ENTRY_FLAG_NONE,
1548 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001549 &nh_12_12_12_12,
1550 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001551 ~0,
1552 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001553 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001554 FIB_ROUTE_PATH_FLAG_NONE);
1555
1556 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1557 dpo = fib_entry_contribute_ip_forwarding(fei);
1558 lb = load_balance_get(dpo->dpoi_index);
1559 FIB_TEST((lb->lb_n_buckets == 4),
1560 "1.2.3.4/32 LB has %d bucket",
1561 lb->lb_n_buckets);
1562
Neale Ranns3ee44042016-10-03 13:05:48 +01001563 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1564 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1565 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1566 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001567
Neale Ranns3ee44042016-10-03 13:05:48 +01001568 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1569 tm->hw[0]->sw_if_index,
1570 tm->hw[1]->sw_if_index),
1571 "RPF list for 1.2.3.4/32 contains both adjs");
1572
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001573
1574 /*
1575 * Unequal Cost load-balance. 4:1 ratio.
1576 * fits in a 16 bucket LB with ratio 13:3
1577 */
1578 fib_prefix_t pfx_1_2_3_5_s_32 = {
1579 .fp_len = 32,
1580 .fp_proto = FIB_PROTOCOL_IP4,
1581 .fp_addr = {
1582 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1583 },
1584 };
1585 fib_table_entry_path_add(fib_index,
1586 &pfx_1_2_3_5_s_32,
1587 FIB_SOURCE_API,
1588 FIB_ENTRY_FLAG_NONE,
1589 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001590 &nh_12_12_12_12,
1591 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001592 ~0,
1593 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001594 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001595 FIB_ROUTE_PATH_FLAG_NONE);
1596 fei = fib_table_entry_path_add(fib_index,
1597 &pfx_1_2_3_5_s_32,
1598 FIB_SOURCE_API,
1599 FIB_ENTRY_FLAG_NONE,
1600 FIB_PROTOCOL_IP4,
1601 &nh_10_10_10_1,
1602 tm->hw[0]->sw_if_index,
1603 ~0,
1604 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001605 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001606 FIB_ROUTE_PATH_FLAG_NONE);
1607
1608 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1609 dpo = fib_entry_contribute_ip_forwarding(fei);
1610 lb = load_balance_get(dpo->dpoi_index);
1611 FIB_TEST((lb->lb_n_buckets == 16),
1612 "1.2.3.5/32 LB has %d bucket",
1613 lb->lb_n_buckets);
1614
1615 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1616 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1617 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1618 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1619 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1620 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1621 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1622 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1623 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1624 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1625 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1626 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1627 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001628 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1629 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1630 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1631
1632 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1633 tm->hw[0]->sw_if_index,
1634 tm->hw[1]->sw_if_index),
1635 "RPF list for 1.2.3.4/32 contains both adjs");
1636
1637 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001638 * Test UCMP with a large weight skew - this produces load-balance objects with large
1639 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1640 * laso testing the LB in placce modify code when number of buckets is large.
1641 */
1642 fib_prefix_t pfx_6_6_6_6_s_32 = {
1643 .fp_len = 32,
1644 .fp_proto = FIB_PROTOCOL_IP4,
1645 .fp_addr = {
1646 /* 1.1.1.1/32 */
1647 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1648 },
1649 };
Neale Ranns81424992017-05-18 03:03:22 -07001650 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001651 .type = FT_LB_ADJ,
1652 .adj = {
1653 .adj = ai_01,
1654 },
1655 };
Neale Ranns81424992017-05-18 03:03:22 -07001656 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001657 .type = FT_LB_ADJ,
1658 .adj = {
1659 .adj = ai_02,
1660 },
1661 };
1662 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1663 .type = FT_LB_ADJ,
1664 .adj = {
1665 .adj = ai_12_12_12_12,
1666 },
1667 };
1668 fib_table_entry_update_one_path(fib_index,
1669 &pfx_6_6_6_6_s_32,
1670 FIB_SOURCE_API,
1671 FIB_ENTRY_FLAG_NONE,
1672 FIB_PROTOCOL_IP4,
1673 &nh_10_10_10_1,
1674 tm->hw[0]->sw_if_index,
1675 ~0, // invalid fib index
1676 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001677 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001678 FIB_ROUTE_PATH_FLAG_NONE);
1679
1680 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1681 FIB_TEST(fib_test_validate_entry(fei,
1682 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1683 1,
Neale Ranns81424992017-05-18 03:03:22 -07001684 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001685 "6.6.6.6/32 via 10.10.10.1");
1686
1687 fib_table_entry_path_add(fib_index,
1688 &pfx_6_6_6_6_s_32,
1689 FIB_SOURCE_API,
1690 FIB_ENTRY_FLAG_NONE,
1691 FIB_PROTOCOL_IP4,
1692 &nh_10_10_10_2,
1693 tm->hw[0]->sw_if_index,
1694 ~0, // invalid fib index
1695 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001696 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001697 FIB_ROUTE_PATH_FLAG_NONE);
1698
1699 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1700 FIB_TEST(fib_test_validate_entry(fei,
1701 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1702 64,
Neale Ranns81424992017-05-18 03:03:22 -07001703 &ip_o_10_10_10_2,
1704 &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_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001767 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1768
1769 fib_table_entry_path_add(fib_index,
1770 &pfx_6_6_6_6_s_32,
1771 FIB_SOURCE_API,
1772 FIB_ENTRY_FLAG_NONE,
1773 FIB_PROTOCOL_IP4,
1774 &nh_12_12_12_12,
1775 tm->hw[1]->sw_if_index,
1776 ~0, // invalid fib index
1777 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001778 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001779 FIB_ROUTE_PATH_FLAG_NONE);
1780
1781 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1782 FIB_TEST(fib_test_validate_entry(fei,
1783 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1784 128,
Neale Ranns81424992017-05-18 03:03:22 -07001785 &ip_o_10_10_10_1,
1786 &ip_o_10_10_10_2,
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,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001850 &ip_6_6_6_6_o_12_12_12_12,
1851 &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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1914
1915 fib_table_entry_path_remove(fib_index,
1916 &pfx_6_6_6_6_s_32,
1917 FIB_SOURCE_API,
1918 FIB_PROTOCOL_IP4,
1919 &nh_12_12_12_12,
1920 tm->hw[1]->sw_if_index,
1921 ~0, // invalid fib index
1922 100,
1923 FIB_ROUTE_PATH_FLAG_NONE);
1924
1925 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1926 FIB_TEST(fib_test_validate_entry(fei,
1927 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1928 64,
Neale Ranns81424992017-05-18 03:03:22 -07001929 &ip_o_10_10_10_2,
1930 &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_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001993 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1994
1995 fib_table_entry_path_remove(fib_index,
1996 &pfx_6_6_6_6_s_32,
1997 FIB_SOURCE_API,
1998 FIB_PROTOCOL_IP4,
1999 &nh_10_10_10_2,
2000 tm->hw[0]->sw_if_index,
2001 ~0, // invalid fib index
2002 100,
2003 FIB_ROUTE_PATH_FLAG_NONE);
2004
2005 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2006 FIB_TEST(fib_test_validate_entry(fei,
2007 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2008 1,
Neale Ranns81424992017-05-18 03:03:22 -07002009 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00002010 "6.6.6.6/32 via 10.10.10.1");
2011
2012 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2013
2014 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01002015 * A recursive via the two unequal cost entries
2016 */
2017 fib_prefix_t bgp_44_s_32 = {
2018 .fp_len = 32,
2019 .fp_proto = FIB_PROTOCOL_IP4,
2020 .fp_addr = {
2021 /* 200.200.200.201/32 */
2022 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2023 },
2024 };
2025 fei = fib_table_entry_path_add(fib_index,
2026 &bgp_44_s_32,
2027 FIB_SOURCE_API,
2028 FIB_ENTRY_FLAG_NONE,
2029 FIB_PROTOCOL_IP4,
2030 &pfx_1_2_3_4_s_32.fp_addr,
2031 ~0,
2032 fib_index,
2033 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002034 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002035 FIB_ROUTE_PATH_FLAG_NONE);
2036 fei = fib_table_entry_path_add(fib_index,
2037 &bgp_44_s_32,
2038 FIB_SOURCE_API,
2039 FIB_ENTRY_FLAG_NONE,
2040 FIB_PROTOCOL_IP4,
2041 &pfx_1_2_3_5_s_32.fp_addr,
2042 ~0,
2043 fib_index,
2044 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002045 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002046 FIB_ROUTE_PATH_FLAG_NONE);
2047
2048 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2049 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2050 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2051 tm->hw[0]->sw_if_index,
2052 tm->hw[1]->sw_if_index),
2053 "RPF list for 1.2.3.4/32 contains both adjs");
2054
2055 /*
2056 * test the uRPF check functions
2057 */
Neale Ranns948e00f2016-10-20 13:39:34 +01002058 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01002059 index_t urpfi;
2060
2061 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2062 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2063
2064 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2065 "uRPF check for 68.68.68.68/32 on %d OK",
2066 tm->hw[0]->sw_if_index);
2067 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2068 "uRPF check for 68.68.68.68/32 on %d OK",
2069 tm->hw[1]->sw_if_index);
2070 FIB_TEST(!fib_urpf_check(urpfi, 99),
2071 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2072 99);
2073 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002074
2075 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002076 &bgp_44_s_32,
2077 FIB_SOURCE_API);
2078 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002079 &pfx_1_2_3_5_s_32,
2080 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002081 fib_table_entry_delete(fib_index,
2082 &pfx_1_2_3_4_s_32,
2083 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002084
2085 /*
2086 * Add a recursive route:
2087 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2088 */
2089 fib_prefix_t bgp_201_pfx = {
2090 .fp_len = 32,
2091 .fp_proto = FIB_PROTOCOL_IP4,
2092 .fp_addr = {
2093 /* 200.200.200.201/32 */
2094 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2095 },
2096 };
2097 /* via 1.1.1.200 */
2098 fib_prefix_t pfx_1_1_1_200_s_32 = {
2099 .fp_len = 32,
2100 .fp_proto = FIB_PROTOCOL_IP4,
2101 .fp_addr = {
2102 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2103 },
2104 };
2105
Neale Ranns57b58602017-07-15 07:37:25 -07002106 fei = fib_table_entry_path_add(fib_index,
2107 &bgp_201_pfx,
2108 FIB_SOURCE_API,
2109 FIB_ENTRY_FLAG_NONE,
2110 FIB_PROTOCOL_IP4,
2111 &pfx_1_1_1_200_s_32.fp_addr,
2112 ~0, // no index provided.
2113 fib_index, // nexthop in same fib as route
2114 1,
2115 NULL,
2116 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002117
Neale Ranns57b58602017-07-15 07:37:25 -07002118 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2119 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002120
2121 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2122 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2123 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002124 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2125 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002126
2127 /*
2128 * +2 entry (BGP & RR) and +1 shared-path-list
2129 */
2130 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2131 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002132 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002133 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002134 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002135 fib_entry_pool_size());
2136
2137 /*
2138 * insert a route that covers the missing 1.1.1.2/32. we epxect
2139 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2140 */
2141 fib_prefix_t pfx_1_1_1_0_s_24 = {
2142 .fp_len = 24,
2143 .fp_proto = FIB_PROTOCOL_IP4,
2144 .fp_addr = {
2145 /* 1.1.1.0/24 */
2146 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2147 },
2148 };
2149
2150 fib_table_entry_path_add(fib_index,
2151 &pfx_1_1_1_0_s_24,
2152 FIB_SOURCE_API,
2153 FIB_ENTRY_FLAG_NONE,
2154 FIB_PROTOCOL_IP4,
2155 &nh_10_10_10_1,
2156 tm->hw[0]->sw_if_index,
2157 ~0, // invalid fib index
2158 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002159 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002160 FIB_ROUTE_PATH_FLAG_NONE);
2161 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2162 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2163 ai = fib_entry_get_adj(fei);
2164 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2165 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2166 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2167 ai = fib_entry_get_adj(fei);
2168 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2169 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2170 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2171 ai = fib_entry_get_adj(fei);
2172 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2173
2174 /*
2175 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2176 */
2177 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2178 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002179 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002180 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002181 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002182 fib_entry_pool_size());
2183
2184 /*
2185 * the recursive adj for 200.200.200.200 should be updated.
2186 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002187 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2188 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2189 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2190 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2191 tm->hw[0]->sw_if_index),
2192 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002193
2194 /*
2195 * insert a more specific route than 1.1.1.0/24 that also covers the
2196 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2197 * 200.200.200.200 to resolve through it.
2198 */
2199 fib_prefix_t pfx_1_1_1_0_s_28 = {
2200 .fp_len = 28,
2201 .fp_proto = FIB_PROTOCOL_IP4,
2202 .fp_addr = {
2203 /* 1.1.1.0/24 */
2204 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2205 },
2206 };
2207
2208 fib_table_entry_path_add(fib_index,
2209 &pfx_1_1_1_0_s_28,
2210 FIB_SOURCE_API,
2211 FIB_ENTRY_FLAG_NONE,
2212 FIB_PROTOCOL_IP4,
2213 &nh_10_10_10_2,
2214 tm->hw[0]->sw_if_index,
2215 ~0, // invalid fib index
2216 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002217 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002218 FIB_ROUTE_PATH_FLAG_NONE);
2219 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2220 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2221 ai = fib_entry_get_adj(fei);
2222 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2223
2224 /*
2225 * +1 entry. +1 shared path-list
2226 */
2227 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2228 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002229 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002230 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002231 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002232 fib_entry_pool_size());
2233
2234 /*
2235 * the recursive adj for 200.200.200.200 should be updated.
2236 * 200.200.200.201 remains unchanged.
2237 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002238 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2239 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002240
2241 /*
2242 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2243 */
2244 fib_table_entry_path_remove(fib_index,
2245 &pfx_1_1_1_0_s_28,
2246 FIB_SOURCE_API,
2247 FIB_PROTOCOL_IP4,
2248 &nh_10_10_10_2,
2249 tm->hw[0]->sw_if_index,
2250 ~0,
2251 1,
2252 FIB_ROUTE_PATH_FLAG_NONE);
2253 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2254 FIB_NODE_INDEX_INVALID),
2255 "1.1.1.0/28 removed");
2256 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2257 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2258 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002259 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2260 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002261
2262 /*
2263 * -1 entry. -1 shared path-list
2264 */
2265 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2266 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002267 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002268 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002269 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002270 fib_entry_pool_size());
2271
2272 /*
2273 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2274 */
2275 fib_table_entry_path_remove(fib_index,
2276 &pfx_1_1_1_0_s_24,
2277 FIB_SOURCE_API,
2278 FIB_PROTOCOL_IP4,
2279 &nh_10_10_10_1,
2280 tm->hw[0]->sw_if_index,
2281 ~0,
2282 1,
2283 FIB_ROUTE_PATH_FLAG_NONE);
2284 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2285 FIB_NODE_INDEX_INVALID),
2286 "1.1.1.0/24 removed");
2287
2288 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2289 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2290 "1.1.1.2/32 route is DROP");
Neale Ranns57b58602017-07-15 07:37:25 -07002291 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002292 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2293 "1.1.1.200/32 route is DROP");
2294
Neale Ranns57b58602017-07-15 07:37:25 -07002295 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2296 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2297 "201 is drop");
2298 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2299 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2300 "200 is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002301
2302 /*
2303 * -1 entry
2304 */
2305 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2306 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002307 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002308 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002309 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002310 fib_entry_pool_size());
2311
2312 /*
2313 * insert the missing 1.1.1.2/32
2314 */
2315 fei = fib_table_entry_path_add(fib_index,
2316 &pfx_1_1_1_2_s_32,
2317 FIB_SOURCE_API,
2318 FIB_ENTRY_FLAG_NONE,
2319 FIB_PROTOCOL_IP4,
2320 &nh_10_10_10_1,
2321 tm->hw[0]->sw_if_index,
2322 ~0, // invalid fib index
2323 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002324 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002325 FIB_ROUTE_PATH_FLAG_NONE);
2326 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2327 ai = fib_entry_get_adj(fei);
2328 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2329
Neale Ranns57b58602017-07-15 07:37:25 -07002330 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2331 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2332 "201 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01002333 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002334
2335 /*
2336 * no change. 1.1.1.2/32 was already there RR sourced.
2337 */
2338 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2339 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002340 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002341 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002342 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002343 fib_entry_pool_size());
2344
2345 /*
Neale Ranns57b58602017-07-15 07:37:25 -07002346 * give 201 a resolved path.
2347 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2348 * only the latter contributes forwarding.
2349 */
2350 fei = fib_table_entry_path_add(fib_index,
2351 &bgp_201_pfx,
2352 FIB_SOURCE_API,
2353 FIB_ENTRY_FLAG_NONE,
2354 FIB_PROTOCOL_IP4,
2355 &pfx_1_1_1_2_s_32.fp_addr,
2356 ~0,
2357 fib_index,
2358 1,
2359 NULL,
2360 FIB_ROUTE_PATH_FLAG_NONE);
2361 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2362 fib_table_entry_path_remove(fib_index,
2363 &bgp_201_pfx,
2364 FIB_SOURCE_API,
2365 FIB_PROTOCOL_IP4,
2366 &pfx_1_1_1_2_s_32.fp_addr,
2367 ~0,
2368 fib_index,
2369 1,
2370 FIB_ROUTE_PATH_FLAG_NONE);
2371
2372 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002373 * remove 200.200.200.201/32 which does not have a valid via FIB
2374 */
2375 fib_table_entry_path_remove(fib_index,
2376 &bgp_201_pfx,
2377 FIB_SOURCE_API,
2378 FIB_PROTOCOL_IP4,
2379 &pfx_1_1_1_200_s_32.fp_addr,
2380 ~0, // no index provided.
2381 fib_index,
2382 1,
2383 FIB_ROUTE_PATH_FLAG_NONE);
2384
2385 /*
2386 * -2 entries (BGP and RR). -1 shared path-list;
2387 */
2388 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2389 FIB_NODE_INDEX_INVALID),
2390 "200.200.200.201/32 removed");
2391 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2392 FIB_NODE_INDEX_INVALID),
2393 "1.1.1.200/32 removed");
2394
2395 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2396 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002397 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002398 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002399 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002400 fib_entry_pool_size());
2401
2402 /*
2403 * remove 200.200.200.200/32 which does have a valid via FIB
2404 */
2405 fib_table_entry_path_remove(fib_index,
2406 &bgp_200_pfx,
2407 FIB_SOURCE_API,
2408 FIB_PROTOCOL_IP4,
2409 &pfx_1_1_1_2_s_32.fp_addr,
2410 ~0, // no index provided.
2411 fib_index,
2412 1,
2413 FIB_ROUTE_PATH_FLAG_NONE);
2414
2415 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2416 FIB_NODE_INDEX_INVALID),
2417 "200.200.200.200/32 removed");
2418 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2419 FIB_NODE_INDEX_INVALID),
2420 "1.1.1.2/32 still present");
2421
2422 /*
2423 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2424 */
2425 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2426 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002427 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002428 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002429 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002430 fib_entry_pool_size());
2431
2432 /*
2433 * A recursive prefix that has a 2 path load-balance.
2434 * It also shares a next-hop with other BGP prefixes and hence
2435 * test the ref counting of RR sourced prefixes and 2 level LB.
2436 */
2437 const fib_prefix_t bgp_102 = {
2438 .fp_len = 32,
2439 .fp_proto = FIB_PROTOCOL_IP4,
2440 .fp_addr = {
2441 /* 100.100.100.101/32 */
2442 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2443 },
2444 };
2445 fib_table_entry_path_add(fib_index,
2446 &bgp_102,
2447 FIB_SOURCE_API,
2448 FIB_ENTRY_FLAG_NONE,
2449 FIB_PROTOCOL_IP4,
2450 &pfx_1_1_1_1_s_32.fp_addr,
2451 ~0, // no index provided.
2452 fib_index, // same as route
2453 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002454 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002455 FIB_ROUTE_PATH_FLAG_NONE);
2456 fib_table_entry_path_add(fib_index,
2457 &bgp_102,
2458 FIB_SOURCE_API,
2459 FIB_ENTRY_FLAG_NONE,
2460 FIB_PROTOCOL_IP4,
2461 &pfx_1_1_1_2_s_32.fp_addr,
2462 ~0, // no index provided.
2463 fib_index, // same as route's FIB
2464 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002465 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002466 FIB_ROUTE_PATH_FLAG_NONE);
2467 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2468 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2469 dpo = fib_entry_contribute_ip_forwarding(fei);
2470
2471 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2472 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2473 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2474 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2475
2476 lb = load_balance_get(dpo->dpoi_index);
2477 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2478 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2479 "First via 10.10.10.1");
2480 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2481 "Second via 10.10.10.1");
2482
2483 fib_table_entry_path_remove(fib_index,
2484 &bgp_102,
2485 FIB_SOURCE_API,
2486 FIB_PROTOCOL_IP4,
2487 &pfx_1_1_1_1_s_32.fp_addr,
2488 ~0, // no index provided.
2489 fib_index, // same as route's FIB
2490 1,
2491 FIB_ROUTE_PATH_FLAG_NONE);
2492 fib_table_entry_path_remove(fib_index,
2493 &bgp_102,
2494 FIB_SOURCE_API,
2495 FIB_PROTOCOL_IP4,
2496 &pfx_1_1_1_2_s_32.fp_addr,
2497 ~0, // no index provided.
2498 fib_index, // same as route's FIB
2499 1,
2500 FIB_ROUTE_PATH_FLAG_NONE);
2501 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2502 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2503
2504 /*
2505 * remove the remaining recursives
2506 */
2507 fib_table_entry_path_remove(fib_index,
2508 &bgp_100_pfx,
2509 FIB_SOURCE_API,
2510 FIB_PROTOCOL_IP4,
2511 &pfx_1_1_1_1_s_32.fp_addr,
2512 ~0, // no index provided.
2513 fib_index, // same as route's FIB
2514 1,
2515 FIB_ROUTE_PATH_FLAG_NONE);
2516 fib_table_entry_path_remove(fib_index,
2517 &bgp_101_pfx,
2518 FIB_SOURCE_API,
2519 FIB_PROTOCOL_IP4,
2520 &pfx_1_1_1_1_s_32.fp_addr,
2521 ~0, // no index provided.
2522 fib_index, // same as route's FIB
2523 1,
2524 FIB_ROUTE_PATH_FLAG_NONE);
2525 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2526 FIB_NODE_INDEX_INVALID),
2527 "100.100.100.100/32 removed");
2528 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2529 FIB_NODE_INDEX_INVALID),
2530 "100.100.100.101/32 removed");
2531
2532 /*
2533 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2534 */
2535 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2536 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002537 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002538 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002539 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002540 fib_entry_pool_size());
2541
2542 /*
2543 * Add a recursive route via a connected cover, using an adj-fib that does exist
2544 */
2545 fib_table_entry_path_add(fib_index,
2546 &bgp_200_pfx,
2547 FIB_SOURCE_API,
2548 FIB_ENTRY_FLAG_NONE,
2549 FIB_PROTOCOL_IP4,
2550 &nh_10_10_10_1,
2551 ~0, // no index provided.
2552 fib_index, // Same as route's FIB
2553 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002554 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002555 FIB_ROUTE_PATH_FLAG_NONE);
2556
2557 /*
2558 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2559 */
2560 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2561 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002562 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002563 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002564 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002565 fib_entry_pool_size());
2566
2567 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2568 dpo = fib_entry_contribute_ip_forwarding(fei);
2569
2570 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2571 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2572
2573 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2574 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2575
2576 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2577 "Flags set on RR via existing attached");
2578
2579 /*
2580 * Add a recursive route via a connected cover, using and adj-fib that does
2581 * not exist
2582 */
2583 ip46_address_t nh_10_10_10_3 = {
2584 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2585 };
2586 fib_prefix_t pfx_10_10_10_3 = {
2587 .fp_len = 32,
2588 .fp_proto = FIB_PROTOCOL_IP4,
2589 .fp_addr = nh_10_10_10_3,
2590 };
2591
2592 fib_table_entry_path_add(fib_index,
2593 &bgp_201_pfx,
2594 FIB_SOURCE_API,
2595 FIB_ENTRY_FLAG_NONE,
2596 FIB_PROTOCOL_IP4,
2597 &nh_10_10_10_3,
2598 ~0, // no index provided.
2599 fib_index,
2600 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002601 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002602 FIB_ROUTE_PATH_FLAG_NONE);
2603
2604 /*
2605 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2606 * one unshared non-recursive via 10.10.10.3
2607 */
2608 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2609 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002610 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002611 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002612 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002613 fib_entry_pool_size());
2614
2615 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002616 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002617 &nh_10_10_10_3,
2618 tm->hw[0]->sw_if_index);
2619
2620 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2621 dpo = fib_entry_contribute_ip_forwarding(fei);
2622 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2623 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2624
2625 ai = fib_entry_get_adj(fei);
2626 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2627 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2628 fib_entry_get_flags(fei)),
2629 "Flags set on RR via non-existing attached");
2630
2631 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2632 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2633
2634 adj_unlock(ai_03);
2635
2636 /*
2637 * remove the recursives
2638 */
2639 fib_table_entry_path_remove(fib_index,
2640 &bgp_200_pfx,
2641 FIB_SOURCE_API,
2642 FIB_PROTOCOL_IP4,
2643 &nh_10_10_10_1,
2644 ~0, // no index provided.
2645 fib_index, // same as route's FIB
2646 1,
2647 FIB_ROUTE_PATH_FLAG_NONE);
2648 fib_table_entry_path_remove(fib_index,
2649 &bgp_201_pfx,
2650 FIB_SOURCE_API,
2651 FIB_PROTOCOL_IP4,
2652 &nh_10_10_10_3,
2653 ~0, // no index provided.
2654 fib_index, // same as route's FIB
2655 1,
2656 FIB_ROUTE_PATH_FLAG_NONE);
2657
2658 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2659 FIB_NODE_INDEX_INVALID),
2660 "200.200.200.201/32 removed");
2661 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2662 FIB_NODE_INDEX_INVALID),
2663 "200.200.200.200/32 removed");
2664 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2665 FIB_NODE_INDEX_INVALID),
2666 "10.10.10.3/32 removed");
2667
2668 /*
2669 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2670 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2671 */
2672 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2673 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002674 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002675 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002676 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002677 fib_entry_pool_size());
2678
2679
2680 /*
2681 * RECURSION LOOPS
2682 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2683 */
2684 fib_prefix_t pfx_5_5_5_5_s_32 = {
2685 .fp_len = 32,
2686 .fp_proto = FIB_PROTOCOL_IP4,
2687 .fp_addr = {
2688 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2689 },
2690 };
2691 fib_prefix_t pfx_5_5_5_6_s_32 = {
2692 .fp_len = 32,
2693 .fp_proto = FIB_PROTOCOL_IP4,
2694 .fp_addr = {
2695 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2696 },
2697 };
2698 fib_prefix_t pfx_5_5_5_7_s_32 = {
2699 .fp_len = 32,
2700 .fp_proto = FIB_PROTOCOL_IP4,
2701 .fp_addr = {
2702 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2703 },
2704 };
2705
2706 fib_table_entry_path_add(fib_index,
2707 &pfx_5_5_5_5_s_32,
2708 FIB_SOURCE_API,
2709 FIB_ENTRY_FLAG_NONE,
2710 FIB_PROTOCOL_IP4,
2711 &pfx_5_5_5_6_s_32.fp_addr,
2712 ~0, // no index provided.
2713 fib_index,
2714 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002715 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002716 FIB_ROUTE_PATH_FLAG_NONE);
2717 fib_table_entry_path_add(fib_index,
2718 &pfx_5_5_5_6_s_32,
2719 FIB_SOURCE_API,
2720 FIB_ENTRY_FLAG_NONE,
2721 FIB_PROTOCOL_IP4,
2722 &pfx_5_5_5_7_s_32.fp_addr,
2723 ~0, // no index provided.
2724 fib_index,
2725 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002726 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002727 FIB_ROUTE_PATH_FLAG_NONE);
2728 fib_table_entry_path_add(fib_index,
2729 &pfx_5_5_5_7_s_32,
2730 FIB_SOURCE_API,
2731 FIB_ENTRY_FLAG_NONE,
2732 FIB_PROTOCOL_IP4,
2733 &pfx_5_5_5_5_s_32.fp_addr,
2734 ~0, // no index provided.
2735 fib_index,
2736 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002737 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002738 FIB_ROUTE_PATH_FLAG_NONE);
2739 /*
2740 * +3 entries, +3 shared path-list
2741 */
2742 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2743 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002744 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002745 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002746 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002747 fib_entry_pool_size());
2748
2749 /*
2750 * All the entries have only looped paths, so they are all drop
2751 */
2752 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2753 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2754 "LB for 5.5.5.7/32 is via adj for DROP");
2755 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2756 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2757 "LB for 5.5.5.5/32 is via adj for DROP");
2758 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2759 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2760 "LB for 5.5.5.6/32 is via adj for DROP");
2761
2762 /*
2763 * provide 5.5.5.6/32 with alternate path.
2764 * this will allow only 5.5.5.6/32 to forward with this path, the others
2765 * are still drop since the loop is still present.
2766 */
2767 fib_table_entry_path_add(fib_index,
2768 &pfx_5_5_5_6_s_32,
2769 FIB_SOURCE_API,
2770 FIB_ENTRY_FLAG_NONE,
2771 FIB_PROTOCOL_IP4,
2772 &nh_10_10_10_1,
2773 tm->hw[0]->sw_if_index,
2774 ~0,
2775 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002776 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002777 FIB_ROUTE_PATH_FLAG_NONE);
2778
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002779 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2780 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2781
2782 lb = load_balance_get(dpo1->dpoi_index);
2783 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2784
2785 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2786 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2787 FIB_TEST((ai_01 == dpo2->dpoi_index),
2788 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2789
2790 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2791 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2792 "LB for 5.5.5.7/32 is via adj for DROP");
2793 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2794 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2795 "LB for 5.5.5.5/32 is via adj for DROP");
2796
2797 /*
2798 * remove the alternate path for 5.5.5.6/32
2799 * back to all drop
2800 */
2801 fib_table_entry_path_remove(fib_index,
2802 &pfx_5_5_5_6_s_32,
2803 FIB_SOURCE_API,
2804 FIB_PROTOCOL_IP4,
2805 &nh_10_10_10_1,
2806 tm->hw[0]->sw_if_index,
2807 ~0,
2808 1,
2809 FIB_ROUTE_PATH_FLAG_NONE);
2810
2811 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2812 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2813 "LB for 5.5.5.7/32 is via adj for DROP");
2814 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2815 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2816 "LB for 5.5.5.5/32 is via adj for DROP");
2817 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2818 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2819 "LB for 5.5.5.6/32 is via adj for DROP");
2820
2821 /*
2822 * break the loop by giving 5.5.5.5/32 a new set of paths
2823 * expect all to forward via this new path.
2824 */
2825 fib_table_entry_update_one_path(fib_index,
2826 &pfx_5_5_5_5_s_32,
2827 FIB_SOURCE_API,
2828 FIB_ENTRY_FLAG_NONE,
2829 FIB_PROTOCOL_IP4,
2830 &nh_10_10_10_1,
2831 tm->hw[0]->sw_if_index,
2832 ~0, // invalid fib index
2833 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002834 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002835 FIB_ROUTE_PATH_FLAG_NONE);
2836
2837 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2838 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2839 lb = load_balance_get(dpo1->dpoi_index);
2840 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2841
2842 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2843 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2844 FIB_TEST((ai_01 == dpo2->dpoi_index),
2845 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2846
2847 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2848 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2849
2850 lb = load_balance_get(dpo2->dpoi_index);
2851 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2852 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2853 "5.5.5.5.7 via 5.5.5.5");
2854
2855 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2856 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2857
2858 lb = load_balance_get(dpo1->dpoi_index);
2859 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2860 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2861 "5.5.5.5.6 via 5.5.5.7");
2862
2863 /*
2864 * revert back to the loop. so we can remove the prefixes with
2865 * the loop intact
2866 */
2867 fib_table_entry_update_one_path(fib_index,
2868 &pfx_5_5_5_5_s_32,
2869 FIB_SOURCE_API,
2870 FIB_ENTRY_FLAG_NONE,
2871 FIB_PROTOCOL_IP4,
2872 &pfx_5_5_5_6_s_32.fp_addr,
2873 ~0, // no index provided.
2874 fib_index,
2875 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002876 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002877 FIB_ROUTE_PATH_FLAG_NONE);
2878
2879 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2880 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2881 "LB for 5.5.5.7/32 is via adj for DROP");
2882 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2883 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2884 "LB for 5.5.5.5/32 is via adj for DROP");
2885 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2886 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2887 "LB for 5.5.5.6/32 is via adj for DROP");
2888
2889 /*
2890 * remove all the 5.5.5.x/32 prefixes
2891 */
2892 fib_table_entry_path_remove(fib_index,
2893 &pfx_5_5_5_5_s_32,
2894 FIB_SOURCE_API,
2895 FIB_PROTOCOL_IP4,
2896 &pfx_5_5_5_6_s_32.fp_addr,
2897 ~0, // no index provided.
2898 fib_index, // same as route's FIB
2899 1,
2900 FIB_ROUTE_PATH_FLAG_NONE);
2901 fib_table_entry_path_remove(fib_index,
2902 &pfx_5_5_5_6_s_32,
2903 FIB_SOURCE_API,
2904 FIB_PROTOCOL_IP4,
2905 &pfx_5_5_5_7_s_32.fp_addr,
2906 ~0, // no index provided.
2907 fib_index, // same as route's FIB
2908 1,
2909 FIB_ROUTE_PATH_FLAG_NONE);
2910 fib_table_entry_path_remove(fib_index,
2911 &pfx_5_5_5_7_s_32,
2912 FIB_SOURCE_API,
2913 FIB_PROTOCOL_IP4,
2914 &pfx_5_5_5_5_s_32.fp_addr,
2915 ~0, // no index provided.
2916 fib_index, // same as route's FIB
2917 1,
2918 FIB_ROUTE_PATH_FLAG_NONE);
2919 fib_table_entry_path_remove(fib_index,
2920 &pfx_5_5_5_6_s_32,
2921 FIB_SOURCE_API,
2922 FIB_PROTOCOL_IP4,
2923 &nh_10_10_10_2,
2924 ~0, // no index provided.
2925 fib_index, // same as route's FIB
2926 1,
2927 FIB_ROUTE_PATH_FLAG_NONE);
2928
2929 /*
2930 * -3 entries, -3 shared path-list
2931 */
2932 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2933 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002934 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002935 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002936 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002937 fib_entry_pool_size());
2938
2939 /*
2940 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2941 */
2942 fib_table_entry_path_add(fib_index,
2943 &pfx_5_5_5_6_s_32,
2944 FIB_SOURCE_API,
2945 FIB_ENTRY_FLAG_NONE,
2946 FIB_PROTOCOL_IP4,
2947 &pfx_5_5_5_6_s_32.fp_addr,
2948 ~0, // no index provided.
2949 fib_index,
2950 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002951 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002952 FIB_ROUTE_PATH_FLAG_NONE);
2953 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2954 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2955 "1-level 5.5.5.6/32 loop is via adj for DROP");
2956
2957 fib_table_entry_path_remove(fib_index,
2958 &pfx_5_5_5_6_s_32,
2959 FIB_SOURCE_API,
2960 FIB_PROTOCOL_IP4,
2961 &pfx_5_5_5_6_s_32.fp_addr,
2962 ~0, // no index provided.
2963 fib_index, // same as route's FIB
2964 1,
2965 FIB_ROUTE_PATH_FLAG_NONE);
2966 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2967 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2968 "1-level 5.5.5.6/32 loop is removed");
2969
2970 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002971 * A recursive route whose next-hop is covered by the prefix.
2972 * This would mean the via-fib, which inherits forwarding from its
2973 * cover, thus picks up forwarding from the prfix, which is via the
2974 * via-fib, and we have a loop.
2975 */
2976 fib_prefix_t pfx_23_23_23_0_s_24 = {
2977 .fp_len = 24,
2978 .fp_proto = FIB_PROTOCOL_IP4,
2979 .fp_addr = {
2980 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2981 },
2982 };
2983 fib_prefix_t pfx_23_23_23_23_s_32 = {
2984 .fp_len = 32,
2985 .fp_proto = FIB_PROTOCOL_IP4,
2986 .fp_addr = {
2987 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2988 },
2989 };
2990 fei = fib_table_entry_path_add(fib_index,
2991 &pfx_23_23_23_0_s_24,
2992 FIB_SOURCE_API,
2993 FIB_ENTRY_FLAG_NONE,
2994 FIB_PROTOCOL_IP4,
2995 &pfx_23_23_23_23_s_32.fp_addr,
2996 ~0, // recursive
2997 fib_index,
2998 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002999 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003000 FIB_ROUTE_PATH_FLAG_NONE);
3001 dpo = fib_entry_contribute_ip_forwarding(fei);
3002 FIB_TEST(load_balance_is_drop(dpo),
3003 "23.23.23.0/24 via covered is DROP");
3004 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3005
3006 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003007 * add-remove test. no change.
3008 */
3009 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3010 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003011 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003012 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003013 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003014 fib_entry_pool_size());
3015
3016 /*
Neale Ranns08b16482017-05-13 05:52:58 -07003017 * Make the default route recursive via a unknown next-hop. Thus the
3018 * next hop's cover would be the default route
3019 */
3020 fei = fib_table_entry_path_add(fib_index,
3021 &pfx_0_0_0_0_s_0,
3022 FIB_SOURCE_API,
3023 FIB_ENTRY_FLAG_NONE,
3024 FIB_PROTOCOL_IP4,
3025 &pfx_23_23_23_23_s_32.fp_addr,
3026 ~0, // recursive
3027 fib_index,
3028 1,
3029 NULL,
3030 FIB_ROUTE_PATH_FLAG_NONE);
3031 dpo = fib_entry_contribute_ip_forwarding(fei);
3032 FIB_TEST(load_balance_is_drop(dpo),
3033 "0.0.0.0.0/0 via is DROP");
3034 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3035 "no resolving interface for looped 0.0.0.0/0");
3036
3037 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3038 dpo = fib_entry_contribute_ip_forwarding(fei);
3039 FIB_TEST(load_balance_is_drop(dpo),
3040 "23.23.23.23/32 via is DROP");
3041 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3042 "no resolving interface for looped 23.23.23.23/32");
3043
3044 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3045
3046 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003047 * A recursive route with recursion constraints.
3048 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3049 */
3050 fib_table_entry_path_add(fib_index,
3051 &bgp_200_pfx,
3052 FIB_SOURCE_API,
3053 FIB_ENTRY_FLAG_NONE,
3054 FIB_PROTOCOL_IP4,
3055 &nh_1_1_1_1,
3056 ~0,
3057 fib_index,
3058 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003059 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003060 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3061
3062 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3063 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3064
3065 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3066 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3067
3068 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3069 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3070
3071 /*
3072 * save the load-balance. we expect it to be inplace modified
3073 */
3074 lb = load_balance_get(dpo1->dpoi_index);
3075
3076 /*
3077 * add a covering prefix for the via fib that would otherwise serve
3078 * as the resolving route when the host is removed
3079 */
3080 fib_table_entry_path_add(fib_index,
3081 &pfx_1_1_1_0_s_28,
3082 FIB_SOURCE_API,
3083 FIB_ENTRY_FLAG_NONE,
3084 FIB_PROTOCOL_IP4,
3085 &nh_10_10_10_1,
3086 tm->hw[0]->sw_if_index,
3087 ~0, // invalid fib index
3088 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003089 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003090 FIB_ROUTE_PATH_FLAG_NONE);
3091 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3092 ai = fib_entry_get_adj(fei);
3093 FIB_TEST((ai == ai_01),
3094 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3095
3096 /*
3097 * remove the host via FIB - expect the BGP prefix to be drop
3098 */
3099 fib_table_entry_path_remove(fib_index,
3100 &pfx_1_1_1_1_s_32,
3101 FIB_SOURCE_API,
3102 FIB_PROTOCOL_IP4,
3103 &nh_10_10_10_1,
3104 tm->hw[0]->sw_if_index,
3105 ~0, // invalid fib index
3106 1,
3107 FIB_ROUTE_PATH_FLAG_NONE);
3108
3109 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3110 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3111
3112 /*
3113 * add the via-entry host reoute back. expect to resolve again
3114 */
3115 fib_table_entry_path_add(fib_index,
3116 &pfx_1_1_1_1_s_32,
3117 FIB_SOURCE_API,
3118 FIB_ENTRY_FLAG_NONE,
3119 FIB_PROTOCOL_IP4,
3120 &nh_10_10_10_1,
3121 tm->hw[0]->sw_if_index,
3122 ~0, // invalid fib index
3123 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003124 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003125 FIB_ROUTE_PATH_FLAG_NONE);
3126 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3127 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3128
3129 /*
3130 * add another path for the recursive. it will then have 2.
3131 */
3132 fib_prefix_t pfx_1_1_1_3_s_32 = {
3133 .fp_len = 32,
3134 .fp_proto = FIB_PROTOCOL_IP4,
3135 .fp_addr = {
3136 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3137 },
3138 };
3139 fib_table_entry_path_add(fib_index,
3140 &pfx_1_1_1_3_s_32,
3141 FIB_SOURCE_API,
3142 FIB_ENTRY_FLAG_NONE,
3143 FIB_PROTOCOL_IP4,
3144 &nh_10_10_10_2,
3145 tm->hw[0]->sw_if_index,
3146 ~0, // invalid fib index
3147 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003148 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003149 FIB_ROUTE_PATH_FLAG_NONE);
3150
3151 fib_table_entry_path_add(fib_index,
3152 &bgp_200_pfx,
3153 FIB_SOURCE_API,
3154 FIB_ENTRY_FLAG_NONE,
3155 FIB_PROTOCOL_IP4,
3156 &pfx_1_1_1_3_s_32.fp_addr,
3157 ~0,
3158 fib_index,
3159 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003160 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003161 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3162
Neale Rannsf12a83f2017-04-18 09:09:40 -07003163 /*
3164 * add a bunch load more entries using this path combo so that we get
3165 * an LB-map created.
3166 */
3167#define N_P 128
3168 fib_prefix_t bgp_78s[N_P];
3169 for (ii = 0; ii < N_P; ii++)
3170 {
3171 bgp_78s[ii].fp_len = 32;
3172 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3173 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3174
3175
3176 fib_table_entry_path_add(fib_index,
3177 &bgp_78s[ii],
3178 FIB_SOURCE_API,
3179 FIB_ENTRY_FLAG_NONE,
3180 FIB_PROTOCOL_IP4,
3181 &pfx_1_1_1_3_s_32.fp_addr,
3182 ~0,
3183 fib_index,
3184 1,
3185 NULL,
3186 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3187 fib_table_entry_path_add(fib_index,
3188 &bgp_78s[ii],
3189 FIB_SOURCE_API,
3190 FIB_ENTRY_FLAG_NONE,
3191 FIB_PROTOCOL_IP4,
3192 &nh_1_1_1_1,
3193 ~0,
3194 fib_index,
3195 1,
3196 NULL,
3197 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3198 }
3199
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003200 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3201 dpo = fib_entry_contribute_ip_forwarding(fei);
3202
3203 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3204 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3205 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3206 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3207 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3208 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3209 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3210 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3211
3212 /*
3213 * expect the lb-map used by the recursive's load-balance is using both buckets
3214 */
3215 load_balance_map_t *lbm;
3216 index_t lbmi;
3217
3218 lb = load_balance_get(dpo->dpoi_index);
3219 lbmi = lb->lb_map;
3220 load_balance_map_lock(lbmi);
3221 lbm = load_balance_map_get(lbmi);
3222
3223 FIB_TEST(lbm->lbm_buckets[0] == 0,
3224 "LB maps's bucket 0 is %d",
3225 lbm->lbm_buckets[0]);
3226 FIB_TEST(lbm->lbm_buckets[1] == 1,
3227 "LB maps's bucket 1 is %d",
3228 lbm->lbm_buckets[1]);
3229
3230 /*
3231 * withdraw one of the /32 via-entrys.
3232 * that ECMP path will be unresolved and forwarding should continue on the
3233 * other available path. this is an iBGP PIC edge failover.
3234 * Test the forwarding changes without re-fetching the adj from the
3235 * recursive entry. this ensures its the same one that is updated; i.e. an
3236 * inplace-modify.
3237 */
3238 fib_table_entry_path_remove(fib_index,
3239 &pfx_1_1_1_1_s_32,
3240 FIB_SOURCE_API,
3241 FIB_PROTOCOL_IP4,
3242 &nh_10_10_10_1,
3243 tm->hw[0]->sw_if_index,
3244 ~0, // invalid fib index
3245 1,
3246 FIB_ROUTE_PATH_FLAG_NONE);
3247
Neale Rannsf12a83f2017-04-18 09:09:40 -07003248 /* suspend so the update walk kicks int */
3249 vlib_process_suspend(vlib_get_main(), 1e-5);
3250
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003251 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3252 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3253 "post PIC 200.200.200.200/32 was inplace modified");
3254
3255 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3256 "post PIC adj for 200.200.200.200/32 is recursive"
3257 " via adj for 1.1.1.3");
3258
3259 /*
3260 * the LB maps that was locked above should have been modified to remove
3261 * the path that was down, and thus its bucket points to a path that is
3262 * still up.
3263 */
3264 FIB_TEST(lbm->lbm_buckets[0] == 1,
3265 "LB maps's bucket 0 is %d",
3266 lbm->lbm_buckets[0]);
3267 FIB_TEST(lbm->lbm_buckets[1] == 1,
3268 "LB maps's bucket 1 is %d",
3269 lbm->lbm_buckets[1]);
3270
Neale Ranns994dab42017-04-18 12:56:45 -07003271 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003272
3273 /*
3274 * add it back. again
3275 */
3276 fib_table_entry_path_add(fib_index,
3277 &pfx_1_1_1_1_s_32,
3278 FIB_SOURCE_API,
3279 FIB_ENTRY_FLAG_NONE,
3280 FIB_PROTOCOL_IP4,
3281 &nh_10_10_10_1,
3282 tm->hw[0]->sw_if_index,
3283 ~0, // invalid fib index
3284 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003285 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003286 FIB_ROUTE_PATH_FLAG_NONE);
3287
Neale Rannsf12a83f2017-04-18 09:09:40 -07003288 /* suspend so the update walk kicks in */
3289 vlib_process_suspend(vlib_get_main(), 1e-5);
3290
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003291 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3292 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3293 "via adj for 1.1.1.1");
3294 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3295 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3296 "via adj for 1.1.1.3");
3297
3298 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3299 dpo = fib_entry_contribute_ip_forwarding(fei);
3300 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3301 "post PIC 200.200.200.200/32 was inplace modified");
3302
3303 /*
3304 * add a 3rd path. this makes the LB 16 buckets.
3305 */
3306 fib_table_entry_path_add(fib_index,
3307 &bgp_200_pfx,
3308 FIB_SOURCE_API,
3309 FIB_ENTRY_FLAG_NONE,
3310 FIB_PROTOCOL_IP4,
3311 &pfx_1_1_1_2_s_32.fp_addr,
3312 ~0,
3313 fib_index,
3314 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003315 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003316 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003317 for (ii = 0; ii < N_P; ii++)
3318 {
3319 fib_table_entry_path_add(fib_index,
3320 &bgp_78s[ii],
3321 FIB_SOURCE_API,
3322 FIB_ENTRY_FLAG_NONE,
3323 FIB_PROTOCOL_IP4,
3324 &pfx_1_1_1_2_s_32.fp_addr,
3325 ~0,
3326 fib_index,
3327 1,
3328 NULL,
3329 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3330 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003331
3332 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3333 dpo = fib_entry_contribute_ip_forwarding(fei);
3334 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3335 "200.200.200.200/32 was inplace modified for 3rd path");
3336 FIB_TEST(16 == lb->lb_n_buckets,
3337 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3338
3339 lbmi = lb->lb_map;
3340 load_balance_map_lock(lbmi);
3341 lbm = load_balance_map_get(lbmi);
3342
3343 for (ii = 0; ii < 16; ii++)
3344 {
3345 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3346 "LB Map for 200.200.200.200/32 at %d is %d",
3347 ii, lbm->lbm_buckets[ii]);
3348 }
3349
3350 /*
3351 * trigger PIC by removing the first via-entry
3352 * the first 6 buckets of the map should map to the next 6
3353 */
3354 fib_table_entry_path_remove(fib_index,
3355 &pfx_1_1_1_1_s_32,
3356 FIB_SOURCE_API,
3357 FIB_PROTOCOL_IP4,
3358 &nh_10_10_10_1,
3359 tm->hw[0]->sw_if_index,
3360 ~0,
3361 1,
3362 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003363 /* suspend so the update walk kicks int */
3364 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003365
3366 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3367 dpo = fib_entry_contribute_ip_forwarding(fei);
3368 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3369 "200.200.200.200/32 was inplace modified for 3rd path");
3370 FIB_TEST(2 == lb->lb_n_buckets,
3371 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3372
3373 for (ii = 0; ii < 6; ii++)
3374 {
3375 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3376 "LB Map for 200.200.200.200/32 at %d is %d",
3377 ii, lbm->lbm_buckets[ii]);
3378 }
3379 for (ii = 6; ii < 16; ii++)
3380 {
3381 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3382 "LB Map for 200.200.200.200/32 at %d is %d",
3383 ii, lbm->lbm_buckets[ii]);
3384 }
Neale Ranns994dab42017-04-18 12:56:45 -07003385 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003386
3387 /*
3388 * tidy up
3389 */
3390 fib_table_entry_path_add(fib_index,
3391 &pfx_1_1_1_1_s_32,
3392 FIB_SOURCE_API,
3393 FIB_ENTRY_FLAG_NONE,
3394 FIB_PROTOCOL_IP4,
3395 &nh_10_10_10_1,
3396 tm->hw[0]->sw_if_index,
3397 ~0,
3398 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003399 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003400 FIB_ROUTE_PATH_FLAG_NONE);
3401
Neale Rannsf12a83f2017-04-18 09:09:40 -07003402 for (ii = 0; ii < N_P; ii++)
3403 {
3404 fib_table_entry_delete(fib_index,
3405 &bgp_78s[ii],
3406 FIB_SOURCE_API);
3407 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3408 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3409 "%U removed",
3410 format_fib_prefix, &bgp_78s[ii]);
3411 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003412 fib_table_entry_path_remove(fib_index,
3413 &bgp_200_pfx,
3414 FIB_SOURCE_API,
3415 FIB_PROTOCOL_IP4,
3416 &pfx_1_1_1_2_s_32.fp_addr,
3417 ~0,
3418 fib_index,
3419 1,
3420 MPLS_LABEL_INVALID);
3421 fib_table_entry_path_remove(fib_index,
3422 &bgp_200_pfx,
3423 FIB_SOURCE_API,
3424 FIB_PROTOCOL_IP4,
3425 &nh_1_1_1_1,
3426 ~0,
3427 fib_index,
3428 1,
3429 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3430 fib_table_entry_path_remove(fib_index,
3431 &bgp_200_pfx,
3432 FIB_SOURCE_API,
3433 FIB_PROTOCOL_IP4,
3434 &pfx_1_1_1_3_s_32.fp_addr,
3435 ~0,
3436 fib_index,
3437 1,
3438 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3439 fib_table_entry_delete(fib_index,
3440 &pfx_1_1_1_3_s_32,
3441 FIB_SOURCE_API);
3442 fib_table_entry_delete(fib_index,
3443 &pfx_1_1_1_0_s_28,
3444 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003445 /* suspend so the update walk kicks int */
3446 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003447 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3448 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3449 "1.1.1.1/28 removed");
3450 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3451 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3452 "1.1.1.3/32 removed");
3453 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3454 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3455 "200.200.200.200/32 removed");
3456
3457 /*
3458 * add-remove test. no change.
3459 */
3460 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3461 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003462 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003463 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003464 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003465 fib_entry_pool_size());
3466
3467 /*
3468 * A route whose paths are built up iteratively and then removed
3469 * all at once
3470 */
3471 fib_prefix_t pfx_4_4_4_4_s_32 = {
3472 .fp_len = 32,
3473 .fp_proto = FIB_PROTOCOL_IP4,
3474 .fp_addr = {
3475 /* 4.4.4.4/32 */
3476 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3477 },
3478 };
3479
3480 fib_table_entry_path_add(fib_index,
3481 &pfx_4_4_4_4_s_32,
3482 FIB_SOURCE_API,
3483 FIB_ENTRY_FLAG_NONE,
3484 FIB_PROTOCOL_IP4,
3485 &nh_10_10_10_1,
3486 tm->hw[0]->sw_if_index,
3487 ~0,
3488 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003489 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003490 FIB_ROUTE_PATH_FLAG_NONE);
3491 fib_table_entry_path_add(fib_index,
3492 &pfx_4_4_4_4_s_32,
3493 FIB_SOURCE_API,
3494 FIB_ENTRY_FLAG_NONE,
3495 FIB_PROTOCOL_IP4,
3496 &nh_10_10_10_2,
3497 tm->hw[0]->sw_if_index,
3498 ~0,
3499 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003500 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003501 FIB_ROUTE_PATH_FLAG_NONE);
3502 fib_table_entry_path_add(fib_index,
3503 &pfx_4_4_4_4_s_32,
3504 FIB_SOURCE_API,
3505 FIB_ENTRY_FLAG_NONE,
3506 FIB_PROTOCOL_IP4,
3507 &nh_10_10_10_3,
3508 tm->hw[0]->sw_if_index,
3509 ~0,
3510 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003511 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003512 FIB_ROUTE_PATH_FLAG_NONE);
3513 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3514 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3515 "4.4.4.4/32 present");
3516
3517 fib_table_entry_delete(fib_index,
3518 &pfx_4_4_4_4_s_32,
3519 FIB_SOURCE_API);
3520 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3521 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3522 "4.4.4.4/32 removed");
3523
3524 /*
3525 * add-remove test. no change.
3526 */
3527 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3528 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003529 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003530 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003531 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003532 fib_entry_pool_size());
3533
3534 /*
3535 * A route with multiple paths at once
3536 */
3537 fib_route_path_t *r_paths = NULL;
3538
3539 for (ii = 0; ii < 4; ii++)
3540 {
3541 fib_route_path_t r_path = {
3542 .frp_proto = FIB_PROTOCOL_IP4,
3543 .frp_addr = {
3544 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3545 },
3546 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3547 .frp_weight = 1,
3548 .frp_fib_index = ~0,
3549 };
3550 vec_add1(r_paths, r_path);
3551 }
3552
3553 fib_table_entry_update(fib_index,
3554 &pfx_4_4_4_4_s_32,
3555 FIB_SOURCE_API,
3556 FIB_ENTRY_FLAG_NONE,
3557 r_paths);
3558
3559 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3560 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3561 dpo = fib_entry_contribute_ip_forwarding(fei);
3562
3563 lb = load_balance_get(dpo->dpoi_index);
3564 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3565
3566 fib_table_entry_delete(fib_index,
3567 &pfx_4_4_4_4_s_32,
3568 FIB_SOURCE_API);
3569 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3570 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3571 "4.4.4.4/32 removed");
3572 vec_free(r_paths);
3573
3574 /*
3575 * add-remove test. no change.
3576 */
3577 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3578 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003579 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003580 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003581 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003582 fib_entry_pool_size());
3583
3584 /*
3585 * A route deag route
3586 */
3587 fib_table_entry_path_add(fib_index,
3588 &pfx_4_4_4_4_s_32,
3589 FIB_SOURCE_API,
3590 FIB_ENTRY_FLAG_NONE,
3591 FIB_PROTOCOL_IP4,
3592 &zero_addr,
3593 ~0,
3594 fib_index,
3595 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003596 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003597 FIB_ROUTE_PATH_FLAG_NONE);
3598
3599 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3600 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3601
3602 dpo = fib_entry_contribute_ip_forwarding(fei);
3603 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3604 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3605
3606 FIB_TEST((fib_index == lkd->lkd_fib_index),
3607 "4.4.4.4/32 is deag in %d %U",
3608 lkd->lkd_fib_index,
3609 format_dpo_id, dpo, 0);
3610
3611 fib_table_entry_delete(fib_index,
3612 &pfx_4_4_4_4_s_32,
3613 FIB_SOURCE_API);
3614 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3615 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3616 "4.4.4.4/32 removed");
3617 vec_free(r_paths);
3618
3619 /*
3620 * add-remove test. no change.
3621 */
3622 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3623 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003624 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003625 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003626 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003627 fib_entry_pool_size());
3628
3629 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003630 * Duplicate paths:
3631 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3632 */
3633 fib_prefix_t pfx_34_1_1_1_s_32 = {
3634 .fp_len = 32,
3635 .fp_proto = FIB_PROTOCOL_IP4,
3636 .fp_addr = {
3637 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3638 },
3639 };
3640 fib_prefix_t pfx_34_34_1_1_s_32 = {
3641 .fp_len = 32,
3642 .fp_proto = FIB_PROTOCOL_IP4,
3643 .fp_addr = {
3644 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3645 },
3646 };
3647 fei = fib_table_entry_path_add(fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -07003648 &pfx_34_34_1_1_s_32,
3649 FIB_SOURCE_API,
3650 FIB_ENTRY_FLAG_NONE,
3651 FIB_PROTOCOL_IP4,
3652 &nh_10_10_10_1,
3653 tm->hw[0]->sw_if_index,
3654 0,
3655 1,
3656 NULL,
3657 FIB_ROUTE_PATH_FLAG_NONE);
3658 fei = fib_table_entry_path_add(fib_index,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003659 &pfx_34_1_1_1_s_32,
3660 FIB_SOURCE_API,
3661 FIB_ENTRY_FLAG_NONE,
3662 FIB_PROTOCOL_IP4,
3663 &pfx_34_34_1_1_s_32.fp_addr,
3664 ~0,
3665 fib_index,
3666 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003667 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003668 FIB_ROUTE_PATH_FLAG_NONE);
3669 fei = fib_table_entry_path_add(fib_index,
3670 &pfx_34_1_1_1_s_32,
3671 FIB_SOURCE_API,
3672 FIB_ENTRY_FLAG_NONE,
3673 FIB_PROTOCOL_IP4,
3674 &pfx_34_34_1_1_s_32.fp_addr,
3675 ~0,
3676 fib_index,
3677 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003678 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003679 FIB_ROUTE_PATH_FLAG_NONE);
3680 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3681 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
Neale Ranns57b58602017-07-15 07:37:25 -07003682 fib_table_entry_delete(fib_index,
3683 &pfx_34_34_1_1_s_32,
3684 FIB_SOURCE_API);
Neale Rannsbcc889c2016-11-03 14:15:28 -07003685
3686 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003687 * CLEANUP
3688 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3689 * all of which are via 10.10.10.1, Itf1
3690 */
3691 fib_table_entry_path_remove(fib_index,
3692 &pfx_1_1_1_2_s_32,
3693 FIB_SOURCE_API,
3694 FIB_PROTOCOL_IP4,
3695 &nh_10_10_10_1,
3696 tm->hw[0]->sw_if_index,
3697 ~0,
3698 1,
3699 FIB_ROUTE_PATH_FLAG_NONE);
3700 fib_table_entry_path_remove(fib_index,
3701 &pfx_1_1_1_1_s_32,
3702 FIB_SOURCE_API,
3703 FIB_PROTOCOL_IP4,
3704 &nh_10_10_10_1,
3705 tm->hw[0]->sw_if_index,
3706 ~0,
3707 1,
3708 FIB_ROUTE_PATH_FLAG_NONE);
3709 fib_table_entry_path_remove(fib_index,
3710 &pfx_1_1_2_0_s_24,
3711 FIB_SOURCE_API,
3712 FIB_PROTOCOL_IP4,
3713 &nh_10_10_10_1,
3714 tm->hw[0]->sw_if_index,
3715 ~0,
3716 1,
3717 FIB_ROUTE_PATH_FLAG_NONE);
3718
3719 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3720 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3721 "1.1.1.1/32 removed");
3722 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3723 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3724 "1.1.1.2/32 removed");
3725 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3726 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3727 "1.1.2.0/24 removed");
3728
3729 /*
3730 * -3 entries and -1 shared path-list
3731 */
3732 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3733 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003734 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003735 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003736 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003737 fib_entry_pool_size());
3738
3739 /*
3740 * An attached-host route. Expect to link to the incomplete adj
3741 */
3742 fib_prefix_t pfx_4_1_1_1_s_32 = {
3743 .fp_len = 32,
3744 .fp_proto = FIB_PROTOCOL_IP4,
3745 .fp_addr = {
3746 /* 4.1.1.1/32 */
3747 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3748 },
3749 };
3750 fib_table_entry_path_add(fib_index,
3751 &pfx_4_1_1_1_s_32,
3752 FIB_SOURCE_API,
3753 FIB_ENTRY_FLAG_NONE,
3754 FIB_PROTOCOL_IP4,
3755 &zero_addr,
3756 tm->hw[0]->sw_if_index,
3757 fib_index,
3758 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003759 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003760 FIB_ROUTE_PATH_FLAG_NONE);
3761
3762 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3763 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3764 ai = fib_entry_get_adj(fei);
3765
3766 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003767 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003768 &pfx_4_1_1_1_s_32.fp_addr,
3769 tm->hw[0]->sw_if_index);
3770 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3771 adj_unlock(ai2);
3772
3773 /*
3774 * +1 entry and +1 shared path-list
3775 */
3776 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3777 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003778 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003779 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003780 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003781 fib_entry_pool_size());
3782
3783 fib_table_entry_delete(fib_index,
3784 &pfx_4_1_1_1_s_32,
3785 FIB_SOURCE_API);
3786
3787 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3788 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003789 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003790 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003791 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003792 fib_entry_pool_size());
3793
3794 /*
3795 * add a v6 prefix via v4 next-hops
3796 */
3797 fib_prefix_t pfx_2001_s_64 = {
3798 .fp_len = 64,
3799 .fp_proto = FIB_PROTOCOL_IP6,
3800 .fp_addr = {
3801 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3802 },
3803 };
3804 fei = fib_table_entry_path_add(0, //default v6 table
3805 &pfx_2001_s_64,
3806 FIB_SOURCE_API,
3807 FIB_ENTRY_FLAG_NONE,
3808 FIB_PROTOCOL_IP4,
3809 &nh_10_10_10_1,
3810 tm->hw[0]->sw_if_index,
3811 fib_index,
3812 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003813 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003814 FIB_ROUTE_PATH_FLAG_NONE);
3815
3816 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3817 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3818 ai = fib_entry_get_adj(fei);
3819 adj = adj_get(ai);
3820 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3821 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003822 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003823 "2001::/64 is link type v6");
3824 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3825 "2001::/64 ADJ-adj is NH proto v4");
3826 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3827
Neale Ranns3ee44042016-10-03 13:05:48 +01003828 /*
3829 * add a uRPF exempt prefix:
3830 * test:
3831 * - it's forwarding is drop
3832 * - it's uRPF list is not empty
3833 * - the uRPF list for the default route (it's cover) is empty
3834 */
3835 fei = fib_table_entry_special_add(fib_index,
3836 &pfx_4_1_1_1_s_32,
3837 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003838 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003839 dpo = fib_entry_contribute_ip_forwarding(fei);
3840 FIB_TEST(load_balance_is_drop(dpo),
3841 "uRPF exempt 4.1.1.1/32 DROP");
3842 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3843 "uRPF list for exempt prefix has itf index 0");
3844 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3845 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3846 "uRPF list for 0.0.0.0/0 empty");
3847
3848 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003849
3850 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003851 * An adj-fib that fails the refinement criteria - no connected cover
3852 */
3853 fib_prefix_t pfx_12_10_10_2_s_32 = {
3854 .fp_len = 32,
3855 .fp_proto = FIB_PROTOCOL_IP4,
3856 .fp_addr = {
3857 /* 12.10.10.2 */
3858 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3859 },
3860 };
3861
Neale Ranns81424992017-05-18 03:03:22 -07003862 fib_table_entry_path_add(fib_index,
3863 &pfx_12_10_10_2_s_32,
3864 FIB_SOURCE_ADJ,
3865 FIB_ENTRY_FLAG_ATTACHED,
3866 FIB_PROTOCOL_IP4,
3867 &pfx_12_10_10_2_s_32.fp_addr,
3868 tm->hw[0]->sw_if_index,
3869 ~0, // invalid fib index
3870 1,
3871 NULL,
3872 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003873
3874 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3875 dpo = fib_entry_contribute_ip_forwarding(fei);
3876 FIB_TEST(!dpo_id_is_valid(dpo),
3877 "no connected cover adj-fib fails refinement");
3878
3879 fib_table_entry_delete(fib_index,
3880 &pfx_12_10_10_2_s_32,
3881 FIB_SOURCE_ADJ);
3882
3883 /*
3884 * An adj-fib that fails the refinement criteria - cover is connected
3885 * but on a different interface
3886 */
3887 fib_prefix_t pfx_10_10_10_127_s_32 = {
3888 .fp_len = 32,
3889 .fp_proto = FIB_PROTOCOL_IP4,
3890 .fp_addr = {
3891 /* 10.10.10.127 */
3892 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3893 },
3894 };
3895
Neale Ranns81424992017-05-18 03:03:22 -07003896 fib_table_entry_path_add(fib_index,
3897 &pfx_10_10_10_127_s_32,
3898 FIB_SOURCE_ADJ,
3899 FIB_ENTRY_FLAG_ATTACHED,
3900 FIB_PROTOCOL_IP4,
3901 &pfx_10_10_10_127_s_32.fp_addr,
3902 tm->hw[1]->sw_if_index,
3903 ~0, // invalid fib index
3904 1,
3905 NULL,
3906 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003907
3908 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3909 dpo = fib_entry_contribute_ip_forwarding(fei);
3910 FIB_TEST(!dpo_id_is_valid(dpo),
3911 "wrong interface adj-fib fails refinement");
3912
3913 fib_table_entry_delete(fib_index,
3914 &pfx_10_10_10_127_s_32,
3915 FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07003916
3917 /*
3918 * add a second path to an adj-fib
3919 * this is a sumiluation of another ARP entry created
3920 * on an interface on which the connected prefi does not exist.
3921 * The second path fails refinement. Expect to forward through the
3922 * first.
3923 */
3924 fib_prefix_t pfx_10_10_10_3_s_32 = {
3925 .fp_len = 32,
3926 .fp_proto = FIB_PROTOCOL_IP4,
3927 .fp_addr = {
3928 /* 10.10.10.3 */
3929 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3930 },
3931 };
3932
3933 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3934 VNET_LINK_IP4,
3935 &nh_10_10_10_3,
3936 tm->hw[0]->sw_if_index);
3937
3938 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
3939 .type = FT_LB_ADJ,
3940 .adj = {
3941 .adj = ai_03,
3942 },
3943 };
3944 fei = fib_table_entry_path_add(fib_index,
3945 &pfx_10_10_10_3_s_32,
3946 FIB_SOURCE_ADJ,
3947 FIB_ENTRY_FLAG_NONE,
3948 FIB_PROTOCOL_IP4,
3949 &nh_10_10_10_3,
3950 tm->hw[0]->sw_if_index,
3951 fib_index,
3952 1,
3953 NULL,
3954 FIB_ROUTE_PATH_FLAG_NONE);
3955 fei = fib_table_entry_path_add(fib_index,
3956 &pfx_10_10_10_3_s_32,
3957 FIB_SOURCE_ADJ,
3958 FIB_ENTRY_FLAG_NONE,
3959 FIB_PROTOCOL_IP4,
3960 &nh_12_12_12_12,
3961 tm->hw[1]->sw_if_index,
3962 fib_index,
3963 1,
3964 NULL,
3965 FIB_ROUTE_PATH_FLAG_NONE);
3966 FIB_TEST(fib_test_validate_entry(fei,
3967 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3968 1,
3969 &ip_o_10_10_10_3),
3970 "10.10.10.3 via 10.10.10.3/Eth0 only");
3971
3972 /*
3973 * remove the path that refines the cover, should go unresolved
3974 */
3975 fib_table_entry_path_remove(fib_index,
3976 &pfx_10_10_10_3_s_32,
3977 FIB_SOURCE_ADJ,
3978 FIB_PROTOCOL_IP4,
3979 &nh_10_10_10_3,
3980 tm->hw[0]->sw_if_index,
3981 fib_index,
3982 1,
3983 FIB_ROUTE_PATH_FLAG_NONE);
3984 dpo = fib_entry_contribute_ip_forwarding(fei);
3985 FIB_TEST(!dpo_id_is_valid(dpo),
3986 "wrong interface adj-fib fails refinement");
3987
3988 /*
3989 * add back the path that refines the cover
3990 */
3991 fei = fib_table_entry_path_add(fib_index,
3992 &pfx_10_10_10_3_s_32,
3993 FIB_SOURCE_ADJ,
3994 FIB_ENTRY_FLAG_NONE,
3995 FIB_PROTOCOL_IP4,
3996 &nh_10_10_10_3,
3997 tm->hw[0]->sw_if_index,
3998 fib_index,
3999 1,
4000 NULL,
4001 FIB_ROUTE_PATH_FLAG_NONE);
4002 FIB_TEST(fib_test_validate_entry(fei,
4003 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4004 1,
4005 &ip_o_10_10_10_3),
4006 "10.10.10.3 via 10.10.10.3/Eth0 only");
4007
4008 /*
4009 * remove the path that does not refine the cover
4010 */
4011 fib_table_entry_path_remove(fib_index,
4012 &pfx_10_10_10_3_s_32,
4013 FIB_SOURCE_ADJ,
4014 FIB_PROTOCOL_IP4,
4015 &nh_12_12_12_12,
4016 tm->hw[1]->sw_if_index,
4017 fib_index,
4018 1,
4019 FIB_ROUTE_PATH_FLAG_NONE);
4020 FIB_TEST(fib_test_validate_entry(fei,
4021 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4022 1,
4023 &ip_o_10_10_10_3),
4024 "10.10.10.3 via 10.10.10.3/Eth0 only");
4025
4026 /*
4027 * remove the path that does refine, it's the last path, so
4028 * the entry should be gone
4029 */
4030 fib_table_entry_path_remove(fib_index,
4031 &pfx_10_10_10_3_s_32,
4032 FIB_SOURCE_ADJ,
4033 FIB_PROTOCOL_IP4,
4034 &nh_10_10_10_3,
4035 tm->hw[0]->sw_if_index,
4036 fib_index,
4037 1,
4038 FIB_ROUTE_PATH_FLAG_NONE);
4039 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4040 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4041
4042 adj_unlock(ai_03);
4043
Neale Ranns227038a2017-04-21 01:07:59 -07004044 /*
4045 * change the table's flow-hash config - expect the update to propagete to
4046 * the entries' load-balance objects
4047 */
4048 flow_hash_config_t old_hash_config, new_hash_config;
4049
4050 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4051 FIB_PROTOCOL_IP4);
4052 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4053 IP_FLOW_HASH_DST_ADDR);
4054
4055 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4056 dpo = fib_entry_contribute_ip_forwarding(fei);
4057 lb = load_balance_get(dpo->dpoi_index);
4058 FIB_TEST((lb->lb_hash_config == old_hash_config),
4059 "Table and LB hash config match: %U",
4060 format_ip_flow_hash_config, lb->lb_hash_config);
4061
4062 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4063
4064 FIB_TEST((lb->lb_hash_config == new_hash_config),
4065 "Table and LB newhash config match: %U",
4066 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08004067
4068 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004069 * CLEANUP
4070 * remove adj-fibs:
4071 */
4072 fib_table_entry_delete(fib_index,
4073 &pfx_10_10_10_1_s_32,
4074 FIB_SOURCE_ADJ);
4075 fib_table_entry_delete(fib_index,
4076 &pfx_10_10_10_2_s_32,
4077 FIB_SOURCE_ADJ);
4078 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4079 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4080 "10.10.10.1/32 adj-fib removed");
4081 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4082 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4083 "10.10.10.2/32 adj-fib removed");
4084
4085 /*
4086 * -2 entries and -2 non-shared path-list
4087 */
4088 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4089 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004090 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004091 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004092 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004093 fib_entry_pool_size());
4094
4095 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01004096 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004097 * These are the last locks on these adjs. they should thus go away.
4098 */
4099 adj_unlock(ai_02);
4100 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01004101 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004102
4103 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4104 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00004105
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004106 /*
4107 * CLEANUP
4108 * remove the interface prefixes
4109 */
4110 local_pfx.fp_len = 32;
4111 fib_table_entry_special_remove(fib_index, &local_pfx,
4112 FIB_SOURCE_INTERFACE);
4113 fei = fib_table_lookup(fib_index, &local_pfx);
4114
4115 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4116 fib_table_lookup_exact_match(fib_index, &local_pfx),
4117 "10.10.10.10/32 adj-fib removed");
4118
4119 local_pfx.fp_len = 24;
4120 fib_table_entry_delete(fib_index, &local_pfx,
4121 FIB_SOURCE_INTERFACE);
4122
4123 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4124 fib_table_lookup_exact_match(fib_index, &local_pfx),
4125 "10.10.10.10/24 adj-fib removed");
4126
4127 /*
4128 * -2 entries and -2 non-shared path-list
4129 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07004130 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004131 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004132 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004133 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004134 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004135 fib_entry_pool_size());
4136
4137 /*
4138 * Last but not least, remove the VRF
4139 */
4140 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4141 FIB_PROTOCOL_IP4,
4142 FIB_SOURCE_API)),
4143 "NO API Source'd prefixes");
4144 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4145 FIB_PROTOCOL_IP4,
4146 FIB_SOURCE_RR)),
4147 "NO RR Source'd prefixes");
4148 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4149 FIB_PROTOCOL_IP4,
4150 FIB_SOURCE_INTERFACE)),
4151 "NO INterface Source'd prefixes");
4152
4153 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
4154
4155 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4156 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004157 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004158 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004159 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004160 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004161 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01004162 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004163 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07004164 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004165 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4166 pool_elts(load_balance_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004167
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004168 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004169}
4170
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004171static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004172fib_test_v6 (void)
4173{
4174 /*
4175 * In the default table check for the presence and correct forwarding
4176 * of the special entries
4177 */
4178 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4179 const dpo_id_t *dpo, *dpo_drop;
4180 const ip_adjacency_t *adj;
4181 const receive_dpo_t *rd;
4182 test_main_t *tm;
4183 u32 fib_index;
4184 int ii;
4185
4186 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4187 adj_nbr_db_size());
4188
4189 /* via 2001:0:0:1::2 */
4190 ip46_address_t nh_2001_2 = {
4191 .ip6 = {
4192 .as_u64 = {
4193 [0] = clib_host_to_net_u64(0x2001000000000001),
4194 [1] = clib_host_to_net_u64(0x0000000000000002),
4195 },
4196 },
4197 };
4198
4199 tm = &test_main;
4200
4201 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4202
4203 /* Find or create FIB table 11 */
4204 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
4205
4206 for (ii = 0; ii < 4; ii++)
4207 {
4208 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4209 }
4210
4211 fib_prefix_t pfx_0_0 = {
4212 .fp_len = 0,
4213 .fp_proto = FIB_PROTOCOL_IP6,
4214 .fp_addr = {
4215 .ip6 = {
4216 {0, 0},
4217 },
4218 },
4219 };
4220
4221 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4222 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4223 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4224 "Default route is DROP");
4225
4226 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4227 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4228 &ip6_main,
4229 1,
4230 &pfx_0_0.fp_addr.ip6)),
4231 "default-route; fwd and non-fwd tables match");
4232
4233 // FIXME - check specials.
4234
4235 /*
4236 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004237 * each with 2 entries and a v6 mfib with 4 path-lists.
4238 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004239 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004240#define ENPS (5+4)
4241#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004242 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004243 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004244 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004245 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004246 fib_entry_pool_size());
4247
4248 /*
4249 * add interface routes.
4250 * validate presence of /64 attached and /128 recieve.
4251 * test for the presence of the receive address in the glean and local adj
4252 *
4253 * receive on 2001:0:0:1::1/128
4254 */
4255 fib_prefix_t local_pfx = {
4256 .fp_len = 64,
4257 .fp_proto = FIB_PROTOCOL_IP6,
4258 .fp_addr = {
4259 .ip6 = {
4260 .as_u64 = {
4261 [0] = clib_host_to_net_u64(0x2001000000000001),
4262 [1] = clib_host_to_net_u64(0x0000000000000001),
4263 },
4264 },
4265 }
4266 };
4267
4268 fib_table_entry_update_one_path(fib_index, &local_pfx,
4269 FIB_SOURCE_INTERFACE,
4270 (FIB_ENTRY_FLAG_CONNECTED |
4271 FIB_ENTRY_FLAG_ATTACHED),
4272 FIB_PROTOCOL_IP6,
4273 NULL,
4274 tm->hw[0]->sw_if_index,
4275 ~0,
4276 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004277 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004278 FIB_ROUTE_PATH_FLAG_NONE);
4279 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4280
4281 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4282
4283 ai = fib_entry_get_adj(fei);
4284 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4285 adj = adj_get(ai);
4286 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4287 "attached interface adj is glean");
4288 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4289 &adj->sub_type.glean.receive_addr)),
4290 "attached interface adj is receive ok");
4291 dpo = fib_entry_contribute_ip_forwarding(fei);
4292 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4293 &ip6_main,
4294 1,
4295 &local_pfx.fp_addr.ip6)),
4296 "attached-route; fwd and non-fwd tables match");
4297
4298 local_pfx.fp_len = 128;
4299 fib_table_entry_update_one_path(fib_index, &local_pfx,
4300 FIB_SOURCE_INTERFACE,
4301 (FIB_ENTRY_FLAG_CONNECTED |
4302 FIB_ENTRY_FLAG_LOCAL),
4303 FIB_PROTOCOL_IP6,
4304 NULL,
4305 tm->hw[0]->sw_if_index,
4306 ~0, // invalid fib index
4307 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004308 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004309 FIB_ROUTE_PATH_FLAG_NONE);
4310 fei = fib_table_lookup(fib_index, &local_pfx);
4311
4312 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4313
4314 dpo = fib_entry_contribute_ip_forwarding(fei);
4315 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4316 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4317 "local interface adj is local");
4318 rd = receive_dpo_get(dpo->dpoi_index);
4319
4320 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4321 &rd->rd_addr)),
4322 "local interface adj is receive ok");
4323
4324 dpo = fib_entry_contribute_ip_forwarding(fei);
4325 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4326 &ip6_main,
4327 1,
4328 &local_pfx.fp_addr.ip6)),
4329 "local-route; fwd and non-fwd tables match");
4330
4331 /*
4332 * +2 entries. +2 unshared path-lists
4333 */
4334 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004335 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004336 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004337 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004338 fib_entry_pool_size());
4339
4340 /*
4341 * Modify the default route to be via an adj not yet known.
4342 * this sources the defalut route with the API source, which is
4343 * a higher preference to the DEFAULT_ROUTE source
4344 */
4345 fib_table_entry_path_add(fib_index, &pfx_0_0,
4346 FIB_SOURCE_API,
4347 FIB_ENTRY_FLAG_NONE,
4348 FIB_PROTOCOL_IP6,
4349 &nh_2001_2,
4350 tm->hw[0]->sw_if_index,
4351 ~0,
4352 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004353 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004354 FIB_ROUTE_PATH_FLAG_NONE);
4355 fei = fib_table_lookup(fib_index, &pfx_0_0);
4356
4357 FIB_TEST((fei == dfrt), "default route same index");
4358 ai = fib_entry_get_adj(fei);
4359 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4360 adj = adj_get(ai);
4361 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4362 "adj is incomplete");
4363 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4364 "adj nbr next-hop ok");
4365
4366 /*
4367 * find the adj in the shared db
4368 */
4369 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004370 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004371 &nh_2001_2,
4372 tm->hw[0]->sw_if_index);
4373 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4374 adj_unlock(locked_ai);
4375
4376 /*
4377 * no more entires. +1 shared path-list
4378 */
4379 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4380 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004381 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004382 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004383 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004384 fib_entry_pool_size());
4385
4386 /*
4387 * remove the API source from the default route. We expected
4388 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4389 */
4390 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4391 FIB_SOURCE_API,
4392 FIB_PROTOCOL_IP6,
4393 &nh_2001_2,
4394 tm->hw[0]->sw_if_index,
4395 ~0,
4396 1,
4397 FIB_ROUTE_PATH_FLAG_NONE);
4398 fei = fib_table_lookup(fib_index, &pfx_0_0);
4399
4400 FIB_TEST((fei == dfrt), "default route same index");
4401 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4402 "Default route is DROP");
4403
4404 /*
4405 * no more entires. -1 shared path-list
4406 */
4407 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4408 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004409 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004410 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004411 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004412 fib_entry_pool_size());
4413
4414 /*
4415 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4416 */
4417 fib_prefix_t pfx_2001_1_2_s_128 = {
4418 .fp_len = 128,
4419 .fp_proto = FIB_PROTOCOL_IP6,
4420 .fp_addr = {
4421 .ip6 = {
4422 .as_u64 = {
4423 [0] = clib_host_to_net_u64(0x2001000000000001),
4424 [1] = clib_host_to_net_u64(0x0000000000000002),
4425 },
4426 },
4427 }
4428 };
4429 fib_prefix_t pfx_2001_1_3_s_128 = {
4430 .fp_len = 128,
4431 .fp_proto = FIB_PROTOCOL_IP6,
4432 .fp_addr = {
4433 .ip6 = {
4434 .as_u64 = {
4435 [0] = clib_host_to_net_u64(0x2001000000000001),
4436 [1] = clib_host_to_net_u64(0x0000000000000003),
4437 },
4438 },
4439 }
4440 };
4441 u8 eth_addr[] = {
4442 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4443 };
4444
4445 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004446 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004447 &pfx_2001_1_2_s_128.fp_addr,
4448 tm->hw[0]->sw_if_index);
4449 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4450 adj = adj_get(ai_01);
4451 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4452 "adj is incomplete");
4453 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4454 &adj->sub_type.nbr.next_hop)),
4455 "adj nbr next-hop ok");
4456
Neale Rannsb80c5362016-10-08 13:03:40 +01004457 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4458 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004459 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4460 "adj is complete");
4461 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4462 &adj->sub_type.nbr.next_hop)),
4463 "adj nbr next-hop ok");
4464
Neale Ranns81424992017-05-18 03:03:22 -07004465 fib_table_entry_path_add(fib_index,
4466 &pfx_2001_1_2_s_128,
4467 FIB_SOURCE_ADJ,
4468 FIB_ENTRY_FLAG_ATTACHED,
4469 FIB_PROTOCOL_IP6,
4470 &pfx_2001_1_2_s_128.fp_addr,
4471 tm->hw[0]->sw_if_index,
4472 ~0,
4473 1,
4474 NULL,
4475 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004476
4477 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4478 ai = fib_entry_get_adj(fei);
4479 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4480
4481 eth_addr[5] = 0xb2;
4482
4483 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004484 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004485 &pfx_2001_1_3_s_128.fp_addr,
4486 tm->hw[0]->sw_if_index);
4487 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4488 adj = adj_get(ai_02);
4489 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4490 "adj is incomplete");
4491 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4492 &adj->sub_type.nbr.next_hop)),
4493 "adj nbr next-hop ok");
4494
Neale Rannsb80c5362016-10-08 13:03:40 +01004495 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4496 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004497 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4498 "adj is complete");
4499 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4500 &adj->sub_type.nbr.next_hop)),
4501 "adj nbr next-hop ok");
4502 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4503
Neale Ranns81424992017-05-18 03:03:22 -07004504 fib_table_entry_path_add(fib_index,
4505 &pfx_2001_1_3_s_128,
4506 FIB_SOURCE_ADJ,
4507 FIB_ENTRY_FLAG_ATTACHED,
4508 FIB_PROTOCOL_IP6,
4509 &pfx_2001_1_3_s_128.fp_addr,
4510 tm->hw[0]->sw_if_index,
4511 ~0,
4512 1,
4513 NULL,
4514 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004515
4516 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4517 ai = fib_entry_get_adj(fei);
4518 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4519
4520 /*
4521 * +2 entries, +2 unshread path-lists.
4522 */
4523 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4524 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004525 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004526 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004527 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004528 fib_entry_pool_size());
4529
4530 /*
4531 * Add a 2 routes via the first ADJ. ensure path-list sharing
4532 */
4533 fib_prefix_t pfx_2001_a_s_64 = {
4534 .fp_len = 64,
4535 .fp_proto = FIB_PROTOCOL_IP6,
4536 .fp_addr = {
4537 .ip6 = {
4538 .as_u64 = {
4539 [0] = clib_host_to_net_u64(0x200100000000000a),
4540 [1] = clib_host_to_net_u64(0x0000000000000000),
4541 },
4542 },
4543 }
4544 };
4545 fib_prefix_t pfx_2001_b_s_64 = {
4546 .fp_len = 64,
4547 .fp_proto = FIB_PROTOCOL_IP6,
4548 .fp_addr = {
4549 .ip6 = {
4550 .as_u64 = {
4551 [0] = clib_host_to_net_u64(0x200100000000000b),
4552 [1] = clib_host_to_net_u64(0x0000000000000000),
4553 },
4554 },
4555 }
4556 };
4557
4558 fib_table_entry_path_add(fib_index,
4559 &pfx_2001_a_s_64,
4560 FIB_SOURCE_API,
4561 FIB_ENTRY_FLAG_NONE,
4562 FIB_PROTOCOL_IP6,
4563 &nh_2001_2,
4564 tm->hw[0]->sw_if_index,
4565 ~0,
4566 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004567 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004568 FIB_ROUTE_PATH_FLAG_NONE);
4569 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4570 ai = fib_entry_get_adj(fei);
4571 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4572 fib_table_entry_path_add(fib_index,
4573 &pfx_2001_b_s_64,
4574 FIB_SOURCE_API,
4575 FIB_ENTRY_FLAG_NONE,
4576 FIB_PROTOCOL_IP6,
4577 &nh_2001_2,
4578 tm->hw[0]->sw_if_index,
4579 ~0,
4580 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004581 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004582 FIB_ROUTE_PATH_FLAG_NONE);
4583 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4584 ai = fib_entry_get_adj(fei);
4585 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4586
4587 /*
4588 * +2 entries, +1 shared path-list.
4589 */
4590 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4591 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004592 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004593 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004594 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004595 fib_entry_pool_size());
4596
4597 /*
4598 * add a v4 prefix via a v6 next-hop
4599 */
4600 fib_prefix_t pfx_1_1_1_1_s_32 = {
4601 .fp_len = 32,
4602 .fp_proto = FIB_PROTOCOL_IP4,
4603 .fp_addr = {
4604 .ip4.as_u32 = 0x01010101,
4605 },
4606 };
4607 fei = fib_table_entry_path_add(0, // default table
4608 &pfx_1_1_1_1_s_32,
4609 FIB_SOURCE_API,
4610 FIB_ENTRY_FLAG_NONE,
4611 FIB_PROTOCOL_IP6,
4612 &nh_2001_2,
4613 tm->hw[0]->sw_if_index,
4614 ~0,
4615 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004616 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004617 FIB_ROUTE_PATH_FLAG_NONE);
4618 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4619 "1.1.1.1/32 o v6 route present");
4620 ai = fib_entry_get_adj(fei);
4621 adj = adj_get(ai);
4622 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4623 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004624 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004625 "1.1.1.1/32 ADJ-adj is link type v4");
4626 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4627 "1.1.1.1/32 ADJ-adj is NH proto v6");
4628 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4629
4630 /*
4631 * An attached route
4632 */
4633 fib_prefix_t pfx_2001_c_s_64 = {
4634 .fp_len = 64,
4635 .fp_proto = FIB_PROTOCOL_IP6,
4636 .fp_addr = {
4637 .ip6 = {
4638 .as_u64 = {
4639 [0] = clib_host_to_net_u64(0x200100000000000c),
4640 [1] = clib_host_to_net_u64(0x0000000000000000),
4641 },
4642 },
4643 }
4644 };
4645 fib_table_entry_path_add(fib_index,
4646 &pfx_2001_c_s_64,
4647 FIB_SOURCE_CLI,
4648 FIB_ENTRY_FLAG_ATTACHED,
4649 FIB_PROTOCOL_IP6,
4650 NULL,
4651 tm->hw[0]->sw_if_index,
4652 ~0,
4653 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004654 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004655 FIB_ROUTE_PATH_FLAG_NONE);
4656 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4657 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4658 ai = fib_entry_get_adj(fei);
4659 adj = adj_get(ai);
4660 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4661 "2001:0:0:c/64 attached resolves via glean");
4662
4663 fib_table_entry_path_remove(fib_index,
4664 &pfx_2001_c_s_64,
4665 FIB_SOURCE_CLI,
4666 FIB_PROTOCOL_IP6,
4667 NULL,
4668 tm->hw[0]->sw_if_index,
4669 ~0,
4670 1,
4671 FIB_ROUTE_PATH_FLAG_NONE);
4672 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4673 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4674
4675 /*
4676 * Shutdown the interface on which we have a connected and through
4677 * which the routes are reachable.
4678 * This will result in the connected, adj-fibs, and routes linking to drop
4679 * The local/for-us prefix continues to receive.
4680 */
4681 clib_error_t * error;
4682
4683 error = vnet_sw_interface_set_flags(vnet_get_main(),
4684 tm->hw[0]->sw_if_index,
4685 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4686 FIB_TEST((NULL == error), "Interface shutdown OK");
4687
4688 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4689 dpo = fib_entry_contribute_ip_forwarding(fei);
4690 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4691 "2001::b/64 resolves via drop");
4692
4693 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4694 dpo = fib_entry_contribute_ip_forwarding(fei);
4695 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4696 "2001::a/64 resolves via drop");
4697 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4698 dpo = fib_entry_contribute_ip_forwarding(fei);
4699 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4700 "2001:0:0:1::3/64 resolves via drop");
4701 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4702 dpo = fib_entry_contribute_ip_forwarding(fei);
4703 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4704 "2001:0:0:1::2/64 resolves via drop");
4705 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4706 dpo = fib_entry_contribute_ip_forwarding(fei);
4707 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4708 "2001:0:0:1::1/128 not drop");
4709 local_pfx.fp_len = 64;
4710 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4711 dpo = fib_entry_contribute_ip_forwarding(fei);
4712 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4713 "2001:0:0:1/64 resolves via drop");
4714
4715 /*
4716 * no change
4717 */
4718 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4719 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004720 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004721 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004722 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004723 fib_entry_pool_size());
4724
4725 /*
4726 * shutdown one of the other interfaces, then add a connected.
4727 * and swap one of the routes to it.
4728 */
4729 error = vnet_sw_interface_set_flags(vnet_get_main(),
4730 tm->hw[1]->sw_if_index,
4731 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4732 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4733
4734 fib_prefix_t connected_pfx = {
4735 .fp_len = 64,
4736 .fp_proto = FIB_PROTOCOL_IP6,
4737 .fp_addr = {
4738 .ip6 = {
4739 /* 2001:0:0:2::1/64 */
4740 .as_u64 = {
4741 [0] = clib_host_to_net_u64(0x2001000000000002),
4742 [1] = clib_host_to_net_u64(0x0000000000000001),
4743 },
4744 },
4745 }
4746 };
4747 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4748 FIB_SOURCE_INTERFACE,
4749 (FIB_ENTRY_FLAG_CONNECTED |
4750 FIB_ENTRY_FLAG_ATTACHED),
4751 FIB_PROTOCOL_IP6,
4752 NULL,
4753 tm->hw[1]->sw_if_index,
4754 ~0,
4755 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004756 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004757 FIB_ROUTE_PATH_FLAG_NONE);
4758 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4759 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4760 dpo = fib_entry_contribute_ip_forwarding(fei);
4761 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4762 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4763 "2001:0:0:2/64 not resolves via drop");
4764
4765 connected_pfx.fp_len = 128;
4766 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4767 FIB_SOURCE_INTERFACE,
4768 (FIB_ENTRY_FLAG_CONNECTED |
4769 FIB_ENTRY_FLAG_LOCAL),
4770 FIB_PROTOCOL_IP6,
4771 NULL,
4772 tm->hw[0]->sw_if_index,
4773 ~0, // invalid fib index
4774 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004775 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004776 FIB_ROUTE_PATH_FLAG_NONE);
4777 fei = fib_table_lookup(fib_index, &connected_pfx);
4778
4779 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4780 dpo = fib_entry_contribute_ip_forwarding(fei);
4781 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4782 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4783 "local interface adj is local");
4784 rd = receive_dpo_get(dpo->dpoi_index);
4785 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4786 &rd->rd_addr)),
4787 "local interface adj is receive ok");
4788
4789 /*
4790 * +2 entries, +2 unshared path-lists
4791 */
4792 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4793 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004794 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004795 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004796 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004797 fib_entry_pool_size());
4798
4799
4800 /*
4801 * bring the interface back up. we expected the routes to return
4802 * to normal forwarding.
4803 */
4804 error = vnet_sw_interface_set_flags(vnet_get_main(),
4805 tm->hw[0]->sw_if_index,
4806 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4807 FIB_TEST((NULL == error), "Interface bring-up OK");
4808 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4809 ai = fib_entry_get_adj(fei);
4810 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4811 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4812 ai = fib_entry_get_adj(fei);
4813 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4814 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4815 ai = fib_entry_get_adj(fei);
4816 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4817 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4818 ai = fib_entry_get_adj(fei);
4819 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4820 local_pfx.fp_len = 64;
4821 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4822 ai = fib_entry_get_adj(fei);
4823 adj = adj_get(ai);
4824 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4825 "attached interface adj is glean");
4826
4827 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004828 * Same test as above, but this time the HW interface goes down
4829 */
4830 error = vnet_hw_interface_set_flags(vnet_get_main(),
4831 tm->hw_if_indicies[0],
4832 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4833 FIB_TEST((NULL == error), "Interface shutdown OK");
4834
4835 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4836 dpo = fib_entry_contribute_ip_forwarding(fei);
4837 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4838 "2001::b/64 resolves via drop");
4839 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4840 dpo = fib_entry_contribute_ip_forwarding(fei);
4841 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4842 "2001::a/64 resolves via drop");
4843 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4844 dpo = fib_entry_contribute_ip_forwarding(fei);
4845 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4846 "2001:0:0:1::3/128 resolves via drop");
4847 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4848 dpo = fib_entry_contribute_ip_forwarding(fei);
4849 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4850 "2001:0:0:1::2/128 resolves via drop");
4851 local_pfx.fp_len = 128;
4852 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4853 dpo = fib_entry_contribute_ip_forwarding(fei);
4854 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4855 "2001:0:0:1::1/128 not drop");
4856 local_pfx.fp_len = 64;
4857 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4858 dpo = fib_entry_contribute_ip_forwarding(fei);
4859 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4860 "2001:0:0:1/64 resolves via drop");
4861
4862 error = vnet_hw_interface_set_flags(vnet_get_main(),
4863 tm->hw_if_indicies[0],
4864 VNET_HW_INTERFACE_FLAG_LINK_UP);
4865 FIB_TEST((NULL == error), "Interface bring-up OK");
4866 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4867 ai = fib_entry_get_adj(fei);
4868 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4869 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4870 ai = fib_entry_get_adj(fei);
4871 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4872 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4873 ai = fib_entry_get_adj(fei);
4874 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4875 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4876 ai = fib_entry_get_adj(fei);
4877 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4878 local_pfx.fp_len = 64;
4879 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4880 ai = fib_entry_get_adj(fei);
4881 adj = adj_get(ai);
4882 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4883 "attached interface adj is glean");
4884
4885 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004886 * Delete the interface that the routes reolve through.
4887 * Again no routes are removed. They all point to drop.
4888 *
4889 * This is considered an error case. The control plane should
4890 * not remove interfaces through which routes resolve, but
4891 * such things can happen. ALL affected routes will drop.
4892 */
4893 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4894
4895 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4896 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4897 "2001::b/64 resolves via drop");
4898 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4899 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4900 "2001::b/64 resolves via drop");
4901 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4902 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4903 "2001:0:0:1::3/64 resolves via drop");
4904 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4905 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4906 "2001:0:0:1::2/64 resolves via drop");
4907 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4908 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4909 "2001:0:0:1::1/128 is drop");
4910 local_pfx.fp_len = 64;
4911 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4912 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4913 "2001:0:0:1/64 resolves via drop");
4914
4915 /*
4916 * no change
4917 */
4918 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4919 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004920 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004921 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004922 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004923 fib_entry_pool_size());
4924
4925 /*
4926 * Add the interface back. routes stay unresolved.
4927 */
4928 error = ethernet_register_interface(vnet_get_main(),
4929 test_interface_device_class.index,
4930 0 /* instance */,
4931 hw_address,
4932 &tm->hw_if_indicies[0],
4933 /* flag change */ 0);
4934
4935 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4936 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4937 "2001::b/64 resolves via drop");
4938 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4939 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4940 "2001::b/64 resolves via drop");
4941 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4942 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4943 "2001:0:0:1::3/64 resolves via drop");
4944 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4945 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4946 "2001:0:0:1::2/64 resolves via drop");
4947 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4948 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4949 "2001:0:0:1::1/128 is drop");
4950 local_pfx.fp_len = 64;
4951 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4952 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4953 "2001:0:0:1/64 resolves via drop");
4954
4955 /*
4956 * CLEANUP ALL the routes
4957 */
4958 fib_table_entry_delete(fib_index,
4959 &pfx_2001_c_s_64,
4960 FIB_SOURCE_API);
4961 fib_table_entry_delete(fib_index,
4962 &pfx_2001_a_s_64,
4963 FIB_SOURCE_API);
4964 fib_table_entry_delete(fib_index,
4965 &pfx_2001_b_s_64,
4966 FIB_SOURCE_API);
4967 fib_table_entry_delete(fib_index,
4968 &pfx_2001_1_3_s_128,
4969 FIB_SOURCE_ADJ);
4970 fib_table_entry_delete(fib_index,
4971 &pfx_2001_1_2_s_128,
4972 FIB_SOURCE_ADJ);
4973 local_pfx.fp_len = 64;
4974 fib_table_entry_delete(fib_index, &local_pfx,
4975 FIB_SOURCE_INTERFACE);
4976 local_pfx.fp_len = 128;
4977 fib_table_entry_special_remove(fib_index, &local_pfx,
4978 FIB_SOURCE_INTERFACE);
4979 connected_pfx.fp_len = 64;
4980 fib_table_entry_delete(fib_index, &connected_pfx,
4981 FIB_SOURCE_INTERFACE);
4982 connected_pfx.fp_len = 128;
4983 fib_table_entry_special_remove(fib_index, &connected_pfx,
4984 FIB_SOURCE_INTERFACE);
4985
4986 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4987 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4988 "2001::a/64 removed");
4989 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4990 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4991 "2001::b/64 removed");
4992 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4993 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4994 "2001:0:0:1::3/128 removed");
4995 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4996 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4997 "2001:0:0:1::3/128 removed");
4998 local_pfx.fp_len = 64;
4999 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5000 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5001 "2001:0:0:1/64 removed");
5002 local_pfx.fp_len = 128;
5003 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5004 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5005 "2001:0:0:1::1/128 removed");
5006 connected_pfx.fp_len = 64;
5007 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5008 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5009 "2001:0:0:2/64 removed");
5010 connected_pfx.fp_len = 128;
5011 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5012 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5013 "2001:0:0:2::1/128 removed");
5014
5015 /*
5016 * -8 entries. -7 path-lists (1 was shared).
5017 */
5018 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5019 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005020 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005021 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005022 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005023 fib_entry_pool_size());
5024
5025 /*
5026 * now remove the VRF
5027 */
5028 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
5029
5030 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5031 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005032 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005033 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005034 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005035 fib_entry_pool_size());
5036
5037 adj_unlock(ai_02);
5038 adj_unlock(ai_01);
5039
5040 /*
5041 * return the interfaces to up state
5042 */
5043 error = vnet_sw_interface_set_flags(vnet_get_main(),
5044 tm->hw[0]->sw_if_index,
5045 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5046 error = vnet_sw_interface_set_flags(vnet_get_main(),
5047 tm->hw[1]->sw_if_index,
5048 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5049
5050 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5051 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005052
5053 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005054}
5055
5056/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005057 * Test Attached Exports
5058 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005059static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005060fib_test_ae (void)
5061{
5062 const dpo_id_t *dpo, *dpo_drop;
5063 const u32 fib_index = 0;
5064 fib_node_index_t fei;
5065 test_main_t *tm;
5066 ip4_main_t *im;
5067
5068 tm = &test_main;
5069 im = &ip4_main;
5070
5071 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5072 adj_nbr_db_size());
5073
5074 /*
5075 * add interface routes. We'll assume this works. It's more rigorously
5076 * tested elsewhere.
5077 */
5078 fib_prefix_t local_pfx = {
5079 .fp_len = 24,
5080 .fp_proto = FIB_PROTOCOL_IP4,
5081 .fp_addr = {
5082 .ip4 = {
5083 /* 10.10.10.10 */
5084 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5085 },
5086 },
5087 };
5088
5089 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5090 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5091
5092 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5093
5094 fib_table_entry_update_one_path(fib_index, &local_pfx,
5095 FIB_SOURCE_INTERFACE,
5096 (FIB_ENTRY_FLAG_CONNECTED |
5097 FIB_ENTRY_FLAG_ATTACHED),
5098 FIB_PROTOCOL_IP4,
5099 NULL,
5100 tm->hw[0]->sw_if_index,
5101 ~0,
5102 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005103 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005104 FIB_ROUTE_PATH_FLAG_NONE);
5105 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5106 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5107 "attached interface route present");
5108
5109 local_pfx.fp_len = 32;
5110 fib_table_entry_update_one_path(fib_index, &local_pfx,
5111 FIB_SOURCE_INTERFACE,
5112 (FIB_ENTRY_FLAG_CONNECTED |
5113 FIB_ENTRY_FLAG_LOCAL),
5114 FIB_PROTOCOL_IP4,
5115 NULL,
5116 tm->hw[0]->sw_if_index,
5117 ~0, // invalid fib index
5118 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005119 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005120 FIB_ROUTE_PATH_FLAG_NONE);
5121 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5122
5123 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5124 "local interface route present");
5125
5126 /*
5127 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5128 */
5129 fib_prefix_t pfx_10_10_10_1_s_32 = {
5130 .fp_len = 32,
5131 .fp_proto = FIB_PROTOCOL_IP4,
5132 .fp_addr = {
5133 /* 10.10.10.1 */
5134 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5135 },
5136 };
5137 fib_node_index_t ai;
5138
Neale Ranns81424992017-05-18 03:03:22 -07005139 fib_table_entry_path_add(fib_index,
5140 &pfx_10_10_10_1_s_32,
5141 FIB_SOURCE_ADJ,
5142 FIB_ENTRY_FLAG_ATTACHED,
5143 FIB_PROTOCOL_IP4,
5144 &pfx_10_10_10_1_s_32.fp_addr,
5145 tm->hw[0]->sw_if_index,
5146 ~0, // invalid fib index
5147 1,
5148 NULL,
5149 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005150
5151 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5152 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5153 ai = fib_entry_get_adj(fei);
5154
5155 /*
5156 * create another FIB table into which routes will be imported
5157 */
5158 u32 import_fib_index1;
5159
5160 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
5161
5162 /*
5163 * Add an attached route in the import FIB
5164 */
5165 local_pfx.fp_len = 24;
5166 fib_table_entry_update_one_path(import_fib_index1,
5167 &local_pfx,
5168 FIB_SOURCE_API,
5169 FIB_ENTRY_FLAG_NONE,
5170 FIB_PROTOCOL_IP4,
5171 NULL,
5172 tm->hw[0]->sw_if_index,
5173 ~0, // invalid fib index
5174 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005175 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005176 FIB_ROUTE_PATH_FLAG_NONE);
5177 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5178 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5179
5180 /*
5181 * check for the presence of the adj-fibs in the import table
5182 */
5183 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5184 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5185 FIB_TEST((ai == fib_entry_get_adj(fei)),
5186 "adj-fib1 Import uses same adj as export");
5187
5188 /*
5189 * check for the presence of the local in the import table
5190 */
5191 local_pfx.fp_len = 32;
5192 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5193 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5194
5195 /*
5196 * Add another adj-fin in the export table. Expect this
5197 * to get magically exported;
5198 */
5199 fib_prefix_t pfx_10_10_10_2_s_32 = {
5200 .fp_len = 32,
5201 .fp_proto = FIB_PROTOCOL_IP4,
5202 .fp_addr = {
5203 /* 10.10.10.2 */
5204 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5205 },
5206 };
5207
Neale Ranns81424992017-05-18 03:03:22 -07005208 fib_table_entry_path_add(fib_index,
5209 &pfx_10_10_10_2_s_32,
5210 FIB_SOURCE_ADJ,
5211 FIB_ENTRY_FLAG_ATTACHED,
5212 FIB_PROTOCOL_IP4,
5213 &pfx_10_10_10_2_s_32.fp_addr,
5214 tm->hw[0]->sw_if_index,
5215 ~0, // invalid fib index
5216 1,
5217 NULL,
5218 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005219 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5220 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5221 ai = fib_entry_get_adj(fei);
5222
5223 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5224 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5225 FIB_TEST((ai == fib_entry_get_adj(fei)),
5226 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005227 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5228 "ADJ-fib2 imported flags %d",
5229 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005230
5231 /*
5232 * create a 2nd FIB table into which routes will be imported
5233 */
5234 u32 import_fib_index2;
5235
5236 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
5237
5238 /*
5239 * Add an attached route in the import FIB
5240 */
5241 local_pfx.fp_len = 24;
5242 fib_table_entry_update_one_path(import_fib_index2,
5243 &local_pfx,
5244 FIB_SOURCE_API,
5245 FIB_ENTRY_FLAG_NONE,
5246 FIB_PROTOCOL_IP4,
5247 NULL,
5248 tm->hw[0]->sw_if_index,
5249 ~0, // invalid fib index
5250 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005251 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005252 FIB_ROUTE_PATH_FLAG_NONE);
5253 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5254 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5255
5256 /*
5257 * check for the presence of all the adj-fibs and local in the import table
5258 */
5259 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5260 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5261 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5262 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5263 local_pfx.fp_len = 32;
5264 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5265 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5266
5267 /*
5268 * add a 3rd adj-fib. expect it to be exported to both tables.
5269 */
5270 fib_prefix_t pfx_10_10_10_3_s_32 = {
5271 .fp_len = 32,
5272 .fp_proto = FIB_PROTOCOL_IP4,
5273 .fp_addr = {
5274 /* 10.10.10.3 */
5275 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5276 },
5277 };
5278
Neale Ranns81424992017-05-18 03:03:22 -07005279 fib_table_entry_path_add(fib_index,
5280 &pfx_10_10_10_3_s_32,
5281 FIB_SOURCE_ADJ,
5282 FIB_ENTRY_FLAG_ATTACHED,
5283 FIB_PROTOCOL_IP4,
5284 &pfx_10_10_10_3_s_32.fp_addr,
5285 tm->hw[0]->sw_if_index,
5286 ~0, // invalid fib index
5287 1,
5288 NULL,
5289 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005290 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5291 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5292 ai = fib_entry_get_adj(fei);
5293
5294 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5295 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5296 FIB_TEST((ai == fib_entry_get_adj(fei)),
5297 "Import uses same adj as export");
5298 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5299 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5300 FIB_TEST((ai == fib_entry_get_adj(fei)),
5301 "Import uses same adj as export");
5302
5303 /*
5304 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5305 */
5306 fib_table_entry_delete(fib_index,
5307 &pfx_10_10_10_3_s_32,
5308 FIB_SOURCE_ADJ);
5309
5310 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5311 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5312
5313 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5314 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5315
5316 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5317 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5318
5319 /*
5320 * remove the attached route from the 2nd FIB. expect the imported
5321 * entires to be removed
5322 */
5323 local_pfx.fp_len = 24;
5324 fib_table_entry_delete(import_fib_index2,
5325 &local_pfx,
5326 FIB_SOURCE_API);
5327 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5328 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5329
5330 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5331 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5332 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5333 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5334 local_pfx.fp_len = 32;
5335 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5336 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5337
5338 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5339 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5340 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5341 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5342 local_pfx.fp_len = 32;
5343 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5344 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5345
5346 /*
5347 * modify the route in FIB1 so it is no longer attached. expect the imported
5348 * entires to be removed
5349 */
5350 local_pfx.fp_len = 24;
5351 fib_table_entry_update_one_path(import_fib_index1,
5352 &local_pfx,
5353 FIB_SOURCE_API,
5354 FIB_ENTRY_FLAG_NONE,
5355 FIB_PROTOCOL_IP4,
5356 &pfx_10_10_10_2_s_32.fp_addr,
5357 tm->hw[0]->sw_if_index,
5358 ~0, // invalid fib index
5359 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005360 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005361 FIB_ROUTE_PATH_FLAG_NONE);
5362 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5363 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5364 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5365 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5366 local_pfx.fp_len = 32;
5367 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5368 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5369
5370 /*
5371 * modify it back to attached. expect the adj-fibs back
5372 */
5373 local_pfx.fp_len = 24;
5374 fib_table_entry_update_one_path(import_fib_index1,
5375 &local_pfx,
5376 FIB_SOURCE_API,
5377 FIB_ENTRY_FLAG_NONE,
5378 FIB_PROTOCOL_IP4,
5379 NULL,
5380 tm->hw[0]->sw_if_index,
5381 ~0, // invalid fib index
5382 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005383 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005384 FIB_ROUTE_PATH_FLAG_NONE);
5385 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5386 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5387 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5388 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5389 local_pfx.fp_len = 32;
5390 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5391 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5392
5393 /*
5394 * add a covering attached next-hop for the interface address, so we have
5395 * a valid adj to find when we check the forwarding tables
5396 */
5397 fib_prefix_t pfx_10_0_0_0_s_8 = {
5398 .fp_len = 8,
5399 .fp_proto = FIB_PROTOCOL_IP4,
5400 .fp_addr = {
5401 /* 10.0.0.0 */
5402 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5403 },
5404 };
5405
5406 fei = fib_table_entry_update_one_path(fib_index,
5407 &pfx_10_0_0_0_s_8,
5408 FIB_SOURCE_API,
5409 FIB_ENTRY_FLAG_NONE,
5410 FIB_PROTOCOL_IP4,
5411 &pfx_10_10_10_3_s_32.fp_addr,
5412 tm->hw[0]->sw_if_index,
5413 ~0, // invalid fib index
5414 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005415 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005416 FIB_ROUTE_PATH_FLAG_NONE);
5417 dpo = fib_entry_contribute_ip_forwarding(fei);
5418
5419 /*
5420 * remove the route in the export fib. expect the adj-fibs to be removed
5421 */
5422 local_pfx.fp_len = 24;
5423 fib_table_entry_delete(fib_index,
5424 &local_pfx,
5425 FIB_SOURCE_INTERFACE);
5426
5427 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5428 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5429 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5430 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5431 local_pfx.fp_len = 32;
5432 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5433 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5434
5435 /*
5436 * the adj-fibs in the export VRF are present in the FIB table,
5437 * but not installed in forwarding, since they have no attached cover.
5438 * Consequently a lookup in the MTRIE gives the adj for the covering
5439 * route 10.0.0.0/8.
5440 */
5441 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5442 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5443
5444 index_t lbi;
5445 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5446 FIB_TEST(lbi == dpo->dpoi_index,
5447 "10.10.10.1 forwards on \n%U not \n%U",
5448 format_load_balance, lbi, 0,
5449 format_dpo_id, dpo, 0);
5450 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5451 FIB_TEST(lbi == dpo->dpoi_index,
5452 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5453 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5454 FIB_TEST(lbi == dpo->dpoi_index,
5455 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5456
5457 /*
5458 * add the export prefix back, but not as attached.
5459 * No adj-fibs in export nor import tables
5460 */
5461 local_pfx.fp_len = 24;
5462 fei = fib_table_entry_update_one_path(fib_index,
5463 &local_pfx,
5464 FIB_SOURCE_API,
5465 FIB_ENTRY_FLAG_NONE,
5466 FIB_PROTOCOL_IP4,
5467 &pfx_10_10_10_1_s_32.fp_addr,
5468 tm->hw[0]->sw_if_index,
5469 ~0, // invalid fib index
5470 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005471 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005472 FIB_ROUTE_PATH_FLAG_NONE);
5473 dpo = fib_entry_contribute_ip_forwarding(fei);
5474
5475 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5476 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5477 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5478 FIB_TEST(lbi == dpo->dpoi_index,
5479 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5480 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5481 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5482 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5483 FIB_TEST(lbi == dpo->dpoi_index,
5484 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5485
5486 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5487 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5488 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5489 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5490 local_pfx.fp_len = 32;
5491 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5492 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5493
5494 /*
5495 * modify the export prefix so it is attached. expect all covereds to return
5496 */
5497 local_pfx.fp_len = 24;
5498 fib_table_entry_update_one_path(fib_index,
5499 &local_pfx,
5500 FIB_SOURCE_API,
5501 FIB_ENTRY_FLAG_NONE,
5502 FIB_PROTOCOL_IP4,
5503 NULL,
5504 tm->hw[0]->sw_if_index,
5505 ~0, // invalid fib index
5506 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005507 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005508 FIB_ROUTE_PATH_FLAG_NONE);
5509
5510 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5511 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5512 dpo = fib_entry_contribute_ip_forwarding(fei);
5513 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5514 "Adj-fib1 is not drop in export");
5515 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5516 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5517 local_pfx.fp_len = 32;
5518 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5519 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5520 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5521 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5522 dpo = fib_entry_contribute_ip_forwarding(fei);
5523 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5524 "Adj-fib1 is not drop 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), "ADJ-fib1 imported");
5527 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5528 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5529 local_pfx.fp_len = 32;
5530 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5531 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5532
5533 /*
5534 * modify the export prefix so connected. no change.
5535 */
5536 local_pfx.fp_len = 24;
5537 fib_table_entry_update_one_path(fib_index, &local_pfx,
5538 FIB_SOURCE_INTERFACE,
5539 (FIB_ENTRY_FLAG_CONNECTED |
5540 FIB_ENTRY_FLAG_ATTACHED),
5541 FIB_PROTOCOL_IP4,
5542 NULL,
5543 tm->hw[0]->sw_if_index,
5544 ~0,
5545 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005546 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005547 FIB_ROUTE_PATH_FLAG_NONE);
5548
5549 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5550 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5551 dpo = fib_entry_contribute_ip_forwarding(fei);
5552 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5553 "Adj-fib1 is not drop in export");
5554 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5555 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5556 local_pfx.fp_len = 32;
5557 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5558 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5559 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5560 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5561 dpo = fib_entry_contribute_ip_forwarding(fei);
5562 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5563 "Adj-fib1 is not drop in export");
5564 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5565 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5566 local_pfx.fp_len = 32;
5567 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5568 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5569
5570 /*
5571 * CLEANUP
5572 */
5573 fib_table_entry_delete(fib_index,
5574 &pfx_10_0_0_0_s_8,
5575 FIB_SOURCE_API);
5576 fib_table_entry_delete(fib_index,
5577 &pfx_10_10_10_1_s_32,
5578 FIB_SOURCE_ADJ);
5579 fib_table_entry_delete(fib_index,
5580 &pfx_10_10_10_2_s_32,
5581 FIB_SOURCE_ADJ);
5582 local_pfx.fp_len = 32;
5583 fib_table_entry_delete(fib_index,
5584 &local_pfx,
5585 FIB_SOURCE_INTERFACE);
5586 local_pfx.fp_len = 24;
5587 fib_table_entry_delete(fib_index,
5588 &local_pfx,
5589 FIB_SOURCE_API);
5590 fib_table_entry_delete(fib_index,
5591 &local_pfx,
5592 FIB_SOURCE_INTERFACE);
5593 local_pfx.fp_len = 24;
5594 fib_table_entry_delete(import_fib_index1,
5595 &local_pfx,
5596 FIB_SOURCE_API);
5597
5598 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5599 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5600
5601 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5602 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005603
5604 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005605}
5606
Neale Ranns57b58602017-07-15 07:37:25 -07005607/*
5608 * Test Path Preference
5609 */
5610static int
5611fib_test_pref (void)
5612{
5613 test_main_t *tm = &test_main;
5614
5615 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5616 .fp_len = 32,
5617 .fp_proto = FIB_PROTOCOL_IP4,
5618 .fp_addr = {
5619 .ip4 = {
5620 .as_u32 = clib_host_to_net_u32(0x01010101),
5621 },
5622 },
5623 };
5624
5625 /*
5626 * 2 high, 2 medium and 2 low preference non-recursive paths
5627 */
5628 fib_route_path_t nr_path_hi_1 = {
5629 .frp_proto = FIB_PROTOCOL_IP4,
5630 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5631 .frp_fib_index = ~0,
5632 .frp_weight = 1,
5633 .frp_preference = 0,
5634 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5635 .frp_addr = {
5636 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5637 },
5638 };
5639 fib_route_path_t nr_path_hi_2 = {
5640 .frp_proto = FIB_PROTOCOL_IP4,
5641 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5642 .frp_fib_index = ~0,
5643 .frp_weight = 1,
5644 .frp_preference = 0,
5645 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5646 .frp_addr = {
5647 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5648 },
5649 };
5650 fib_route_path_t nr_path_med_1 = {
5651 .frp_proto = FIB_PROTOCOL_IP4,
5652 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5653 .frp_fib_index = ~0,
5654 .frp_weight = 1,
5655 .frp_preference = 1,
5656 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5657 .frp_addr = {
5658 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5659 },
5660 };
5661 fib_route_path_t nr_path_med_2 = {
5662 .frp_proto = FIB_PROTOCOL_IP4,
5663 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5664 .frp_fib_index = ~0,
5665 .frp_weight = 1,
5666 .frp_preference = 1,
5667 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5668 .frp_addr = {
5669 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5670 },
5671 };
5672 fib_route_path_t nr_path_low_1 = {
5673 .frp_proto = FIB_PROTOCOL_IP4,
5674 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5675 .frp_fib_index = ~0,
5676 .frp_weight = 1,
5677 .frp_preference = 2,
5678 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5679 .frp_addr = {
5680 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5681 },
5682 };
5683 fib_route_path_t nr_path_low_2 = {
5684 .frp_proto = FIB_PROTOCOL_IP4,
5685 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5686 .frp_fib_index = ~0,
5687 .frp_weight = 1,
5688 .frp_preference = 2,
5689 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5690 .frp_addr = {
5691 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5692 },
5693 };
5694 fib_route_path_t *nr_paths = NULL;
5695
5696 vec_add1(nr_paths, nr_path_hi_1);
5697 vec_add1(nr_paths, nr_path_hi_2);
5698 vec_add1(nr_paths, nr_path_med_1);
5699 vec_add1(nr_paths, nr_path_med_2);
5700 vec_add1(nr_paths, nr_path_low_1);
5701 vec_add1(nr_paths, nr_path_low_2);
5702
5703 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5704 VNET_LINK_IP4,
5705 &nr_path_hi_1.frp_addr,
5706 nr_path_hi_1.frp_sw_if_index);
5707 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5708 VNET_LINK_IP4,
5709 &nr_path_hi_2.frp_addr,
5710 nr_path_hi_2.frp_sw_if_index);
5711 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5712 VNET_LINK_IP4,
5713 &nr_path_med_1.frp_addr,
5714 nr_path_med_1.frp_sw_if_index);
5715 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5716 VNET_LINK_IP4,
5717 &nr_path_med_2.frp_addr,
5718 nr_path_med_2.frp_sw_if_index);
5719 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5720 VNET_LINK_IP4,
5721 &nr_path_low_1.frp_addr,
5722 nr_path_low_1.frp_sw_if_index);
5723 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5724 VNET_LINK_IP4,
5725 &nr_path_low_2.frp_addr,
5726 nr_path_low_2.frp_sw_if_index);
5727
5728 fib_test_lb_bucket_t ip_hi_1 = {
5729 .type = FT_LB_ADJ,
5730 .adj = {
5731 .adj = ai_hi_1,
5732 },
5733 };
5734 fib_test_lb_bucket_t ip_hi_2 = {
5735 .type = FT_LB_ADJ,
5736 .adj = {
5737 .adj = ai_hi_2,
5738 },
5739 };
5740 fib_test_lb_bucket_t ip_med_1 = {
5741 .type = FT_LB_ADJ,
5742 .adj = {
5743 .adj = ai_med_1,
5744 },
5745 };
5746 fib_test_lb_bucket_t ip_med_2 = {
5747 .type = FT_LB_ADJ,
5748 .adj = {
5749 .adj = ai_med_2,
5750 },
5751 };
5752 fib_test_lb_bucket_t ip_low_1 = {
5753 .type = FT_LB_ADJ,
5754 .adj = {
5755 .adj = ai_low_1,
5756 },
5757 };
5758 fib_test_lb_bucket_t ip_low_2 = {
5759 .type = FT_LB_ADJ,
5760 .adj = {
5761 .adj = ai_low_2,
5762 },
5763 };
5764
5765 fib_node_index_t fei;
5766
5767 fei = fib_table_entry_path_add2(0,
5768 &pfx_1_1_1_1_s_32,
5769 FIB_SOURCE_API,
5770 FIB_ENTRY_FLAG_NONE,
5771 nr_paths);
5772
5773 FIB_TEST(fib_test_validate_entry(fei,
5774 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5775 2,
5776 &ip_hi_1,
5777 &ip_hi_2),
5778 "1.1.1.1/32 via high preference paths");
5779
5780 /*
5781 * bring down the interface on which the high preference path lie
5782 */
5783 vnet_sw_interface_set_flags(vnet_get_main(),
5784 tm->hw[0]->sw_if_index,
5785 0);
5786
5787 FIB_TEST(fib_test_validate_entry(fei,
5788 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5789 2,
5790 &ip_med_1,
5791 &ip_med_2),
5792 "1.1.1.1/32 via medium preference paths");
5793
5794 /*
5795 * bring down the interface on which the medium preference path lie
5796 */
5797 vnet_sw_interface_set_flags(vnet_get_main(),
5798 tm->hw[1]->sw_if_index,
5799 0);
5800
5801 FIB_TEST(fib_test_validate_entry(fei,
5802 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5803 2,
5804 &ip_low_1,
5805 &ip_low_2),
5806 "1.1.1.1/32 via low preference paths");
5807
5808 /*
5809 * bring up the interface on which the high preference path lie
5810 */
5811 vnet_sw_interface_set_flags(vnet_get_main(),
5812 tm->hw[0]->sw_if_index,
5813 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5814
5815 FIB_TEST(fib_test_validate_entry(fei,
5816 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5817 2,
5818 &ip_hi_1,
5819 &ip_hi_2),
5820 "1.1.1.1/32 via high preference paths");
5821
5822 /*
5823 * bring up the interface on which the medium preference path lie
5824 */
5825 vnet_sw_interface_set_flags(vnet_get_main(),
5826 tm->hw[1]->sw_if_index,
5827 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5828
5829 FIB_TEST(fib_test_validate_entry(fei,
5830 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5831 2,
5832 &ip_hi_1,
5833 &ip_hi_2),
5834 "1.1.1.1/32 via high preference paths");
5835
5836 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5837 fib_entry_contribute_forwarding(fei,
5838 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5839 &ip_1_1_1_1);
5840
5841 /*
5842 * 3 recursive paths of different preference
5843 */
5844 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5845 .fp_len = 32,
5846 .fp_proto = FIB_PROTOCOL_IP4,
5847 .fp_addr = {
5848 .ip4 = {
5849 .as_u32 = clib_host_to_net_u32(0x01010102),
5850 },
5851 },
5852 };
5853 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5854 .fp_len = 32,
5855 .fp_proto = FIB_PROTOCOL_IP4,
5856 .fp_addr = {
5857 .ip4 = {
5858 .as_u32 = clib_host_to_net_u32(0x01010103),
5859 },
5860 },
5861 };
5862 fei = fib_table_entry_path_add2(0,
5863 &pfx_1_1_1_2_s_32,
5864 FIB_SOURCE_API,
5865 FIB_ENTRY_FLAG_NONE,
5866 nr_paths);
5867 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5868 fib_entry_contribute_forwarding(fei,
5869 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5870 &ip_1_1_1_2);
5871 fei = fib_table_entry_path_add2(0,
5872 &pfx_1_1_1_3_s_32,
5873 FIB_SOURCE_API,
5874 FIB_ENTRY_FLAG_NONE,
5875 nr_paths);
5876 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
5877 fib_entry_contribute_forwarding(fei,
5878 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5879 &ip_1_1_1_3);
5880
5881 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
5882 .type = FT_LB_O_LB,
5883 .lb = {
5884 .lb = ip_1_1_1_1.dpoi_index,
5885 },
5886 };
5887 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
5888 .type = FT_LB_O_LB,
5889 .lb = {
5890 .lb = ip_1_1_1_2.dpoi_index,
5891 },
5892 };
5893 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
5894 .type = FT_LB_O_LB,
5895 .lb = {
5896 .lb = ip_1_1_1_3.dpoi_index,
5897 },
5898 };
5899 fib_route_path_t r_path_hi = {
5900 .frp_proto = FIB_PROTOCOL_IP4,
5901 .frp_sw_if_index = ~0,
5902 .frp_fib_index = 0,
5903 .frp_weight = 1,
5904 .frp_preference = 0,
5905 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5906 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
5907 };
5908 fib_route_path_t r_path_med = {
5909 .frp_proto = FIB_PROTOCOL_IP4,
5910 .frp_sw_if_index = ~0,
5911 .frp_fib_index = 0,
5912 .frp_weight = 1,
5913 .frp_preference = 10,
5914 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5915 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
5916 };
5917 fib_route_path_t r_path_low = {
5918 .frp_proto = FIB_PROTOCOL_IP4,
5919 .frp_sw_if_index = ~0,
5920 .frp_fib_index = 0,
5921 .frp_weight = 1,
5922 .frp_preference = 1000,
5923 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5924 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
5925 };
5926 fib_route_path_t *r_paths = NULL;
5927
5928 vec_add1(r_paths, r_path_hi);
5929 vec_add1(r_paths, r_path_low);
5930 vec_add1(r_paths, r_path_med);
5931
5932 /*
5933 * add many recursive so we get the LB MAp created
5934 */
5935 #define N_PFXS 64
5936 fib_prefix_t pfx_r[N_PFXS];
5937 uint32_t n_pfxs;
5938 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
5939 {
5940 pfx_r[n_pfxs].fp_len = 32;
5941 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
5942 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
5943 clib_host_to_net_u32(0x02000000 + n_pfxs);
5944
5945 fei = fib_table_entry_path_add2(0,
5946 &pfx_r[n_pfxs],
5947 FIB_SOURCE_API,
5948 FIB_ENTRY_FLAG_NONE,
5949 r_paths);
5950
5951 FIB_TEST(fib_test_validate_entry(fei,
5952 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5953 1,
5954 &ip_o_1_1_1_1),
5955 "recursive via high preference paths");
5956
5957 /*
5958 * withdraw hig pref resolving entry
5959 */
5960 fib_table_entry_delete(0,
5961 &pfx_1_1_1_1_s_32,
5962 FIB_SOURCE_API);
5963
5964 /* suspend so the update walk kicks int */
5965 vlib_process_suspend(vlib_get_main(), 1e-5);
5966
5967 FIB_TEST(fib_test_validate_entry(fei,
5968 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5969 1,
5970 &ip_o_1_1_1_2),
5971 "recursive via medium preference paths");
5972
5973 /*
5974 * withdraw medium pref resolving entry
5975 */
5976 fib_table_entry_delete(0,
5977 &pfx_1_1_1_2_s_32,
5978 FIB_SOURCE_API);
5979
5980 /* suspend so the update walk kicks int */
5981 vlib_process_suspend(vlib_get_main(), 1e-5);
5982
5983 FIB_TEST(fib_test_validate_entry(fei,
5984 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5985 1,
5986 &ip_o_1_1_1_3),
5987 "recursive via low preference paths");
5988
5989 /*
5990 * add back paths for next iteration
5991 */
5992 fei = fib_table_entry_update(0,
5993 &pfx_1_1_1_2_s_32,
5994 FIB_SOURCE_API,
5995 FIB_ENTRY_FLAG_NONE,
5996 nr_paths);
5997 fei = fib_table_entry_update(0,
5998 &pfx_1_1_1_1_s_32,
5999 FIB_SOURCE_API,
6000 FIB_ENTRY_FLAG_NONE,
6001 nr_paths);
6002
6003 /* suspend so the update walk kicks int */
6004 vlib_process_suspend(vlib_get_main(), 1e-5);
6005
6006 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6007 FIB_TEST(fib_test_validate_entry(fei,
6008 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6009 1,
6010 &ip_o_1_1_1_1),
6011 "recursive via high preference paths");
6012 }
6013
6014
6015 fib_table_entry_delete(0,
6016 &pfx_1_1_1_1_s_32,
6017 FIB_SOURCE_API);
6018
6019 /* suspend so the update walk kicks int */
6020 vlib_process_suspend(vlib_get_main(), 1e-5);
6021
6022 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6023 {
6024 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6025
6026 FIB_TEST(fib_test_validate_entry(fei,
6027 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6028 1,
6029 &ip_o_1_1_1_2),
6030 "recursive via medium preference paths");
6031 }
6032 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6033 {
6034 fib_table_entry_delete(0,
6035 &pfx_r[n_pfxs],
6036 FIB_SOURCE_API);
6037 }
6038
6039 /*
6040 * Cleanup
6041 */
6042 fib_table_entry_delete(0,
6043 &pfx_1_1_1_2_s_32,
6044 FIB_SOURCE_API);
6045 fib_table_entry_delete(0,
6046 &pfx_1_1_1_3_s_32,
6047 FIB_SOURCE_API);
6048
6049 dpo_reset(&ip_1_1_1_1);
6050 dpo_reset(&ip_1_1_1_2);
6051 dpo_reset(&ip_1_1_1_3);
6052 adj_unlock(ai_low_2);
6053 adj_unlock(ai_low_1);
6054 adj_unlock(ai_med_2);
6055 adj_unlock(ai_med_1);
6056 adj_unlock(ai_hi_2);
6057 adj_unlock(ai_hi_1);
6058 return (0);
6059}
Neale Rannsad422ed2016-11-02 14:20:04 +00006060
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006061/*
6062 * Test the recursive route route handling for GRE tunnels
6063 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006064static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006065fib_test_label (void)
6066{
6067 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;
6068 const u32 fib_index = 0;
6069 test_main_t *tm;
6070 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00006071 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006072
6073 lb_count = pool_elts(load_balance_pool);
6074 tm = &test_main;
6075 im = &ip4_main;
6076
6077 /*
6078 * add interface routes. We'll assume this works. It's more rigorously
6079 * tested elsewhere.
6080 */
6081 fib_prefix_t local0_pfx = {
6082 .fp_len = 24,
6083 .fp_proto = FIB_PROTOCOL_IP4,
6084 .fp_addr = {
6085 .ip4 = {
6086 /* 10.10.10.10 */
6087 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6088 },
6089 },
6090 };
6091
6092 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6093 adj_nbr_db_size());
6094
6095 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6096 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6097
6098 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6099 FIB_SOURCE_INTERFACE,
6100 (FIB_ENTRY_FLAG_CONNECTED |
6101 FIB_ENTRY_FLAG_ATTACHED),
6102 FIB_PROTOCOL_IP4,
6103 NULL,
6104 tm->hw[0]->sw_if_index,
6105 ~0,
6106 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006107 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006108 FIB_ROUTE_PATH_FLAG_NONE);
6109 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6110 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6111 "attached interface route present");
6112
6113 local0_pfx.fp_len = 32;
6114 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6115 FIB_SOURCE_INTERFACE,
6116 (FIB_ENTRY_FLAG_CONNECTED |
6117 FIB_ENTRY_FLAG_LOCAL),
6118 FIB_PROTOCOL_IP4,
6119 NULL,
6120 tm->hw[0]->sw_if_index,
6121 ~0, // invalid fib index
6122 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006123 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006124 FIB_ROUTE_PATH_FLAG_NONE);
6125 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6126
6127 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6128 "local interface route present");
6129
6130 fib_prefix_t local1_pfx = {
6131 .fp_len = 24,
6132 .fp_proto = FIB_PROTOCOL_IP4,
6133 .fp_addr = {
6134 .ip4 = {
6135 /* 10.10.11.10 */
6136 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6137 },
6138 },
6139 };
6140
6141 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6142 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6143
6144 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6145 FIB_SOURCE_INTERFACE,
6146 (FIB_ENTRY_FLAG_CONNECTED |
6147 FIB_ENTRY_FLAG_ATTACHED),
6148 FIB_PROTOCOL_IP4,
6149 NULL,
6150 tm->hw[1]->sw_if_index,
6151 ~0,
6152 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006153 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006154 FIB_ROUTE_PATH_FLAG_NONE);
6155 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6156 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6157 "attached interface route present");
6158
6159 local1_pfx.fp_len = 32;
6160 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6161 FIB_SOURCE_INTERFACE,
6162 (FIB_ENTRY_FLAG_CONNECTED |
6163 FIB_ENTRY_FLAG_LOCAL),
6164 FIB_PROTOCOL_IP4,
6165 NULL,
6166 tm->hw[1]->sw_if_index,
6167 ~0, // invalid fib index
6168 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006169 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006170 FIB_ROUTE_PATH_FLAG_NONE);
6171 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6172
6173 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6174 "local interface route present");
6175
6176 ip46_address_t nh_10_10_10_1 = {
6177 .ip4 = {
6178 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6179 },
6180 };
6181 ip46_address_t nh_10_10_11_1 = {
6182 .ip4 = {
6183 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6184 },
6185 };
6186 ip46_address_t nh_10_10_11_2 = {
6187 .ip4 = {
6188 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6189 },
6190 };
6191
6192 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006193 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006194 &nh_10_10_11_1,
6195 tm->hw[1]->sw_if_index);
6196 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006197 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006198 &nh_10_10_11_2,
6199 tm->hw[1]->sw_if_index);
6200 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006201 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006202 &nh_10_10_10_1,
6203 tm->hw[0]->sw_if_index);
6204 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006205 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006206 &nh_10_10_11_2,
6207 tm->hw[1]->sw_if_index);
6208 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006209 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006210 &nh_10_10_11_1,
6211 tm->hw[1]->sw_if_index);
6212
6213 /*
6214 * Add an etry with one path with a real out-going label
6215 */
6216 fib_prefix_t pfx_1_1_1_1_s_32 = {
6217 .fp_len = 32,
6218 .fp_proto = FIB_PROTOCOL_IP4,
6219 .fp_addr = {
6220 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6221 },
6222 };
6223 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6224 .type = FT_LB_LABEL_O_ADJ,
6225 .label_o_adj = {
6226 .adj = ai_mpls_10_10_10_1,
6227 .label = 99,
6228 .eos = MPLS_EOS,
6229 },
6230 };
6231 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6232 .type = FT_LB_LABEL_O_ADJ,
6233 .label_o_adj = {
6234 .adj = ai_mpls_10_10_10_1,
6235 .label = 99,
6236 .eos = MPLS_NON_EOS,
6237 },
6238 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006239 mpls_label_t *l99 = NULL;
6240 vec_add1(l99, 99);
6241
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006242 fib_table_entry_update_one_path(fib_index,
6243 &pfx_1_1_1_1_s_32,
6244 FIB_SOURCE_API,
6245 FIB_ENTRY_FLAG_NONE,
6246 FIB_PROTOCOL_IP4,
6247 &nh_10_10_10_1,
6248 tm->hw[0]->sw_if_index,
6249 ~0, // invalid fib index
6250 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006251 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006252 FIB_ROUTE_PATH_FLAG_NONE);
6253
6254 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6255 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6256
6257 FIB_TEST(fib_test_validate_entry(fei,
6258 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6259 1,
6260 &l99_eos_o_10_10_10_1),
6261 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6262
6263 /*
6264 * add a path with an implicit NULL label
6265 */
6266 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6267 .type = FT_LB_ADJ,
6268 .adj = {
6269 .adj = ai_v4_10_10_11_1,
6270 },
6271 };
6272 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6273 .type = FT_LB_ADJ,
6274 .adj = {
6275 .adj = ai_mpls_10_10_11_1,
6276 },
6277 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006278 mpls_label_t *l_imp_null = NULL;
6279 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006280
6281 fei = fib_table_entry_path_add(fib_index,
6282 &pfx_1_1_1_1_s_32,
6283 FIB_SOURCE_API,
6284 FIB_ENTRY_FLAG_NONE,
6285 FIB_PROTOCOL_IP4,
6286 &nh_10_10_11_1,
6287 tm->hw[1]->sw_if_index,
6288 ~0, // invalid fib index
6289 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006290 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006291 FIB_ROUTE_PATH_FLAG_NONE);
6292
6293 FIB_TEST(fib_test_validate_entry(fei,
6294 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6295 2,
6296 &l99_eos_o_10_10_10_1,
6297 &a_o_10_10_11_1),
6298 "1.1.1.1/32 LB 2 buckets via: "
6299 "label 99 over 10.10.10.1, "
6300 "adj over 10.10.11.1");
6301
6302 /*
6303 * assign the route a local label
6304 */
6305 fib_table_entry_local_label_add(fib_index,
6306 &pfx_1_1_1_1_s_32,
6307 24001);
6308
6309 fib_prefix_t pfx_24001_eos = {
6310 .fp_proto = FIB_PROTOCOL_MPLS,
6311 .fp_label = 24001,
6312 .fp_eos = MPLS_EOS,
6313 };
6314 fib_prefix_t pfx_24001_neos = {
6315 .fp_proto = FIB_PROTOCOL_MPLS,
6316 .fp_label = 24001,
6317 .fp_eos = MPLS_NON_EOS,
6318 };
6319
6320 /*
6321 * The EOS entry should link to both the paths,
6322 * and use an ip adj for the imp-null
6323 * The NON-EOS entry should link to both the paths,
6324 * and use an mpls adj for the imp-null
6325 */
6326 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6327 &pfx_24001_eos);
6328 FIB_TEST(fib_test_validate_entry(fei,
6329 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6330 2,
6331 &l99_eos_o_10_10_10_1,
6332 &a_o_10_10_11_1),
6333 "24001/eos LB 2 buckets via: "
6334 "label 99 over 10.10.10.1, "
6335 "adj over 10.10.11.1");
6336
6337
6338 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6339 &pfx_24001_neos);
6340 FIB_TEST(fib_test_validate_entry(fei,
6341 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6342 2,
6343 &l99_neos_o_10_10_10_1,
6344 &a_mpls_o_10_10_11_1),
6345 "24001/neos LB 1 bucket via: "
6346 "label 99 over 10.10.10.1 ",
6347 "mpls-adj via 10.10.11.1");
6348
6349 /*
6350 * add an unlabelled path, this is excluded from the neos chains,
6351 */
6352 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6353 .type = FT_LB_ADJ,
6354 .adj = {
6355 .adj = ai_v4_10_10_11_2,
6356 },
6357 };
6358
6359 fei = fib_table_entry_path_add(fib_index,
6360 &pfx_1_1_1_1_s_32,
6361 FIB_SOURCE_API,
6362 FIB_ENTRY_FLAG_NONE,
6363 FIB_PROTOCOL_IP4,
6364 &nh_10_10_11_2,
6365 tm->hw[1]->sw_if_index,
6366 ~0, // invalid fib index
6367 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006368 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006369 FIB_ROUTE_PATH_FLAG_NONE);
6370
6371 FIB_TEST(fib_test_validate_entry(fei,
6372 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6373 16, // 3 choices spread over 16 buckets
6374 &l99_eos_o_10_10_10_1,
6375 &l99_eos_o_10_10_10_1,
6376 &l99_eos_o_10_10_10_1,
6377 &l99_eos_o_10_10_10_1,
6378 &l99_eos_o_10_10_10_1,
6379 &l99_eos_o_10_10_10_1,
6380 &a_o_10_10_11_1,
6381 &a_o_10_10_11_1,
6382 &a_o_10_10_11_1,
6383 &a_o_10_10_11_1,
6384 &a_o_10_10_11_1,
6385 &adj_o_10_10_11_2,
6386 &adj_o_10_10_11_2,
6387 &adj_o_10_10_11_2,
6388 &adj_o_10_10_11_2,
6389 &adj_o_10_10_11_2),
6390 "1.1.1.1/32 LB 16 buckets via: "
6391 "label 99 over 10.10.10.1, "
6392 "adj over 10.10.11.1",
6393 "adj over 10.10.11.2");
6394
6395 /*
6396 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6397 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006398 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006399 fib_entry_contribute_forwarding(fei,
6400 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6401 &non_eos_1_1_1_1);
6402
6403 /*
6404 * n-eos has only the 2 labelled paths
6405 */
6406 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6407 &pfx_24001_neos);
6408
6409 FIB_TEST(fib_test_validate_entry(fei,
6410 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6411 2,
6412 &l99_neos_o_10_10_10_1,
6413 &a_mpls_o_10_10_11_1),
6414 "24001/neos LB 2 buckets via: "
6415 "label 99 over 10.10.10.1, "
6416 "adj-mpls over 10.10.11.2");
6417
6418 /*
6419 * A labelled recursive
6420 */
6421 fib_prefix_t pfx_2_2_2_2_s_32 = {
6422 .fp_len = 32,
6423 .fp_proto = FIB_PROTOCOL_IP4,
6424 .fp_addr = {
6425 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6426 },
6427 };
6428 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6429 .type = FT_LB_LABEL_O_LB,
6430 .label_o_lb = {
6431 .lb = non_eos_1_1_1_1.dpoi_index,
6432 .label = 1600,
6433 .eos = MPLS_EOS,
6434 },
6435 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006436 mpls_label_t *l1600 = NULL;
6437 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006438
6439 fib_table_entry_update_one_path(fib_index,
6440 &pfx_2_2_2_2_s_32,
6441 FIB_SOURCE_API,
6442 FIB_ENTRY_FLAG_NONE,
6443 FIB_PROTOCOL_IP4,
6444 &pfx_1_1_1_1_s_32.fp_addr,
6445 ~0,
6446 fib_index,
6447 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006448 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006449 FIB_ROUTE_PATH_FLAG_NONE);
6450
6451 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6452 FIB_TEST(fib_test_validate_entry(fei,
6453 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6454 1,
6455 &l1600_eos_o_1_1_1_1),
6456 "2.2.2.2.2/32 LB 1 buckets via: "
6457 "label 1600 over 1.1.1.1");
6458
Neale Ranns948e00f2016-10-20 13:39:34 +01006459 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01006460 index_t urpfi;
6461
6462 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6463 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6464
6465 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6466 "uRPF check for 2.2.2.2/32 on %d OK",
6467 tm->hw[0]->sw_if_index);
6468 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6469 "uRPF check for 2.2.2.2/32 on %d OK",
6470 tm->hw[1]->sw_if_index);
6471 FIB_TEST(!fib_urpf_check(urpfi, 99),
6472 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6473 99);
6474
6475 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6476 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6477 "Shared uRPF on IP and non-EOS chain");
6478
6479 dpo_reset(&dpo_44);
6480
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006481 /*
6482 * we are holding a lock on the non-eos LB of the via-entry.
6483 * do a PIC-core failover by shutting the link of the via-entry.
6484 *
6485 * shut down the link with the valid label
6486 */
6487 vnet_sw_interface_set_flags(vnet_get_main(),
6488 tm->hw[0]->sw_if_index,
6489 0);
6490
6491 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6492 FIB_TEST(fib_test_validate_entry(fei,
6493 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6494 2,
6495 &a_o_10_10_11_1,
6496 &adj_o_10_10_11_2),
6497 "1.1.1.1/32 LB 2 buckets via: "
6498 "adj over 10.10.11.1, ",
6499 "adj-v4 over 10.10.11.2");
6500
6501 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6502 &pfx_24001_eos);
6503 FIB_TEST(fib_test_validate_entry(fei,
6504 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6505 2,
6506 &a_o_10_10_11_1,
6507 &adj_o_10_10_11_2),
6508 "24001/eos LB 2 buckets via: "
6509 "adj over 10.10.11.1, ",
6510 "adj-v4 over 10.10.11.2");
6511
6512 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6513 &pfx_24001_neos);
6514 FIB_TEST(fib_test_validate_entry(fei,
6515 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6516 1,
6517 &a_mpls_o_10_10_11_1),
6518 "24001/neos LB 1 buckets via: "
6519 "adj-mpls over 10.10.11.2");
6520
6521 /*
6522 * test that the pre-failover load-balance has been in-place
6523 * modified
6524 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006525 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006526 fib_entry_contribute_forwarding(fei,
6527 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6528 &current);
6529
6530 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6531 &current),
6532 "PIC-core LB inplace modified %U %U",
6533 format_dpo_id, &non_eos_1_1_1_1, 0,
6534 format_dpo_id, &current, 0);
6535
6536 dpo_reset(&non_eos_1_1_1_1);
6537 dpo_reset(&current);
6538
6539 /*
6540 * no-shut the link with the valid label
6541 */
6542 vnet_sw_interface_set_flags(vnet_get_main(),
6543 tm->hw[0]->sw_if_index,
6544 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6545
6546 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6547 FIB_TEST(fib_test_validate_entry(fei,
6548 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6549 16, // 3 choices spread over 16 buckets
6550 &l99_eos_o_10_10_10_1,
6551 &l99_eos_o_10_10_10_1,
6552 &l99_eos_o_10_10_10_1,
6553 &l99_eos_o_10_10_10_1,
6554 &l99_eos_o_10_10_10_1,
6555 &l99_eos_o_10_10_10_1,
6556 &a_o_10_10_11_1,
6557 &a_o_10_10_11_1,
6558 &a_o_10_10_11_1,
6559 &a_o_10_10_11_1,
6560 &a_o_10_10_11_1,
6561 &adj_o_10_10_11_2,
6562 &adj_o_10_10_11_2,
6563 &adj_o_10_10_11_2,
6564 &adj_o_10_10_11_2,
6565 &adj_o_10_10_11_2),
6566 "1.1.1.1/32 LB 16 buckets via: "
6567 "label 99 over 10.10.10.1, "
6568 "adj over 10.10.11.1",
6569 "adj-v4 over 10.10.11.2");
6570
6571
6572 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6573 &pfx_24001_eos);
6574 FIB_TEST(fib_test_validate_entry(fei,
6575 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6576 16, // 3 choices spread over 16 buckets
6577 &l99_eos_o_10_10_10_1,
6578 &l99_eos_o_10_10_10_1,
6579 &l99_eos_o_10_10_10_1,
6580 &l99_eos_o_10_10_10_1,
6581 &l99_eos_o_10_10_10_1,
6582 &l99_eos_o_10_10_10_1,
6583 &a_o_10_10_11_1,
6584 &a_o_10_10_11_1,
6585 &a_o_10_10_11_1,
6586 &a_o_10_10_11_1,
6587 &a_o_10_10_11_1,
6588 &adj_o_10_10_11_2,
6589 &adj_o_10_10_11_2,
6590 &adj_o_10_10_11_2,
6591 &adj_o_10_10_11_2,
6592 &adj_o_10_10_11_2),
6593 "24001/eos LB 16 buckets via: "
6594 "label 99 over 10.10.10.1, "
6595 "adj over 10.10.11.1",
6596 "adj-v4 over 10.10.11.2");
6597
6598 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6599 &pfx_24001_neos);
6600 FIB_TEST(fib_test_validate_entry(fei,
6601 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6602 2,
6603 &l99_neos_o_10_10_10_1,
6604 &a_mpls_o_10_10_11_1),
6605 "24001/neos LB 2 buckets via: "
6606 "label 99 over 10.10.10.1, "
6607 "adj-mpls over 10.10.11.2");
6608
6609 /*
6610 * remove the first path with the valid label
6611 */
6612 fib_table_entry_path_remove(fib_index,
6613 &pfx_1_1_1_1_s_32,
6614 FIB_SOURCE_API,
6615 FIB_PROTOCOL_IP4,
6616 &nh_10_10_10_1,
6617 tm->hw[0]->sw_if_index,
6618 ~0, // invalid fib index
6619 1,
6620 FIB_ROUTE_PATH_FLAG_NONE);
6621
6622 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6623 FIB_TEST(fib_test_validate_entry(fei,
6624 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6625 2,
6626 &a_o_10_10_11_1,
6627 &adj_o_10_10_11_2),
6628 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006629 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006630 "adj-v4 over 10.10.11.2");
6631
6632 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6633 &pfx_24001_eos);
6634 FIB_TEST(fib_test_validate_entry(fei,
6635 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6636 2,
6637 &a_o_10_10_11_1,
6638 &adj_o_10_10_11_2),
6639 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006640 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006641 "adj-v4 over 10.10.11.2");
6642
6643 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6644 &pfx_24001_neos);
6645
6646 FIB_TEST(fib_test_validate_entry(fei,
6647 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6648 1,
6649 &a_mpls_o_10_10_11_1),
6650 "24001/neos LB 1 buckets via: "
6651 "adj-mpls over 10.10.11.2");
6652
6653 /*
6654 * remove the other path with a valid label
6655 */
6656 fib_test_lb_bucket_t bucket_drop = {
6657 .type = FT_LB_SPECIAL,
6658 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00006659 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006660 },
6661 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006662 fib_test_lb_bucket_t mpls_bucket_drop = {
6663 .type = FT_LB_SPECIAL,
6664 .special = {
6665 .adj = DPO_PROTO_MPLS,
6666 },
6667 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006668
6669 fib_table_entry_path_remove(fib_index,
6670 &pfx_1_1_1_1_s_32,
6671 FIB_SOURCE_API,
6672 FIB_PROTOCOL_IP4,
6673 &nh_10_10_11_1,
6674 tm->hw[1]->sw_if_index,
6675 ~0, // invalid fib index
6676 1,
6677 FIB_ROUTE_PATH_FLAG_NONE);
6678
6679 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6680 FIB_TEST(fib_test_validate_entry(fei,
6681 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6682 1,
6683 &adj_o_10_10_11_2),
6684 "1.1.1.1/32 LB 1 buckets via: "
6685 "adj over 10.10.11.2");
6686
6687 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6688 &pfx_24001_eos);
6689 FIB_TEST(fib_test_validate_entry(fei,
6690 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6691 1,
6692 &adj_o_10_10_11_2),
6693 "24001/eos LB 1 buckets via: "
6694 "adj over 10.10.11.2");
6695
6696 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6697 &pfx_24001_neos);
6698 FIB_TEST(fib_test_validate_entry(fei,
6699 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006700 1,
6701 &mpls_bucket_drop),
6702 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006703
6704 /*
6705 * add back the path with the valid label
6706 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006707 l99 = NULL;
6708 vec_add1(l99, 99);
6709
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006710 fib_table_entry_path_add(fib_index,
6711 &pfx_1_1_1_1_s_32,
6712 FIB_SOURCE_API,
6713 FIB_ENTRY_FLAG_NONE,
6714 FIB_PROTOCOL_IP4,
6715 &nh_10_10_10_1,
6716 tm->hw[0]->sw_if_index,
6717 ~0, // invalid fib index
6718 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006719 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006720 FIB_ROUTE_PATH_FLAG_NONE);
6721
6722 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6723 FIB_TEST(fib_test_validate_entry(fei,
6724 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6725 2,
6726 &l99_eos_o_10_10_10_1,
6727 &adj_o_10_10_11_2),
6728 "1.1.1.1/32 LB 2 buckets via: "
6729 "label 99 over 10.10.10.1, "
6730 "adj over 10.10.11.2");
6731
6732 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6733 &pfx_24001_eos);
6734 FIB_TEST(fib_test_validate_entry(fei,
6735 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6736 2,
6737 &l99_eos_o_10_10_10_1,
6738 &adj_o_10_10_11_2),
6739 "24001/eos LB 2 buckets via: "
6740 "label 99 over 10.10.10.1, "
6741 "adj over 10.10.11.2");
6742
6743 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6744 &pfx_24001_neos);
6745 FIB_TEST(fib_test_validate_entry(fei,
6746 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6747 1,
6748 &l99_neos_o_10_10_10_1),
6749 "24001/neos LB 1 buckets via: "
6750 "label 99 over 10.10.10.1");
6751
6752 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006753 * change the local label
6754 */
6755 fib_table_entry_local_label_add(fib_index,
6756 &pfx_1_1_1_1_s_32,
6757 25005);
6758
6759 fib_prefix_t pfx_25005_eos = {
6760 .fp_proto = FIB_PROTOCOL_MPLS,
6761 .fp_label = 25005,
6762 .fp_eos = MPLS_EOS,
6763 };
6764 fib_prefix_t pfx_25005_neos = {
6765 .fp_proto = FIB_PROTOCOL_MPLS,
6766 .fp_label = 25005,
6767 .fp_eos = MPLS_NON_EOS,
6768 };
6769
6770 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6771 fib_table_lookup(fib_index, &pfx_24001_eos)),
6772 "24001/eos removed after label change");
6773 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6774 fib_table_lookup(fib_index, &pfx_24001_neos)),
6775 "24001/eos removed after label change");
6776
6777 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6778 &pfx_25005_eos);
6779 FIB_TEST(fib_test_validate_entry(fei,
6780 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6781 2,
6782 &l99_eos_o_10_10_10_1,
6783 &adj_o_10_10_11_2),
6784 "25005/eos LB 2 buckets via: "
6785 "label 99 over 10.10.10.1, "
6786 "adj over 10.10.11.2");
6787
6788 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6789 &pfx_25005_neos);
6790 FIB_TEST(fib_test_validate_entry(fei,
6791 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6792 1,
6793 &l99_neos_o_10_10_10_1),
6794 "25005/neos LB 1 buckets via: "
6795 "label 99 over 10.10.10.1");
6796
6797 /*
6798 * remove the local label.
6799 * the check that the MPLS entries are gone is done by the fact the
6800 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006801 */
6802 fib_table_entry_local_label_remove(fib_index,
6803 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006804 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006805
6806 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6807 FIB_TEST(fib_test_validate_entry(fei,
6808 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6809 2,
6810 &l99_eos_o_10_10_10_1,
6811 &adj_o_10_10_11_2),
6812 "24001/eos LB 2 buckets via: "
6813 "label 99 over 10.10.10.1, "
6814 "adj over 10.10.11.2");
6815
6816 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6817 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6818 "No more MPLS FIB entries => table removed");
6819
6820 /*
6821 * add another via-entry for the recursive
6822 */
6823 fib_prefix_t pfx_1_1_1_2_s_32 = {
6824 .fp_len = 32,
6825 .fp_proto = FIB_PROTOCOL_IP4,
6826 .fp_addr = {
6827 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6828 },
6829 };
6830 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6831 .type = FT_LB_LABEL_O_ADJ,
6832 .label_o_adj = {
6833 .adj = ai_mpls_10_10_10_1,
6834 .label = 101,
6835 .eos = MPLS_EOS,
6836 },
6837 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006838 mpls_label_t *l101 = NULL;
6839 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006840
6841 fei = fib_table_entry_update_one_path(fib_index,
6842 &pfx_1_1_1_2_s_32,
6843 FIB_SOURCE_API,
6844 FIB_ENTRY_FLAG_NONE,
6845 FIB_PROTOCOL_IP4,
6846 &nh_10_10_10_1,
6847 tm->hw[0]->sw_if_index,
6848 ~0, // invalid fib index
6849 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006850 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006851 FIB_ROUTE_PATH_FLAG_NONE);
6852
6853 FIB_TEST(fib_test_validate_entry(fei,
6854 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6855 1,
6856 &l101_eos_o_10_10_10_1),
6857 "1.1.1.2/32 LB 1 buckets via: "
6858 "label 101 over 10.10.10.1");
6859
Neale Ranns948e00f2016-10-20 13:39:34 +01006860 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006861 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6862 &pfx_1_1_1_1_s_32),
6863 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6864 &non_eos_1_1_1_1);
6865 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6866 &pfx_1_1_1_2_s_32),
6867 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6868 &non_eos_1_1_1_2);
6869
6870 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6871 .type = FT_LB_LABEL_O_LB,
6872 .label_o_lb = {
6873 .lb = non_eos_1_1_1_2.dpoi_index,
6874 .label = 1601,
6875 .eos = MPLS_EOS,
6876 },
6877 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006878 mpls_label_t *l1601 = NULL;
6879 vec_add1(l1601, 1601);
6880
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006881 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6882
6883 fei = fib_table_entry_path_add(fib_index,
6884 &pfx_2_2_2_2_s_32,
6885 FIB_SOURCE_API,
6886 FIB_ENTRY_FLAG_NONE,
6887 FIB_PROTOCOL_IP4,
6888 &pfx_1_1_1_2_s_32.fp_addr,
6889 ~0,
6890 fib_index,
6891 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006892 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006893 FIB_ROUTE_PATH_FLAG_NONE);
6894
6895 FIB_TEST(fib_test_validate_entry(fei,
6896 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6897 2,
6898 &l1600_eos_o_1_1_1_1,
6899 &l1601_eos_o_1_1_1_2),
6900 "2.2.2.2/32 LB 2 buckets via: "
6901 "label 1600 via 1.1,1.1, "
6902 "label 16001 via 1.1.1.2");
6903
6904 /*
6905 * update the via-entry so it no longer has an imp-null path.
6906 * the LB for the recursive can use an imp-null
6907 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006908 l_imp_null = NULL;
6909 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6910
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006911 fei = fib_table_entry_update_one_path(fib_index,
6912 &pfx_1_1_1_2_s_32,
6913 FIB_SOURCE_API,
6914 FIB_ENTRY_FLAG_NONE,
6915 FIB_PROTOCOL_IP4,
6916 &nh_10_10_11_1,
6917 tm->hw[1]->sw_if_index,
6918 ~0, // invalid fib index
6919 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006920 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006921 FIB_ROUTE_PATH_FLAG_NONE);
6922
6923 FIB_TEST(fib_test_validate_entry(fei,
6924 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6925 1,
6926 &a_o_10_10_11_1),
6927 "1.1.1.2/32 LB 1 buckets via: "
6928 "adj 10.10.11.1");
6929
6930 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6931 FIB_TEST(fib_test_validate_entry(fei,
6932 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6933 2,
6934 &l1600_eos_o_1_1_1_1,
6935 &l1601_eos_o_1_1_1_2),
6936 "2.2.2.2/32 LB 2 buckets via: "
6937 "label 1600 via 1.1,1.1, "
6938 "label 16001 via 1.1.1.2");
6939
6940 /*
6941 * update the via-entry so it no longer has labelled paths.
6942 * the LB for the recursive should exclue this via form its LB
6943 */
6944 fei = fib_table_entry_update_one_path(fib_index,
6945 &pfx_1_1_1_2_s_32,
6946 FIB_SOURCE_API,
6947 FIB_ENTRY_FLAG_NONE,
6948 FIB_PROTOCOL_IP4,
6949 &nh_10_10_11_1,
6950 tm->hw[1]->sw_if_index,
6951 ~0, // invalid fib index
6952 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006953 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006954 FIB_ROUTE_PATH_FLAG_NONE);
6955
6956 FIB_TEST(fib_test_validate_entry(fei,
6957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6958 1,
6959 &a_o_10_10_11_1),
6960 "1.1.1.2/32 LB 1 buckets via: "
6961 "adj 10.10.11.1");
6962
6963 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6964 FIB_TEST(fib_test_validate_entry(fei,
6965 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6966 1,
6967 &l1600_eos_o_1_1_1_1),
6968 "2.2.2.2/32 LB 1 buckets via: "
6969 "label 1600 via 1.1,1.1");
6970
6971 dpo_reset(&non_eos_1_1_1_1);
6972 dpo_reset(&non_eos_1_1_1_2);
6973
6974 /*
6975 * Add a recursive with no out-labels. We expect to use the IP of the via
6976 */
6977 fib_prefix_t pfx_2_2_2_3_s_32 = {
6978 .fp_len = 32,
6979 .fp_proto = FIB_PROTOCOL_IP4,
6980 .fp_addr = {
6981 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6982 },
6983 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006984 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006985
6986 fib_table_entry_update_one_path(fib_index,
6987 &pfx_2_2_2_3_s_32,
6988 FIB_SOURCE_API,
6989 FIB_ENTRY_FLAG_NONE,
6990 FIB_PROTOCOL_IP4,
6991 &pfx_1_1_1_1_s_32.fp_addr,
6992 ~0,
6993 fib_index,
6994 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006995 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006996 FIB_ROUTE_PATH_FLAG_NONE);
6997
6998 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6999 &pfx_1_1_1_1_s_32),
7000 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7001 &ip_1_1_1_1);
7002
7003 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7004 .type = FT_LB_O_LB,
7005 .lb = {
7006 .lb = ip_1_1_1_1.dpoi_index,
7007 },
7008 };
7009
7010 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7011 FIB_TEST(fib_test_validate_entry(fei,
7012 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7013 1,
7014 &ip_o_1_1_1_1),
7015 "2.2.2.2.3/32 LB 1 buckets via: "
7016 "ip 1.1.1.1");
7017
7018 /*
7019 * Add a recursive with an imp-null out-label.
7020 * We expect to use the IP of the via
7021 */
7022 fib_prefix_t pfx_2_2_2_4_s_32 = {
7023 .fp_len = 32,
7024 .fp_proto = FIB_PROTOCOL_IP4,
7025 .fp_addr = {
7026 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7027 },
7028 };
7029
7030 fib_table_entry_update_one_path(fib_index,
7031 &pfx_2_2_2_4_s_32,
7032 FIB_SOURCE_API,
7033 FIB_ENTRY_FLAG_NONE,
7034 FIB_PROTOCOL_IP4,
7035 &pfx_1_1_1_1_s_32.fp_addr,
7036 ~0,
7037 fib_index,
7038 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007039 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007040 FIB_ROUTE_PATH_FLAG_NONE);
7041
7042 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7043 FIB_TEST(fib_test_validate_entry(fei,
7044 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7045 1,
7046 &ip_o_1_1_1_1),
7047 "2.2.2.2.4/32 LB 1 buckets via: "
7048 "ip 1.1.1.1");
7049
7050 dpo_reset(&ip_1_1_1_1);
7051
7052 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00007053 * Create an entry with a deep label stack
7054 */
7055 fib_prefix_t pfx_2_2_5_5_s_32 = {
7056 .fp_len = 32,
7057 .fp_proto = FIB_PROTOCOL_IP4,
7058 .fp_addr = {
7059 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7060 },
7061 };
7062 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7063 .type = FT_LB_LABEL_STACK_O_ADJ,
7064 .label_stack_o_adj = {
7065 .adj = ai_mpls_10_10_11_1,
7066 .label_stack_size = 8,
7067 .label_stack = {
7068 200, 201, 202, 203, 204, 205, 206, 207
7069 },
7070 .eos = MPLS_EOS,
7071 },
7072 };
7073 mpls_label_t *label_stack = NULL;
7074 vec_validate(label_stack, 7);
7075 for (ii = 0; ii < 8; ii++)
7076 {
7077 label_stack[ii] = ii + 200;
7078 }
7079
7080 fei = fib_table_entry_update_one_path(fib_index,
7081 &pfx_2_2_5_5_s_32,
7082 FIB_SOURCE_API,
7083 FIB_ENTRY_FLAG_NONE,
7084 FIB_PROTOCOL_IP4,
7085 &nh_10_10_11_1,
7086 tm->hw[1]->sw_if_index,
7087 ~0, // invalid fib index
7088 1,
7089 label_stack,
7090 FIB_ROUTE_PATH_FLAG_NONE);
7091
7092 FIB_TEST(fib_test_validate_entry(fei,
7093 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7094 1,
7095 &ls_eos_o_10_10_10_1),
7096 "2.2.5.5/32 LB 1 buckets via: "
7097 "adj 10.10.11.1");
7098 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7099
7100 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007101 * cleanup
7102 */
7103 fib_table_entry_delete(fib_index,
7104 &pfx_1_1_1_2_s_32,
7105 FIB_SOURCE_API);
7106
7107 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7108 FIB_TEST(fib_test_validate_entry(fei,
7109 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7110 1,
7111 &l1600_eos_o_1_1_1_1),
7112 "2.2.2.2/32 LB 1 buckets via: "
7113 "label 1600 via 1.1,1.1");
7114
7115 fib_table_entry_delete(fib_index,
7116 &pfx_1_1_1_1_s_32,
7117 FIB_SOURCE_API);
7118
7119 FIB_TEST(fib_test_validate_entry(fei,
7120 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7121 1,
7122 &bucket_drop),
7123 "2.2.2.2/32 LB 1 buckets via: DROP");
7124
7125 fib_table_entry_delete(fib_index,
7126 &pfx_2_2_2_2_s_32,
7127 FIB_SOURCE_API);
7128 fib_table_entry_delete(fib_index,
7129 &pfx_2_2_2_3_s_32,
7130 FIB_SOURCE_API);
7131 fib_table_entry_delete(fib_index,
7132 &pfx_2_2_2_4_s_32,
7133 FIB_SOURCE_API);
7134
7135 adj_unlock(ai_mpls_10_10_10_1);
7136 adj_unlock(ai_mpls_10_10_11_2);
7137 adj_unlock(ai_v4_10_10_11_1);
7138 adj_unlock(ai_v4_10_10_11_2);
7139 adj_unlock(ai_mpls_10_10_11_1);
7140
7141 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7142 adj_nbr_db_size());
7143
7144 local0_pfx.fp_len = 32;
7145 fib_table_entry_delete(fib_index,
7146 &local0_pfx,
7147 FIB_SOURCE_INTERFACE);
7148 local0_pfx.fp_len = 24;
7149 fib_table_entry_delete(fib_index,
7150 &local0_pfx,
7151 FIB_SOURCE_INTERFACE);
7152 local1_pfx.fp_len = 32;
7153 fib_table_entry_delete(fib_index,
7154 &local1_pfx,
7155 FIB_SOURCE_INTERFACE);
7156 local1_pfx.fp_len = 24;
7157 fib_table_entry_delete(fib_index,
7158 &local1_pfx,
7159 FIB_SOURCE_INTERFACE);
7160
7161 /*
7162 * +1 for the drop LB in the MPLS tables.
7163 */
7164 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7165 "Load-balance resources freed %d of %d",
7166 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007167
7168 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007169}
7170
7171#define N_TEST_CHILDREN 4
7172#define PARENT_INDEX 0
7173
7174typedef struct fib_node_test_t_
7175{
7176 fib_node_t node;
7177 u32 sibling;
7178 u32 index;
7179 fib_node_back_walk_ctx_t *ctxs;
7180 u32 destroyed;
7181} fib_node_test_t;
7182
7183static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7184
7185#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7186
7187#define FOR_EACH_TEST_CHILD(_tc) \
7188 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7189 ii < N_TEST_CHILDREN+1; \
7190 ii++, (_tc) = &fib_test_nodes[ii])
7191
7192static fib_node_t *
7193fib_test_child_get_node (fib_node_index_t index)
7194{
7195 return (&fib_test_nodes[index].node);
7196}
7197
7198static int fib_test_walk_spawns_walks;
7199
7200static fib_node_back_walk_rc_t
7201fib_test_child_back_walk_notify (fib_node_t *node,
7202 fib_node_back_walk_ctx_t *ctx)
7203{
7204 fib_node_test_t *tc = (fib_node_test_t*) node;
7205
7206 vec_add1(tc->ctxs, *ctx);
7207
7208 if (1 == fib_test_walk_spawns_walks)
7209 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7210 if (2 == fib_test_walk_spawns_walks)
7211 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7212 FIB_WALK_PRIORITY_HIGH, ctx);
7213
7214 return (FIB_NODE_BACK_WALK_CONTINUE);
7215}
7216
7217static void
7218fib_test_child_last_lock_gone (fib_node_t *node)
7219{
7220 fib_node_test_t *tc = (fib_node_test_t *)node;
7221
7222 tc->destroyed = 1;
7223}
7224
7225/**
7226 * The FIB walk's graph node virtual function table
7227 */
7228static const fib_node_vft_t fib_test_child_vft = {
7229 .fnv_get = fib_test_child_get_node,
7230 .fnv_last_lock = fib_test_child_last_lock_gone,
7231 .fnv_back_walk = fib_test_child_back_walk_notify,
7232};
7233
7234/*
7235 * the function (that should have been static but isn't so I can do this)
7236 * that processes the walk from the async queue,
7237 */
7238f64 fib_walk_process_queues(vlib_main_t * vm,
7239 const f64 quota);
7240u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7241
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007242static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007243fib_test_walk (void)
7244{
7245 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7246 fib_node_test_t *tc;
7247 vlib_main_t *vm;
7248 u32 ii;
7249
7250 vm = vlib_get_main();
7251 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7252
7253 /*
7254 * init a fake node on which we will add children
7255 */
7256 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7257 FIB_NODE_TYPE_TEST);
7258
7259 FOR_EACH_TEST_CHILD(tc)
7260 {
7261 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7262 fib_node_lock(&tc->node);
7263 tc->ctxs = NULL;
7264 tc->index = ii;
7265 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7266 PARENT_INDEX,
7267 FIB_NODE_TYPE_TEST, ii);
7268 }
7269
7270 /*
7271 * enqueue a walk across the parents children.
7272 */
Neale Ranns450cd302016-11-09 17:49:42 +00007273 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007274
7275 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7276 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7277 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7278 "Parent has %d children pre-walk",
7279 fib_node_list_get_size(PARENT()->fn_children));
7280
7281 /*
7282 * give the walk a large amount of time so it gets to the end
7283 */
7284 fib_walk_process_queues(vm, 1);
7285
7286 FOR_EACH_TEST_CHILD(tc)
7287 {
7288 FIB_TEST(1 == vec_len(tc->ctxs),
7289 "%d child visitsed %d times",
7290 ii, vec_len(tc->ctxs));
7291 vec_free(tc->ctxs);
7292 }
7293 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7294 "Queue is empty post walk");
7295 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7296 "Parent has %d children post walk",
7297 fib_node_list_get_size(PARENT()->fn_children));
7298
7299 /*
7300 * walk again. should be no increase in the number of visits, since
7301 * the walk will have terminated.
7302 */
7303 fib_walk_process_queues(vm, 1);
7304
7305 FOR_EACH_TEST_CHILD(tc)
7306 {
7307 FIB_TEST(0 == vec_len(tc->ctxs),
7308 "%d child visitsed %d times",
7309 ii, vec_len(tc->ctxs));
7310 }
7311
7312 /*
7313 * schedule a low and hig priority walk. expect the high to be performed
7314 * before the low.
7315 * schedule the high prio walk first so that it is further from the head
7316 * of the dependency list. that way it won't merge with the low one.
7317 */
7318 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7319 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7320
7321 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7322 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7323 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7324 FIB_WALK_PRIORITY_LOW, &low_ctx);
7325
7326 fib_walk_process_queues(vm, 1);
7327
7328 FOR_EACH_TEST_CHILD(tc)
7329 {
7330 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7331 "%d child visitsed by high prio walk", ii);
7332 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7333 "%d child visitsed by low prio walk", ii);
7334 vec_free(tc->ctxs);
7335 }
7336 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7337 "Queue is empty post prio walk");
7338 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7339 "Parent has %d children post prio walk",
7340 fib_node_list_get_size(PARENT()->fn_children));
7341
7342 /*
7343 * schedule 2 walks of the same priority that can be megred.
7344 * expect that each child is thus visited only once.
7345 */
7346 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7347 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7348
7349 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7350 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7351 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7352 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7353
7354 fib_walk_process_queues(vm, 1);
7355
7356 FOR_EACH_TEST_CHILD(tc)
7357 {
7358 FIB_TEST(1 == vec_len(tc->ctxs),
7359 "%d child visitsed %d times during merge walk",
7360 ii, vec_len(tc->ctxs));
7361 vec_free(tc->ctxs);
7362 }
7363 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7364 "Queue is empty post merge walk");
7365 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7366 "Parent has %d children post merge walk",
7367 fib_node_list_get_size(PARENT()->fn_children));
7368
7369 /*
7370 * schedule 2 walks of the same priority that cannot be megred.
7371 * expect that each child is thus visited twice and in the order
7372 * in which the walks were scheduled.
7373 */
7374 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7375 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7376
7377 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7378 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7379 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7380 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7381
7382 fib_walk_process_queues(vm, 1);
7383
7384 FOR_EACH_TEST_CHILD(tc)
7385 {
7386 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7387 "%d child visitsed by high prio walk", ii);
7388 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7389 "%d child visitsed by low prio walk", ii);
7390 vec_free(tc->ctxs);
7391 }
7392 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7393 "Queue is empty post no-merge walk");
7394 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7395 "Parent has %d children post no-merge walk",
7396 fib_node_list_get_size(PARENT()->fn_children));
7397
7398 /*
7399 * schedule a walk that makes one one child progress.
7400 * we do this by giving the queue draining process zero
7401 * time quanta. it's a do..while loop, so it does something.
7402 */
Neale Ranns450cd302016-11-09 17:49:42 +00007403 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007404
7405 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7406 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7407 fib_walk_process_queues(vm, 0);
7408
7409 FOR_EACH_TEST_CHILD(tc)
7410 {
7411 if (ii == N_TEST_CHILDREN)
7412 {
7413 FIB_TEST(1 == vec_len(tc->ctxs),
7414 "%d child visitsed %d times in zero quanta walk",
7415 ii, vec_len(tc->ctxs));
7416 }
7417 else
7418 {
7419 FIB_TEST(0 == vec_len(tc->ctxs),
7420 "%d child visitsed %d times in 0 quanta walk",
7421 ii, vec_len(tc->ctxs));
7422 }
7423 }
7424 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7425 "Queue is not empty post zero quanta walk");
7426 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7427 "Parent has %d children post zero qunta walk",
7428 fib_node_list_get_size(PARENT()->fn_children));
7429
7430 /*
7431 * another one step
7432 */
7433 fib_walk_process_queues(vm, 0);
7434
7435 FOR_EACH_TEST_CHILD(tc)
7436 {
7437 if (ii >= N_TEST_CHILDREN-1)
7438 {
7439 FIB_TEST(1 == vec_len(tc->ctxs),
7440 "%d child visitsed %d times in 2nd zero quanta walk",
7441 ii, vec_len(tc->ctxs));
7442 }
7443 else
7444 {
7445 FIB_TEST(0 == vec_len(tc->ctxs),
7446 "%d child visitsed %d times in 2nd 0 quanta walk",
7447 ii, vec_len(tc->ctxs));
7448 }
7449 }
7450 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7451 "Queue is not empty post zero quanta walk");
7452 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7453 "Parent has %d children post zero qunta walk",
7454 fib_node_list_get_size(PARENT()->fn_children));
7455
7456 /*
7457 * schedule another walk that will catch-up and merge.
7458 */
7459 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7460 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7461 fib_walk_process_queues(vm, 1);
7462
7463 FOR_EACH_TEST_CHILD(tc)
7464 {
7465 if (ii >= N_TEST_CHILDREN-1)
7466 {
7467 FIB_TEST(2 == vec_len(tc->ctxs),
7468 "%d child visitsed %d times in 2nd zero quanta merge walk",
7469 ii, vec_len(tc->ctxs));
7470 vec_free(tc->ctxs);
7471 }
7472 else
7473 {
7474 FIB_TEST(1 == vec_len(tc->ctxs),
7475 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7476 ii, vec_len(tc->ctxs));
7477 vec_free(tc->ctxs);
7478 }
7479 }
7480 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7481 "Queue is not empty post 2nd zero quanta merge walk");
7482 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7483 "Parent has %d children post 2nd zero qunta merge walk",
7484 fib_node_list_get_size(PARENT()->fn_children));
7485
7486 /*
7487 * park a async walk in the middle of the list, then have an sync walk catch
7488 * it. same expectations as async catches async.
7489 */
Neale Ranns450cd302016-11-09 17:49:42 +00007490 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007491
7492 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7493 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7494
7495 fib_walk_process_queues(vm, 0);
7496 fib_walk_process_queues(vm, 0);
7497
7498 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7499
7500 FOR_EACH_TEST_CHILD(tc)
7501 {
7502 if (ii >= N_TEST_CHILDREN-1)
7503 {
7504 FIB_TEST(2 == vec_len(tc->ctxs),
7505 "%d child visitsed %d times in sync catches async walk",
7506 ii, vec_len(tc->ctxs));
7507 vec_free(tc->ctxs);
7508 }
7509 else
7510 {
7511 FIB_TEST(1 == vec_len(tc->ctxs),
7512 "%d child visitsed %d times in sync catches async walk",
7513 ii, vec_len(tc->ctxs));
7514 vec_free(tc->ctxs);
7515 }
7516 }
7517 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7518 "Queue is not empty post 2nd zero quanta merge walk");
7519 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7520 "Parent has %d children post 2nd zero qunta merge walk",
7521 fib_node_list_get_size(PARENT()->fn_children));
7522
7523 /*
7524 * make the parent a child of one of its children, thus inducing a routing loop.
7525 */
7526 fib_test_nodes[PARENT_INDEX].sibling =
7527 fib_node_child_add(FIB_NODE_TYPE_TEST,
7528 1, // the first child
7529 FIB_NODE_TYPE_TEST,
7530 PARENT_INDEX);
7531
7532 /*
7533 * execute a sync walk from the parent. each child visited spawns more sync
7534 * walks. we expect the walk to terminate.
7535 */
7536 fib_test_walk_spawns_walks = 1;
7537
7538 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7539
7540 FOR_EACH_TEST_CHILD(tc)
7541 {
7542 /*
7543 * child 1 - which is last in the list - has the loop.
7544 * the other children a re thus visitsed first. the we meet
7545 * child 1. we go round the loop again, visting the other children.
7546 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7547 * again.
7548 */
7549 if (1 == ii)
7550 {
7551 FIB_TEST(1 == vec_len(tc->ctxs),
7552 "child %d visitsed %d times during looped sync walk",
7553 ii, vec_len(tc->ctxs));
7554 }
7555 else
7556 {
7557 FIB_TEST(2 == vec_len(tc->ctxs),
7558 "child %d visitsed %d times during looped sync walk",
7559 ii, vec_len(tc->ctxs));
7560 }
7561 vec_free(tc->ctxs);
7562 }
7563 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7564 "Parent has %d children post sync loop walk",
7565 fib_node_list_get_size(PARENT()->fn_children));
7566
7567 /*
7568 * the walk doesn't reach the max depth because the infra knows that sync
7569 * meets sync implies a loop and bails early.
7570 */
7571 FIB_TEST(high_ctx.fnbw_depth == 9,
7572 "Walk context depth %d post sync loop walk",
7573 high_ctx.fnbw_depth);
7574
7575 /*
7576 * execute an async walk of the graph loop, with each child spawns sync walks
7577 */
7578 high_ctx.fnbw_depth = 0;
7579 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7580 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7581
7582 fib_walk_process_queues(vm, 1);
7583
7584 FOR_EACH_TEST_CHILD(tc)
7585 {
7586 /*
7587 * we don't really care how many times the children are visisted, as long as
7588 * it is more than once.
7589 */
7590 FIB_TEST(1 <= vec_len(tc->ctxs),
7591 "child %d visitsed %d times during looped aync spawns sync walk",
7592 ii, vec_len(tc->ctxs));
7593 vec_free(tc->ctxs);
7594 }
7595
7596 /*
7597 * execute an async walk of the graph loop, with each child spawns async walks
7598 */
7599 fib_test_walk_spawns_walks = 2;
7600 high_ctx.fnbw_depth = 0;
7601 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7602 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7603
7604 fib_walk_process_queues(vm, 1);
7605
7606 FOR_EACH_TEST_CHILD(tc)
7607 {
7608 /*
7609 * we don't really care how many times the children are visisted, as long as
7610 * it is more than once.
7611 */
7612 FIB_TEST(1 <= vec_len(tc->ctxs),
7613 "child %d visitsed %d times during looped async spawns async walk",
7614 ii, vec_len(tc->ctxs));
7615 vec_free(tc->ctxs);
7616 }
7617
7618
7619 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7620 1, // the first child
7621 fib_test_nodes[PARENT_INDEX].sibling);
7622
7623 /*
7624 * cleanup
7625 */
7626 FOR_EACH_TEST_CHILD(tc)
7627 {
7628 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7629 tc->sibling);
7630 fib_node_deinit(&tc->node);
7631 fib_node_unlock(&tc->node);
7632 }
7633 fib_node_deinit(PARENT());
7634
7635 /*
7636 * The parent will be destroyed when the last lock on it goes.
7637 * this test ensures all the walk objects are unlocking it.
7638 */
7639 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7640 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007641
7642 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007643}
7644
Neale Ranns88fc83e2017-04-05 08:11:14 -07007645/*
7646 * declaration of the otherwise static callback functions
7647 */
7648void fib_bfd_notify (bfd_listen_event_e event,
7649 const bfd_session_t *session);
7650void adj_bfd_notify (bfd_listen_event_e event,
7651 const bfd_session_t *session);
7652
7653/**
7654 * Test BFD session interaction with FIB
7655 */
7656static int
7657fib_test_bfd (void)
7658{
7659 fib_node_index_t fei;
7660 test_main_t *tm;
7661 int n_feis;
7662
7663 /* via 10.10.10.1 */
7664 ip46_address_t nh_10_10_10_1 = {
7665 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7666 };
7667 /* via 10.10.10.2 */
7668 ip46_address_t nh_10_10_10_2 = {
7669 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7670 };
7671 /* via 10.10.10.10 */
7672 ip46_address_t nh_10_10_10_10 = {
7673 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7674 };
7675 n_feis = fib_entry_pool_size();
7676
7677 tm = &test_main;
7678
7679 /*
7680 * add interface routes. we'll assume this works. it's tested elsewhere
7681 */
7682 fib_prefix_t pfx_10_10_10_10_s_24 = {
7683 .fp_len = 24,
7684 .fp_proto = FIB_PROTOCOL_IP4,
7685 .fp_addr = nh_10_10_10_10,
7686 };
7687
7688 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7689 FIB_SOURCE_INTERFACE,
7690 (FIB_ENTRY_FLAG_CONNECTED |
7691 FIB_ENTRY_FLAG_ATTACHED),
7692 FIB_PROTOCOL_IP4,
7693 NULL,
7694 tm->hw[0]->sw_if_index,
7695 ~0, // invalid fib index
7696 1, // weight
7697 NULL,
7698 FIB_ROUTE_PATH_FLAG_NONE);
7699
7700 fib_prefix_t pfx_10_10_10_10_s_32 = {
7701 .fp_len = 32,
7702 .fp_proto = FIB_PROTOCOL_IP4,
7703 .fp_addr = nh_10_10_10_10,
7704 };
7705 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7706 FIB_SOURCE_INTERFACE,
7707 (FIB_ENTRY_FLAG_CONNECTED |
7708 FIB_ENTRY_FLAG_LOCAL),
7709 FIB_PROTOCOL_IP4,
7710 NULL,
7711 tm->hw[0]->sw_if_index,
7712 ~0, // invalid fib index
7713 1, // weight
7714 NULL,
7715 FIB_ROUTE_PATH_FLAG_NONE);
7716
7717 /*
7718 * A BFD session via a neighbour we do not yet know
7719 */
7720 bfd_session_t bfd_10_10_10_1 = {
7721 .udp = {
7722 .key = {
7723 .fib_index = 0,
7724 .peer_addr = nh_10_10_10_1,
7725 },
7726 },
7727 .hop_type = BFD_HOP_TYPE_MULTI,
7728 .local_state = BFD_STATE_init,
7729 };
7730
7731 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7732
7733 /*
7734 * A new entry will be created that forwards via the adj
7735 */
7736 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7737 VNET_LINK_IP4,
7738 &nh_10_10_10_1,
7739 tm->hw[0]->sw_if_index);
7740 fib_prefix_t pfx_10_10_10_1_s_32 = {
7741 .fp_addr = nh_10_10_10_1,
7742 .fp_len = 32,
7743 .fp_proto = FIB_PROTOCOL_IP4,
7744 };
7745 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7746 .type = FT_LB_ADJ,
7747 .adj = {
7748 .adj = ai_10_10_10_1,
7749 },
7750 };
7751
7752 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7753 FIB_TEST(fib_test_validate_entry(fei,
7754 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7755 1,
7756 &adj_o_10_10_10_1),
7757 "BFD sourced %U via %U",
7758 format_fib_prefix, &pfx_10_10_10_1_s_32,
7759 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7760
7761 /*
7762 * Delete the BFD session. Expect the fib_entry to be removed
7763 */
7764 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7765
7766 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7767 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7768 "BFD sourced %U removed",
7769 format_fib_prefix, &pfx_10_10_10_1_s_32);
7770
7771 /*
7772 * Add the BFD source back
7773 */
7774 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7775
7776 /*
7777 * source the entry via the ADJ fib
7778 */
Neale Ranns81424992017-05-18 03:03:22 -07007779 fei = fib_table_entry_path_add(0,
7780 &pfx_10_10_10_1_s_32,
7781 FIB_SOURCE_ADJ,
7782 FIB_ENTRY_FLAG_ATTACHED,
7783 FIB_PROTOCOL_IP4,
7784 &nh_10_10_10_1,
7785 tm->hw[0]->sw_if_index,
7786 ~0, // invalid fib index
7787 1,
7788 NULL,
7789 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007790
7791 /*
7792 * Delete the BFD session. Expect the fib_entry to remain
7793 */
7794 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7795
7796 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7797 FIB_TEST(fib_test_validate_entry(fei,
7798 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7799 1,
7800 &adj_o_10_10_10_1),
7801 "BFD sourced %U remains via %U",
7802 format_fib_prefix, &pfx_10_10_10_1_s_32,
7803 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7804
7805 /*
7806 * Add the BFD source back
7807 */
7808 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7809
7810 /*
7811 * Create another ADJ FIB
7812 */
7813 fib_prefix_t pfx_10_10_10_2_s_32 = {
7814 .fp_addr = nh_10_10_10_2,
7815 .fp_len = 32,
7816 .fp_proto = FIB_PROTOCOL_IP4,
7817 };
Neale Ranns81424992017-05-18 03:03:22 -07007818 fib_table_entry_path_add(0,
7819 &pfx_10_10_10_2_s_32,
7820 FIB_SOURCE_ADJ,
7821 FIB_ENTRY_FLAG_ATTACHED,
7822 FIB_PROTOCOL_IP4,
7823 &nh_10_10_10_2,
7824 tm->hw[0]->sw_if_index,
7825 ~0, // invalid fib index
7826 1,
7827 NULL,
7828 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007829 /*
7830 * A BFD session for the new ADJ FIB
7831 */
7832 bfd_session_t bfd_10_10_10_2 = {
7833 .udp = {
7834 .key = {
7835 .fib_index = 0,
7836 .peer_addr = nh_10_10_10_2,
7837 },
7838 },
7839 .hop_type = BFD_HOP_TYPE_MULTI,
7840 .local_state = BFD_STATE_init,
7841 };
7842
7843 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7844
7845 /*
7846 * remove the adj-fib source whilst the session is present
7847 * then add it back
7848 */
7849 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07007850 fib_table_entry_path_add(0,
7851 &pfx_10_10_10_2_s_32,
7852 FIB_SOURCE_ADJ,
7853 FIB_ENTRY_FLAG_ATTACHED,
7854 FIB_PROTOCOL_IP4,
7855 &nh_10_10_10_2,
7856 tm->hw[0]->sw_if_index,
7857 ~0, // invalid fib index
7858 1,
7859 NULL,
7860 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007861
7862 /*
7863 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7864 * bring one of the sessions UP, leave the other down
7865 */
7866 bfd_10_10_10_1.local_state = BFD_STATE_up;
7867 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7868 bfd_10_10_10_2.local_state = BFD_STATE_down;
7869 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7870
7871 /*
7872 * A recursive prefix via both of the ADJ FIBs
7873 */
7874 fib_prefix_t pfx_200_0_0_0_s_24 = {
7875 .fp_proto = FIB_PROTOCOL_IP4,
7876 .fp_len = 32,
7877 .fp_addr = {
7878 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7879 },
7880 };
7881 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7882
7883 dpo_10_10_10_1 =
7884 fib_entry_contribute_ip_forwarding(
7885 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7886 dpo_10_10_10_2 =
7887 fib_entry_contribute_ip_forwarding(
7888 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7889
7890 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7891 .type = FT_LB_O_LB,
7892 .lb = {
7893 .lb = dpo_10_10_10_1->dpoi_index,
7894 },
7895 };
7896 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7897 .type = FT_LB_O_LB,
7898 .lb = {
7899 .lb = dpo_10_10_10_2->dpoi_index,
7900 },
7901 };
7902
7903 /*
7904 * A prefix via the adj-fib that is BFD down => DROP
7905 */
7906 fei = fib_table_entry_path_add(0,
7907 &pfx_200_0_0_0_s_24,
7908 FIB_SOURCE_API,
7909 FIB_ENTRY_FLAG_NONE,
7910 FIB_PROTOCOL_IP4,
7911 &nh_10_10_10_2,
7912 ~0, // recursive
7913 0, // default fib index
7914 1,
7915 NULL,
7916 FIB_ROUTE_PATH_FLAG_NONE);
7917 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7918 "%U resolves via drop",
7919 format_fib_prefix, &pfx_200_0_0_0_s_24);
7920
7921 /*
7922 * add a path via the UP BFD adj-fib.
7923 * we expect that the DOWN BFD ADJ FIB is not used.
7924 */
7925 fei = fib_table_entry_path_add(0,
7926 &pfx_200_0_0_0_s_24,
7927 FIB_SOURCE_API,
7928 FIB_ENTRY_FLAG_NONE,
7929 FIB_PROTOCOL_IP4,
7930 &nh_10_10_10_1,
7931 ~0, // recursive
7932 0, // default fib index
7933 1,
7934 NULL,
7935 FIB_ROUTE_PATH_FLAG_NONE);
7936
7937 FIB_TEST(fib_test_validate_entry(fei,
7938 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7939 1,
7940 &lb_o_10_10_10_1),
7941 "Recursive %U only UP BFD adj-fibs",
7942 format_fib_prefix, &pfx_200_0_0_0_s_24);
7943
7944 /*
7945 * Send a BFD state change to UP - both sessions are now up
7946 * the recursive prefix should LB over both
7947 */
7948 bfd_10_10_10_2.local_state = BFD_STATE_up;
7949 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7950
7951
7952 FIB_TEST(fib_test_validate_entry(fei,
7953 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7954 2,
7955 &lb_o_10_10_10_1,
7956 &lb_o_10_10_10_2),
7957 "Recursive %U via both UP BFD adj-fibs",
7958 format_fib_prefix, &pfx_200_0_0_0_s_24);
7959
7960 /*
7961 * Send a BFD state change to DOWN
7962 * the recursive prefix should exclude the down
7963 */
7964 bfd_10_10_10_2.local_state = BFD_STATE_down;
7965 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7966
7967
7968 FIB_TEST(fib_test_validate_entry(fei,
7969 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7970 1,
7971 &lb_o_10_10_10_1),
7972 "Recursive %U via only UP",
7973 format_fib_prefix, &pfx_200_0_0_0_s_24);
7974
7975 /*
7976 * Delete the BFD session while it is in the DOWN state.
7977 * FIB should consider the entry's state as back up
7978 */
7979 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
7980
7981 FIB_TEST(fib_test_validate_entry(fei,
7982 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7983 2,
7984 &lb_o_10_10_10_1,
7985 &lb_o_10_10_10_2),
7986 "Recursive %U via both UP BFD adj-fibs post down session delete",
7987 format_fib_prefix, &pfx_200_0_0_0_s_24);
7988
7989 /*
7990 * Delete the BFD other session while it is in the UP state.
7991 */
7992 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7993
7994 FIB_TEST(fib_test_validate_entry(fei,
7995 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7996 2,
7997 &lb_o_10_10_10_1,
7998 &lb_o_10_10_10_2),
7999 "Recursive %U via both UP BFD adj-fibs post up session delete",
8000 format_fib_prefix, &pfx_200_0_0_0_s_24);
8001
8002 /*
8003 * cleaup
8004 */
8005 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8006 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8007 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8008
8009 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8010 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8011
8012 adj_unlock(ai_10_10_10_1);
8013 /*
8014 * test no-one left behind
8015 */
8016 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8017 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8018
8019 /*
8020 * Single-hop BFD tests
8021 */
8022 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8023 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8024
8025 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8026
8027 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8028 VNET_LINK_IP4,
8029 &nh_10_10_10_1,
8030 tm->hw[0]->sw_if_index);
8031 /*
8032 * whilst the BFD session is not signalled, the adj is up
8033 */
8034 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8035
8036 /*
8037 * bring the BFD session up
8038 */
8039 bfd_10_10_10_1.local_state = BFD_STATE_up;
8040 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8041 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8042
8043 /*
8044 * bring the BFD session down
8045 */
8046 bfd_10_10_10_1.local_state = BFD_STATE_down;
8047 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8048 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8049
8050
8051 /*
8052 * add an attached next hop FIB entry via the down adj
8053 */
8054 fib_prefix_t pfx_5_5_5_5_s_32 = {
8055 .fp_addr = {
8056 .ip4 = {
8057 .as_u32 = clib_host_to_net_u32(0x05050505),
8058 },
8059 },
8060 .fp_len = 32,
8061 .fp_proto = FIB_PROTOCOL_IP4,
8062 };
8063
8064 fei = fib_table_entry_path_add(0,
8065 &pfx_5_5_5_5_s_32,
8066 FIB_SOURCE_CLI,
8067 FIB_ENTRY_FLAG_NONE,
8068 FIB_PROTOCOL_IP4,
8069 &nh_10_10_10_1,
8070 tm->hw[0]->sw_if_index,
8071 ~0, // invalid fib index
8072 1,
8073 NULL,
8074 FIB_ROUTE_PATH_FLAG_NONE);
8075 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8076 "%U resolves via drop",
8077 format_fib_prefix, &pfx_5_5_5_5_s_32);
8078
8079 /*
8080 * Add a path via an ADJ that is up
8081 */
8082 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8083 VNET_LINK_IP4,
8084 &nh_10_10_10_2,
8085 tm->hw[0]->sw_if_index);
8086
8087 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8088 .type = FT_LB_ADJ,
8089 .adj = {
8090 .adj = ai_10_10_10_2,
8091 },
8092 };
8093 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8094
8095 fei = fib_table_entry_path_add(0,
8096 &pfx_5_5_5_5_s_32,
8097 FIB_SOURCE_CLI,
8098 FIB_ENTRY_FLAG_NONE,
8099 FIB_PROTOCOL_IP4,
8100 &nh_10_10_10_2,
8101 tm->hw[0]->sw_if_index,
8102 ~0, // invalid fib index
8103 1,
8104 NULL,
8105 FIB_ROUTE_PATH_FLAG_NONE);
8106
8107 FIB_TEST(fib_test_validate_entry(fei,
8108 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8109 1,
8110 &adj_o_10_10_10_2),
8111 "BFD sourced %U via %U",
8112 format_fib_prefix, &pfx_5_5_5_5_s_32,
8113 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8114
8115 /*
8116 * Bring up the down session - should now LB
8117 */
8118 bfd_10_10_10_1.local_state = BFD_STATE_up;
8119 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8120 FIB_TEST(fib_test_validate_entry(fei,
8121 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8122 2,
8123 &adj_o_10_10_10_1,
8124 &adj_o_10_10_10_2),
8125 "BFD sourced %U via noth adjs",
8126 format_fib_prefix, &pfx_5_5_5_5_s_32);
8127
8128 /*
8129 * remove the BFD session state from the adj
8130 */
8131 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8132
8133 /*
8134 * clean-up
8135 */
8136 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8137 adj_unlock(ai_10_10_10_1);
8138 adj_unlock(ai_10_10_10_2);
8139
8140 /*
8141 * test no-one left behind
8142 */
8143 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8144 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8145 return (0);
8146}
8147
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008148static int
8149lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008150{
8151 const mpls_label_t deag_label = 50;
8152 const u32 lfib_index = 0;
8153 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01008154 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008155 const dpo_id_t *dpo1;
8156 fib_node_index_t lfe;
8157 lookup_dpo_t *lkd;
8158 test_main_t *tm;
8159 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00008160 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008161
8162 tm = &test_main;
8163 lb_count = pool_elts(load_balance_pool);
8164
8165 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8166 adj_nbr_db_size());
8167
8168 /*
8169 * MPLS enable an interface so we get the MPLS table created
8170 */
8171 mpls_sw_interface_enable_disable(&mpls_main,
8172 tm->hw[0]->sw_if_index,
8173 1);
8174
Neale Rannsad422ed2016-11-02 14:20:04 +00008175 ip46_address_t nh_10_10_10_1 = {
8176 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8177 };
8178 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8179 VNET_LINK_MPLS,
8180 &nh_10_10_10_1,
8181 tm->hw[0]->sw_if_index);
8182
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008183 /*
8184 * Test the specials stack properly.
8185 */
8186 fib_prefix_t exp_null_v6_pfx = {
8187 .fp_proto = FIB_PROTOCOL_MPLS,
8188 .fp_eos = MPLS_EOS,
8189 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8190 .fp_payload_proto = DPO_PROTO_IP6,
8191 };
8192 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8193 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8194 "%U/%U present",
8195 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8196 format_mpls_eos_bit, MPLS_EOS);
8197 fib_entry_contribute_forwarding(lfe,
8198 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8199 &dpo);
8200 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8201 lkd = lookup_dpo_get(dpo1->dpoi_index);
8202
8203 FIB_TEST((fib_index == lkd->lkd_fib_index),
8204 "%U/%U is deag in %d %U",
8205 format_mpls_unicast_label, deag_label,
8206 format_mpls_eos_bit, MPLS_EOS,
8207 lkd->lkd_fib_index,
8208 format_dpo_id, &dpo, 0);
8209 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8210 "%U/%U is dst deag",
8211 format_mpls_unicast_label, deag_label,
8212 format_mpls_eos_bit, MPLS_EOS);
8213 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8214 "%U/%U is lookup in interface's table",
8215 format_mpls_unicast_label, deag_label,
8216 format_mpls_eos_bit, MPLS_EOS);
8217 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8218 "%U/%U is %U dst deag",
8219 format_mpls_unicast_label, deag_label,
8220 format_mpls_eos_bit, MPLS_EOS,
8221 format_dpo_proto, lkd->lkd_proto);
8222
8223
8224 /*
8225 * A route deag route for EOS
8226 */
8227 fib_prefix_t pfx = {
8228 .fp_proto = FIB_PROTOCOL_MPLS,
8229 .fp_eos = MPLS_EOS,
8230 .fp_label = deag_label,
8231 .fp_payload_proto = DPO_PROTO_IP4,
8232 };
8233 lfe = fib_table_entry_path_add(lfib_index,
8234 &pfx,
8235 FIB_SOURCE_CLI,
8236 FIB_ENTRY_FLAG_NONE,
8237 FIB_PROTOCOL_IP4,
8238 &zero_addr,
8239 ~0,
8240 fib_index,
8241 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008242 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008243 FIB_ROUTE_PATH_FLAG_NONE);
8244
8245 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8246 "%U/%U present",
8247 format_mpls_unicast_label, deag_label,
8248 format_mpls_eos_bit, MPLS_EOS);
8249
8250 fib_entry_contribute_forwarding(lfe,
8251 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8252 &dpo);
8253 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8254 lkd = lookup_dpo_get(dpo1->dpoi_index);
8255
8256 FIB_TEST((fib_index == lkd->lkd_fib_index),
8257 "%U/%U is deag in %d %U",
8258 format_mpls_unicast_label, deag_label,
8259 format_mpls_eos_bit, MPLS_EOS,
8260 lkd->lkd_fib_index,
8261 format_dpo_id, &dpo, 0);
8262 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8263 "%U/%U is dst deag",
8264 format_mpls_unicast_label, deag_label,
8265 format_mpls_eos_bit, MPLS_EOS);
8266 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8267 "%U/%U is %U dst deag",
8268 format_mpls_unicast_label, deag_label,
8269 format_mpls_eos_bit, MPLS_EOS,
8270 format_dpo_proto, lkd->lkd_proto);
8271
8272 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8273
8274 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8275 &pfx)),
8276 "%U/%U not present",
8277 format_mpls_unicast_label, deag_label,
8278 format_mpls_eos_bit, MPLS_EOS);
8279
8280 /*
8281 * A route deag route for non-EOS
8282 */
8283 pfx.fp_eos = MPLS_NON_EOS;
8284 lfe = fib_table_entry_path_add(lfib_index,
8285 &pfx,
8286 FIB_SOURCE_CLI,
8287 FIB_ENTRY_FLAG_NONE,
8288 FIB_PROTOCOL_IP4,
8289 &zero_addr,
8290 ~0,
8291 lfib_index,
8292 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008293 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008294 FIB_ROUTE_PATH_FLAG_NONE);
8295
8296 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8297 "%U/%U present",
8298 format_mpls_unicast_label, deag_label,
8299 format_mpls_eos_bit, MPLS_NON_EOS);
8300
8301 fib_entry_contribute_forwarding(lfe,
8302 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8303 &dpo);
8304 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8305 lkd = lookup_dpo_get(dpo1->dpoi_index);
8306
8307 FIB_TEST((fib_index == lkd->lkd_fib_index),
8308 "%U/%U is deag in %d %U",
8309 format_mpls_unicast_label, deag_label,
8310 format_mpls_eos_bit, MPLS_NON_EOS,
8311 lkd->lkd_fib_index,
8312 format_dpo_id, &dpo, 0);
8313 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8314 "%U/%U is dst deag",
8315 format_mpls_unicast_label, deag_label,
8316 format_mpls_eos_bit, MPLS_NON_EOS);
8317
8318 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8319 "%U/%U is %U dst deag",
8320 format_mpls_unicast_label, deag_label,
8321 format_mpls_eos_bit, MPLS_NON_EOS,
8322 format_dpo_proto, lkd->lkd_proto);
8323
8324 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8325
8326 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8327 &pfx)),
8328 "%U/%U not present",
8329 format_mpls_unicast_label, deag_label,
8330 format_mpls_eos_bit, MPLS_EOS);
8331
Neale Rannsad422ed2016-11-02 14:20:04 +00008332 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008333
Neale Rannsad422ed2016-11-02 14:20:04 +00008334 /*
8335 * An MPLS x-connect
8336 */
8337 fib_prefix_t pfx_1200 = {
8338 .fp_len = 21,
8339 .fp_proto = FIB_PROTOCOL_MPLS,
8340 .fp_label = 1200,
8341 .fp_eos = MPLS_NON_EOS,
8342 };
8343 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8344 .type = FT_LB_LABEL_STACK_O_ADJ,
8345 .label_stack_o_adj = {
8346 .adj = ai_mpls_10_10_10_1,
8347 .label_stack_size = 4,
8348 .label_stack = {
8349 200, 300, 400, 500,
8350 },
8351 .eos = MPLS_NON_EOS,
8352 },
8353 };
8354 dpo_id_t neos_1200 = DPO_INVALID;
8355 dpo_id_t ip_1200 = DPO_INVALID;
8356 mpls_label_t *l200 = NULL;
8357 vec_add1(l200, 200);
8358 vec_add1(l200, 300);
8359 vec_add1(l200, 400);
8360 vec_add1(l200, 500);
8361
8362 lfe = fib_table_entry_update_one_path(fib_index,
8363 &pfx_1200,
8364 FIB_SOURCE_API,
8365 FIB_ENTRY_FLAG_NONE,
8366 FIB_PROTOCOL_IP4,
8367 &nh_10_10_10_1,
8368 tm->hw[0]->sw_if_index,
8369 ~0, // invalid fib index
8370 1,
8371 l200,
8372 FIB_ROUTE_PATH_FLAG_NONE);
8373
8374 FIB_TEST(fib_test_validate_entry(lfe,
8375 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8376 1,
8377 &neos_o_10_10_10_1),
8378 "1200/0 LB 1 buckets via: "
8379 "adj 10.10.11.1");
8380
8381 /*
8382 * A recursive route via the MPLS x-connect
8383 */
8384 fib_prefix_t pfx_2_2_2_3_s_32 = {
8385 .fp_len = 32,
8386 .fp_proto = FIB_PROTOCOL_IP4,
8387 .fp_addr = {
8388 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8389 },
8390 };
8391 fib_route_path_t *rpaths = NULL, rpath = {
8392 .frp_proto = FIB_PROTOCOL_MPLS,
8393 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008394 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008395 .frp_sw_if_index = ~0, // recurive
8396 .frp_fib_index = 0, // Default MPLS fib
8397 .frp_weight = 1,
8398 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8399 .frp_label_stack = NULL,
8400 };
8401 vec_add1(rpaths, rpath);
8402
8403 fib_table_entry_path_add2(fib_index,
8404 &pfx_2_2_2_3_s_32,
8405 FIB_SOURCE_API,
8406 FIB_ENTRY_FLAG_NONE,
8407 rpaths);
8408
8409 /*
8410 * A labelled recursive route via the MPLS x-connect
8411 */
8412 fib_prefix_t pfx_2_2_2_4_s_32 = {
8413 .fp_len = 32,
8414 .fp_proto = FIB_PROTOCOL_IP4,
8415 .fp_addr = {
8416 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8417 },
8418 };
8419 mpls_label_t *l999 = NULL;
8420 vec_add1(l999, 999);
8421 rpaths[0].frp_label_stack = l999,
8422
8423 fib_table_entry_path_add2(fib_index,
8424 &pfx_2_2_2_4_s_32,
8425 FIB_SOURCE_API,
8426 FIB_ENTRY_FLAG_NONE,
8427 rpaths);
8428
8429 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8430 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8431 &ip_1200);
8432 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8433 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8434 &neos_1200);
8435
8436 fib_test_lb_bucket_t ip_o_1200 = {
8437 .type = FT_LB_O_LB,
8438 .lb = {
8439 .lb = ip_1200.dpoi_index,
8440 },
8441 };
8442 fib_test_lb_bucket_t mpls_o_1200 = {
8443 .type = FT_LB_LABEL_O_LB,
8444 .label_o_lb = {
8445 .lb = neos_1200.dpoi_index,
8446 .label = 999,
8447 .eos = MPLS_EOS,
8448 },
8449 };
8450
8451 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8452 FIB_TEST(fib_test_validate_entry(lfe,
8453 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8454 1,
8455 &ip_o_1200),
8456 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8457 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8458 FIB_TEST(fib_test_validate_entry(lfe,
8459 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8460 1,
8461 &mpls_o_1200),
8462 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8463
8464 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8465 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8466 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8467
8468 dpo_reset(&neos_1200);
8469 dpo_reset(&ip_1200);
8470
8471 /*
8472 * A recursive via a label that does not exist
8473 */
8474 fib_test_lb_bucket_t bucket_drop = {
8475 .type = FT_LB_SPECIAL,
8476 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07008477 .adj = DPO_PROTO_IP4,
8478 },
8479 };
8480 fib_test_lb_bucket_t mpls_bucket_drop = {
8481 .type = FT_LB_SPECIAL,
8482 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00008483 .adj = DPO_PROTO_MPLS,
8484 },
8485 };
8486
8487 rpaths[0].frp_label_stack = NULL;
8488 lfe = fib_table_entry_path_add2(fib_index,
8489 &pfx_2_2_2_4_s_32,
8490 FIB_SOURCE_API,
8491 FIB_ENTRY_FLAG_NONE,
8492 rpaths);
8493
8494 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8495 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8496 &ip_1200);
8497 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8498
8499 FIB_TEST(fib_test_validate_entry(lfe,
8500 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8501 1,
Neale Ranns57b58602017-07-15 07:37:25 -07008502 &bucket_drop),
8503 "2.2.2.2.4/32 LB 1 buckets via: drop");
Neale Rannsad422ed2016-11-02 14:20:04 +00008504 lfe = fib_table_lookup(fib_index, &pfx_1200);
8505 FIB_TEST(fib_test_validate_entry(lfe,
8506 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8507 1,
8508 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07008509 "1200/neos LB 1 buckets via: ip4-DROP");
8510 FIB_TEST(fib_test_validate_entry(lfe,
8511 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8512 1,
8513 &mpls_bucket_drop),
8514 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00008515
8516 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8517
8518 dpo_reset(&ip_1200);
8519
8520 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008521 * An rx-interface route.
8522 * like the tail of an mcast LSP
8523 */
8524 dpo_id_t idpo = DPO_INVALID;
8525
8526 interface_dpo_add_or_lock(DPO_PROTO_IP4,
8527 tm->hw[0]->sw_if_index,
8528 &idpo);
8529
8530 fib_prefix_t pfx_2500 = {
8531 .fp_len = 21,
8532 .fp_proto = FIB_PROTOCOL_MPLS,
8533 .fp_label = 2500,
8534 .fp_eos = MPLS_EOS,
8535 .fp_payload_proto = DPO_PROTO_IP4,
8536 };
8537 fib_test_lb_bucket_t rx_intf_0 = {
8538 .type = FT_LB_INTF,
8539 .adj = {
8540 .adj = idpo.dpoi_index,
8541 },
8542 };
8543
8544 lfe = fib_table_entry_update_one_path(fib_index,
8545 &pfx_2500,
8546 FIB_SOURCE_API,
8547 FIB_ENTRY_FLAG_NONE,
8548 FIB_PROTOCOL_IP4,
8549 NULL,
8550 tm->hw[0]->sw_if_index,
8551 ~0, // invalid fib index
8552 0,
8553 NULL,
8554 FIB_ROUTE_PATH_INTF_RX);
8555 FIB_TEST(fib_test_validate_entry(lfe,
8556 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8557 1,
8558 &rx_intf_0),
8559 "2500 rx-interface 0");
8560 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8561
8562 /*
8563 * An MPLS mulicast entry
8564 */
8565 fib_prefix_t pfx_3500 = {
8566 .fp_len = 21,
8567 .fp_proto = FIB_PROTOCOL_MPLS,
8568 .fp_label = 3500,
8569 .fp_eos = MPLS_EOS,
8570 .fp_payload_proto = DPO_PROTO_IP4,
8571 };
8572 fib_test_rep_bucket_t mc_0 = {
8573 .type = FT_REP_LABEL_O_ADJ,
8574 .label_o_adj = {
8575 .adj = ai_mpls_10_10_10_1,
8576 .label = 3300,
8577 .eos = MPLS_EOS,
8578 },
8579 };
8580 fib_test_rep_bucket_t mc_intf_0 = {
8581 .type = FT_REP_INTF,
8582 .adj = {
8583 .adj = idpo.dpoi_index,
8584 },
8585 };
8586 mpls_label_t *l3300 = NULL;
8587 vec_add1(l3300, 3300);
8588
8589 lfe = fib_table_entry_update_one_path(lfib_index,
8590 &pfx_3500,
8591 FIB_SOURCE_API,
8592 FIB_ENTRY_FLAG_MULTICAST,
8593 FIB_PROTOCOL_IP4,
8594 &nh_10_10_10_1,
8595 tm->hw[0]->sw_if_index,
8596 ~0, // invalid fib index
8597 1,
8598 l3300,
8599 FIB_ROUTE_PATH_FLAG_NONE);
8600 FIB_TEST(fib_test_validate_entry(lfe,
8601 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8602 1,
8603 &mc_0),
8604 "3500 via replicate over 10.10.10.1");
8605
8606 /*
8607 * MPLS Bud-node. Add a replication via an interface-receieve path
8608 */
8609 lfe = fib_table_entry_path_add(lfib_index,
8610 &pfx_3500,
8611 FIB_SOURCE_API,
8612 FIB_ENTRY_FLAG_MULTICAST,
8613 FIB_PROTOCOL_IP4,
8614 NULL,
8615 tm->hw[0]->sw_if_index,
8616 ~0, // invalid fib index
8617 0,
8618 NULL,
8619 FIB_ROUTE_PATH_INTF_RX);
8620 FIB_TEST(fib_test_validate_entry(lfe,
8621 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8622 2,
8623 &mc_0,
8624 &mc_intf_0),
8625 "3500 via replicate over 10.10.10.1 and interface-rx");
8626
8627 /*
8628 * Add a replication via an interface-free for-us path
8629 */
8630 fib_test_rep_bucket_t mc_disp = {
8631 .type = FT_REP_DISP_MFIB_LOOKUP,
8632 .adj = {
8633 .adj = idpo.dpoi_index,
8634 },
8635 };
8636 lfe = fib_table_entry_path_add(lfib_index,
8637 &pfx_3500,
8638 FIB_SOURCE_API,
8639 FIB_ENTRY_FLAG_MULTICAST,
8640 FIB_PROTOCOL_IP4,
8641 NULL,
8642 5, // rpf-id
8643 0, // default table
8644 0,
8645 NULL,
8646 FIB_ROUTE_PATH_RPF_ID);
8647 FIB_TEST(fib_test_validate_entry(lfe,
8648 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8649 3,
8650 &mc_0,
8651 &mc_disp,
8652 &mc_intf_0),
8653 "3500 via replicate over 10.10.10.1 and interface-rx");
8654
8655
8656
8657 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8658 dpo_reset(&idpo);
8659
8660 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008661 * cleanup
8662 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008663 mpls_sw_interface_enable_disable(&mpls_main,
8664 tm->hw[0]->sw_if_index,
8665 0);
8666
Neale Rannsad422ed2016-11-02 14:20:04 +00008667 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008668 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008669 lb_count, pool_elts(load_balance_pool));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008670 FIB_TEST(0 == pool_elts(interface_dpo_pool),
8671 "interface_dpo resources freed %d of %d",
8672 0, pool_elts(interface_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008673
8674 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008675}
8676
8677static clib_error_t *
8678fib_test (vlib_main_t * vm,
8679 unformat_input_t * input,
8680 vlib_cli_command_t * cmd_arg)
8681{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008682 int res;
8683
8684 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008685 fib_test_mk_intf(4);
8686
Neale Ranns88fc83e2017-04-05 08:11:14 -07008687 if (unformat (input, "debug"))
8688 {
8689 fib_test_do_debug = 1;
8690 }
8691
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008692 if (unformat (input, "ip"))
8693 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008694 res += fib_test_v4();
8695 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008696 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008697 else if (unformat (input, "label"))
8698 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008699 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008700 }
8701 else if (unformat (input, "ae"))
8702 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008703 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008704 }
Neale Ranns57b58602017-07-15 07:37:25 -07008705 else if (unformat (input, "pref"))
8706 {
8707 res += fib_test_pref();
8708 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008709 else if (unformat (input, "lfib"))
8710 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008711 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008712 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008713 else if (unformat (input, "walk"))
8714 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008715 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008716 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008717 else if (unformat (input, "bfd"))
8718 {
8719 res += fib_test_bfd();
8720 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008721 else
8722 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008723 res += fib_test_v4();
8724 res += fib_test_v6();
8725 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008726 res += fib_test_bfd();
Neale Ranns57b58602017-07-15 07:37:25 -07008727 res += fib_test_pref();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008728 res += fib_test_label();
8729 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008730
8731 /*
8732 * fib-walk process must be disabled in order for the walk tests to work
8733 */
8734 fib_walk_process_disable();
8735 res += fib_test_walk();
8736 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008737 }
8738
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008739 if (res)
8740 {
8741 return clib_error_return(0, "FIB Unit Test Failed");
8742 }
8743 else
8744 {
8745 return (NULL);
8746 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008747}
8748
8749VLIB_CLI_COMMAND (test_fib_command, static) = {
8750 .path = "test fib",
8751 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8752 .function = fib_test,
8753};
8754
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008755clib_error_t *
8756fib_test_init (vlib_main_t *vm)
8757{
8758 return 0;
8759}
8760
8761VLIB_INIT_FUNCTION (fib_test_init);