blob: d3bdfa35c06b5c94c5642675b64ebc7e8cdebde3 [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),
607 "bucket %d stacks on lb %d",
608 bucket,
609 exp->lb.lb);
610 break;
611 case FT_LB_SPECIAL:
612 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
613 "bucket %d stacks on %U",
614 bucket,
615 format_dpo_type, dpo->dpoi_type);
616 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
617 "bucket %d stacks on drop %d",
618 bucket,
619 exp->special.adj);
620 break;
621 }
622 }
623 return (!0);
624}
625
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800626int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000627fib_test_validate_entry (fib_node_index_t fei,
628 fib_forward_chain_type_t fct,
629 u16 n_buckets,
630 ...)
631{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000632 dpo_id_t dpo = DPO_INVALID;
633 fib_prefix_t pfx;
634 index_t fw_lbi;
635 u32 fib_index;
636 va_list ap;
637 int res;
638
639 va_start(ap, n_buckets);
640
641 fib_entry_get_prefix(fei, &pfx);
642 fib_index = fib_entry_get_fib_index(fei);
643 fib_entry_contribute_forwarding(fei, fct, &dpo);
644
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800645 if (DPO_REPLICATE == dpo.dpoi_type)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000646 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800647 const replicate_t *rep;
648
649 rep = replicate_get(dpo.dpoi_index);
650 res = fib_test_validate_rep_v(rep, n_buckets, ap);
651 }
652 else
653 {
654 const load_balance_t *lb;
655
656 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
657 "Entry links to %U",
658 format_dpo_type, dpo.dpoi_type);
659
660 lb = load_balance_get(dpo.dpoi_index);
661 res = fib_test_validate_lb_v(lb, n_buckets, ap);
662
663 /*
664 * ensure that the LB contributed by the entry is the
665 * same as the LB in the forwarding tables
666 */
667 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Rannsad422ed2016-11-02 14:20:04 +0000668 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800669 switch (pfx.fp_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000670 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800671 case FIB_PROTOCOL_IP4:
672 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
Neale Rannsad422ed2016-11-02 14:20:04 +0000673 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800674 case FIB_PROTOCOL_IP6:
675 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
676 break;
677 case FIB_PROTOCOL_MPLS:
678 {
679 mpls_unicast_header_t hdr = {
680 .label_exp_s_ttl = 0,
681 };
682
683 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
684 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
685 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
686
687 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
688 break;
689 }
690 default:
691 fw_lbi = 0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000692 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800693 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
694 "Contributed LB = FW LB: %U\n %U",
695 format_load_balance, fw_lbi, 0,
696 format_load_balance, dpo.dpoi_index, 0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000697 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000698 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000699
700 dpo_reset(&dpo);
701
702 va_end(ap);
703
704 return (res);
705}
706
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000707static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100708fib_test_v4 (void)
709{
710 /*
711 * In the default table check for the presence and correct forwarding
712 * of the special entries
713 */
714 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
715 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
716 const ip_adjacency_t *adj;
717 const load_balance_t *lb;
718 test_main_t *tm;
719 u32 fib_index;
Neale Ranns994dab42017-04-18 12:56:45 -0700720 int lb_count;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100721 int ii;
722
723 /* via 10.10.10.1 */
724 ip46_address_t nh_10_10_10_1 = {
725 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
726 };
727 /* via 10.10.10.2 */
728 ip46_address_t nh_10_10_10_2 = {
729 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
730 };
731
Neale Rannsf12a83f2017-04-18 09:09:40 -0700732 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
733 pool_elts(load_balance_map_pool));
734
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100735 tm = &test_main;
736
Neale Ranns994dab42017-04-18 12:56:45 -0700737 /* record the nubmer of load-balances in use before we start */
738 lb_count = pool_elts(load_balance_pool);
739
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100740 /* Find or create FIB table 11 */
741 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
742
743 for (ii = 0; ii < 4; ii++)
744 {
745 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
746 }
747
748 fib_prefix_t pfx_0_0_0_0_s_0 = {
749 .fp_len = 0,
750 .fp_proto = FIB_PROTOCOL_IP4,
751 .fp_addr = {
752 .ip4 = {
753 {0}
754 },
755 },
756 };
757
758 fib_prefix_t pfx = {
759 .fp_len = 0,
760 .fp_proto = FIB_PROTOCOL_IP4,
761 .fp_addr = {
762 .ip4 = {
763 {0}
764 },
765 },
766 };
767
768 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
769
770 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
771 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
772 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
773 "Default route is DROP");
774
775 pfx.fp_len = 32;
776 fei = fib_table_lookup(fib_index, &pfx);
777 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
778 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
779 "all 0s route is DROP");
780
781 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
782 pfx.fp_len = 32;
783 fei = fib_table_lookup(fib_index, &pfx);
784 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
785 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
786 "all 1s route is DROP");
787
788 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
789 pfx.fp_len = 8;
790 fei = fib_table_lookup(fib_index, &pfx);
791 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
792 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
793 "all-mcast route is DROP");
794
795 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
796 pfx.fp_len = 8;
797 fei = fib_table_lookup(fib_index, &pfx);
798 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
799 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
800 "class-e route is DROP");
801
802 /*
803 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
804 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000805 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
806 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100807 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000808#define ENBR (5+5+2)
809#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100810 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000811 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100812 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000813 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100814 fib_entry_pool_size());
815
816 /*
817 * add interface routes.
818 * validate presence of /24 attached and /32 recieve.
819 * test for the presence of the receive address in the glean and local adj
820 */
821 fib_prefix_t local_pfx = {
822 .fp_len = 24,
823 .fp_proto = FIB_PROTOCOL_IP4,
824 .fp_addr = {
825 .ip4 = {
826 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
827 },
828 },
829 };
830
831 fib_table_entry_update_one_path(fib_index, &local_pfx,
832 FIB_SOURCE_INTERFACE,
833 (FIB_ENTRY_FLAG_CONNECTED |
834 FIB_ENTRY_FLAG_ATTACHED),
835 FIB_PROTOCOL_IP4,
836 NULL,
837 tm->hw[0]->sw_if_index,
838 ~0, // invalid fib index
839 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000840 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100841 FIB_ROUTE_PATH_FLAG_NONE);
842 fei = fib_table_lookup(fib_index, &local_pfx);
843 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
844 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
845 fib_entry_get_flags(fei)),
846 "Flags set on attached interface");
847
848 ai = fib_entry_get_adj(fei);
849 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
850 adj = adj_get(ai);
851 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
852 "attached interface adj is glean");
853 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
854 &adj->sub_type.glean.receive_addr)),
855 "attached interface adj is receive ok");
856
857 local_pfx.fp_len = 32;
858 fib_table_entry_update_one_path(fib_index, &local_pfx,
859 FIB_SOURCE_INTERFACE,
860 (FIB_ENTRY_FLAG_CONNECTED |
861 FIB_ENTRY_FLAG_LOCAL),
862 FIB_PROTOCOL_IP4,
863 NULL,
864 tm->hw[0]->sw_if_index,
865 ~0, // invalid fib index
866 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000867 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100868 FIB_ROUTE_PATH_FLAG_NONE);
869 fei = fib_table_lookup(fib_index, &local_pfx);
870 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
871 fib_entry_get_flags(fei)),
872 "Flags set on local interface");
873
874 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
875
876 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100877 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
878 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100879 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
880 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
881 "local interface adj is local");
882 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
883
884 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
885 &rd->rd_addr)),
886 "local interface adj is receive ok");
887
888 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
889 FIB_PROTOCOL_IP4,
890 FIB_SOURCE_INTERFACE)),
891 "2 Interface Source'd prefixes");
892
893 /*
894 * +2 interface routes +2 non-shared path-lists
895 */
896 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000897 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100898 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000899 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100900 fib_entry_pool_size());
901
902 /*
903 * Modify the default route to be via an adj not yet known.
904 * this sources the defalut route with the API source, which is
905 * a higher preference to the DEFAULT_ROUTE source
906 */
907 pfx.fp_addr.ip4.as_u32 = 0;
908 pfx.fp_len = 0;
909 fib_table_entry_path_add(fib_index, &pfx,
910 FIB_SOURCE_API,
911 FIB_ENTRY_FLAG_NONE,
912 FIB_PROTOCOL_IP4,
913 &nh_10_10_10_1,
914 tm->hw[0]->sw_if_index,
915 ~0, // invalid fib index
916 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000917 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100918 FIB_ROUTE_PATH_FLAG_NONE);
919 fei = fib_table_lookup(fib_index, &pfx);
920 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
921 "Flags set on API route");
922
923 FIB_TEST((fei == dfrt), "default route same index");
924 ai = fib_entry_get_adj(fei);
925 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
926 adj = adj_get(ai);
927 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
928 "adj is incomplete");
929 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
930 "adj nbr next-hop ok");
931 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
932 FIB_PROTOCOL_IP4,
933 FIB_SOURCE_API)),
934 "1 API Source'd prefixes");
935
936 /*
937 * find the adj in the shared db
938 */
939 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100940 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100941 &nh_10_10_10_1,
942 tm->hw[0]->sw_if_index);
943 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
944 adj_unlock(locked_ai);
945
946 /*
947 * +1 shared path-list
948 */
949 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
950 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000951 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100952 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000953 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100954 fib_entry_pool_size());
955
956 /*
957 * remove the API source from the default route. We expected
958 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
959 */
960 pfx.fp_addr.ip4.as_u32 = 0;
961 pfx.fp_len = 0;
962 fib_table_entry_path_remove(fib_index, &pfx,
963 FIB_SOURCE_API,
964 FIB_PROTOCOL_IP4,
965 &nh_10_10_10_1,
966 tm->hw[0]->sw_if_index,
967 ~0, // non-recursive path, so no FIB index
968 1,
969 FIB_ROUTE_PATH_FLAG_NONE);
970
971 fei = fib_table_lookup(fib_index, &pfx);
972
973 FIB_TEST((fei == dfrt), "default route same index");
974 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
975 "Default route is DROP");
976
977 /*
978 * -1 shared-path-list
979 */
980 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000981 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100982 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000983 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100984 fib_entry_pool_size());
985
986 /*
987 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
988 */
989 fib_prefix_t pfx_10_10_10_1_s_32 = {
990 .fp_len = 32,
991 .fp_proto = FIB_PROTOCOL_IP4,
992 .fp_addr = {
993 /* 10.10.10.1 */
994 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
995 },
996 };
997 fib_prefix_t pfx_10_10_10_2_s_32 = {
998 .fp_len = 32,
999 .fp_proto = FIB_PROTOCOL_IP4,
1000 .fp_addr = {
1001 /* 10.10.10.2 */
1002 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1003 },
1004 };
1005 fib_prefix_t pfx_11_11_11_11_s_32 = {
1006 .fp_len = 32,
1007 .fp_proto = FIB_PROTOCOL_IP4,
1008 .fp_addr = {
1009 /* 11.11.11.11 */
1010 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1011 },
1012 };
1013 u8 eth_addr[] = {
1014 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1015 };
Neale Rannsb80c5362016-10-08 13:03:40 +01001016
Neale Ranns3ee44042016-10-03 13:05:48 +01001017 ip46_address_t nh_12_12_12_12 = {
1018 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1019 };
1020 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001021
1022 /*
1023 * Add a route via an incomplete ADJ. then complete the ADJ
1024 * Expect the route LB is updated to use complete adj type.
1025 */
1026 fei = fib_table_entry_update_one_path(fib_index,
1027 &pfx_11_11_11_11_s_32,
1028 FIB_SOURCE_API,
1029 FIB_ENTRY_FLAG_ATTACHED,
1030 FIB_PROTOCOL_IP4,
1031 &pfx_10_10_10_1_s_32.fp_addr,
1032 tm->hw[0]->sw_if_index,
1033 ~0, // invalid fib index
1034 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001035 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001036 FIB_ROUTE_PATH_FLAG_NONE);
1037
1038 dpo = fib_entry_contribute_ip_forwarding(fei);
1039 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1040 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1041 "11.11.11.11/32 via incomplete adj");
1042
1043 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001044 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001045 &pfx_10_10_10_1_s_32.fp_addr,
1046 tm->hw[0]->sw_if_index);
1047 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1048 adj = adj_get(ai_01);
1049 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1050 "adj is incomplete");
1051 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1052 &adj->sub_type.nbr.next_hop)),
1053 "adj nbr next-hop ok");
1054
Neale Rannsb80c5362016-10-08 13:03:40 +01001055 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1056 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001057 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1058 "adj is complete");
1059 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1060 &adj->sub_type.nbr.next_hop)),
1061 "adj nbr next-hop ok");
1062 ai = fib_entry_get_adj(fei);
1063 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1064
1065 dpo = fib_entry_contribute_ip_forwarding(fei);
1066 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1067 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1068 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001069 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1070 tm->hw[0]->sw_if_index),
1071 "RPF list for adj-fib contains adj");
1072
1073 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001074 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001075 &nh_12_12_12_12,
1076 tm->hw[1]->sw_if_index);
1077 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1078 adj = adj_get(ai_12_12_12_12);
1079 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1080 "adj is incomplete");
1081 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1082 &adj->sub_type.nbr.next_hop)),
1083 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001084 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1085 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001086 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1087 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001088
1089 /*
1090 * add the adj fib
1091 */
1092 fei = fib_table_entry_update_one_path(fib_index,
1093 &pfx_10_10_10_1_s_32,
1094 FIB_SOURCE_ADJ,
1095 FIB_ENTRY_FLAG_ATTACHED,
1096 FIB_PROTOCOL_IP4,
1097 &pfx_10_10_10_1_s_32.fp_addr,
1098 tm->hw[0]->sw_if_index,
1099 ~0, // invalid fib index
1100 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001101 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001102 FIB_ROUTE_PATH_FLAG_NONE);
1103 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1104 "Flags set on adj-fib");
1105 ai = fib_entry_get_adj(fei);
1106 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1107
1108 fib_table_entry_path_remove(fib_index,
1109 &pfx_11_11_11_11_s_32,
1110 FIB_SOURCE_API,
1111 FIB_PROTOCOL_IP4,
1112 &pfx_10_10_10_1_s_32.fp_addr,
1113 tm->hw[0]->sw_if_index,
1114 ~0, // invalid fib index
1115 1,
1116 FIB_ROUTE_PATH_FLAG_NONE);
1117
1118 eth_addr[5] = 0xb2;
1119
1120 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001121 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001122 &pfx_10_10_10_2_s_32.fp_addr,
1123 tm->hw[0]->sw_if_index);
1124 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1125 adj = adj_get(ai_02);
1126 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1127 "adj is incomplete");
1128 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1129 &adj->sub_type.nbr.next_hop)),
1130 "adj nbr next-hop ok");
1131
Neale Rannsb80c5362016-10-08 13:03:40 +01001132 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1133 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001134 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1135 "adj is complete");
1136 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1137 &adj->sub_type.nbr.next_hop)),
1138 "adj nbr next-hop ok");
1139 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1140
1141 fib_table_entry_update_one_path(fib_index,
1142 &pfx_10_10_10_2_s_32,
1143 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00001144 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001145 FIB_PROTOCOL_IP4,
1146 &pfx_10_10_10_2_s_32.fp_addr,
1147 tm->hw[0]->sw_if_index,
1148 ~0, // invalid fib index
1149 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001150 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001151 FIB_ROUTE_PATH_FLAG_NONE);
1152
1153 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1154 ai = fib_entry_get_adj(fei);
1155 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1156
1157 /*
1158 * +2 adj-fibs, and their non-shared path-lists
1159 */
1160 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001161 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001162 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001163 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001164 fib_entry_pool_size());
1165
1166 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001167 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001168 */
1169 fib_prefix_t pfx_1_1_1_1_s_32 = {
1170 .fp_len = 32,
1171 .fp_proto = FIB_PROTOCOL_IP4,
1172 .fp_addr = {
1173 /* 1.1.1.1/32 */
1174 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1175 },
1176 };
1177
1178 fib_table_entry_path_add(fib_index,
1179 &pfx_1_1_1_1_s_32,
1180 FIB_SOURCE_API,
1181 FIB_ENTRY_FLAG_NONE,
1182 FIB_PROTOCOL_IP4,
1183 &nh_10_10_10_1,
1184 tm->hw[0]->sw_if_index,
1185 ~0, // invalid fib index
1186 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001187 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001188 FIB_ROUTE_PATH_FLAG_NONE);
1189 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1190 ai = fib_entry_get_adj(fei);
1191 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1192
1193 /*
1194 * +1 entry and a shared path-list
1195 */
1196 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001197 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001198 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001199 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001200 fib_entry_pool_size());
1201
1202 /* 1.1.2.0/24 */
1203 fib_prefix_t pfx_1_1_2_0_s_24 = {
1204 .fp_len = 24,
1205 .fp_proto = FIB_PROTOCOL_IP4,
1206 .fp_addr = {
1207 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1208 }
1209 };
1210
1211 fib_table_entry_path_add(fib_index,
1212 &pfx_1_1_2_0_s_24,
1213 FIB_SOURCE_API,
1214 FIB_ENTRY_FLAG_NONE,
1215 FIB_PROTOCOL_IP4,
1216 &nh_10_10_10_1,
1217 tm->hw[0]->sw_if_index,
1218 ~0, // invalid fib index
1219 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001220 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001221 FIB_ROUTE_PATH_FLAG_NONE);
1222 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1223 ai = fib_entry_get_adj(fei);
1224 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1225
1226 /*
1227 * +1 entry only
1228 */
1229 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001230 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001231 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001232 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001233 fib_entry_pool_size());
1234
1235 /*
1236 * modify 1.1.2.0/24 to use multipath.
1237 */
1238 fib_table_entry_path_add(fib_index,
1239 &pfx_1_1_2_0_s_24,
1240 FIB_SOURCE_API,
1241 FIB_ENTRY_FLAG_NONE,
1242 FIB_PROTOCOL_IP4,
1243 &nh_10_10_10_2,
1244 tm->hw[0]->sw_if_index,
1245 ~0, // invalid fib index
1246 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001247 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001248 FIB_ROUTE_PATH_FLAG_NONE);
1249 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1250 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001251 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1252 1, tm->hw[0]->sw_if_index),
1253 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001254
1255 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1256 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1257 FIB_TEST((ai_01 == dpo1->dpoi_index),
1258 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1259 ai_01, dpo1->dpoi_index);
1260
1261 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1262 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1263 FIB_TEST((ai_02 == dpo1->dpoi_index),
1264 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1265
1266 /*
1267 * +1 shared-pathlist
1268 */
1269 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001270 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001271 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001272 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001273 fib_entry_pool_size());
1274
1275 /*
1276 * revert the modify
1277 */
1278 fib_table_entry_path_remove(fib_index,
1279 &pfx_1_1_2_0_s_24,
1280 FIB_SOURCE_API,
1281 FIB_PROTOCOL_IP4,
1282 &nh_10_10_10_2,
1283 tm->hw[0]->sw_if_index,
1284 ~0,
1285 1,
1286 FIB_ROUTE_PATH_FLAG_NONE);
1287 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001288 dpo = fib_entry_contribute_ip_forwarding(fei);
1289 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1290 1, tm->hw[0]->sw_if_index),
1291 "RPF list for 1.1.2.0/24 contains one adj");
1292
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001293 ai = fib_entry_get_adj(fei);
1294 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1295
1296 /*
1297 * +1 shared-pathlist
1298 */
1299 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1300 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001301 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001302 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001303 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001304 fib_entry_pool_size());
1305
1306 /*
1307 * Add 2 recursive routes:
1308 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1309 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1310 */
1311 fib_prefix_t bgp_100_pfx = {
1312 .fp_len = 32,
1313 .fp_proto = FIB_PROTOCOL_IP4,
1314 .fp_addr = {
1315 /* 100.100.100.100/32 */
1316 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1317 },
1318 };
1319 /* via 1.1.1.1 */
1320 ip46_address_t nh_1_1_1_1 = {
1321 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1322 };
1323
Neale Ranns3ee44042016-10-03 13:05:48 +01001324 fei = fib_table_entry_path_add(fib_index,
1325 &bgp_100_pfx,
1326 FIB_SOURCE_API,
1327 FIB_ENTRY_FLAG_NONE,
1328 FIB_PROTOCOL_IP4,
1329 &nh_1_1_1_1,
1330 ~0, // no index provided.
1331 fib_index, // nexthop in same fib as route
1332 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001333 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001334 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001335
Neale Ranns3ee44042016-10-03 13:05:48 +01001336 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1337 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1338 tm->hw[0]->sw_if_index),
1339 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001340
1341 /*
1342 * +1 entry and +1 shared-path-list
1343 */
1344 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1345 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001346 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001347 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001348 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001349 fib_entry_pool_size());
1350
1351 fib_prefix_t bgp_101_pfx = {
1352 .fp_len = 32,
1353 .fp_proto = FIB_PROTOCOL_IP4,
1354 .fp_addr = {
1355 /* 100.100.100.101/32 */
1356 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1357 },
1358 };
1359
1360 fib_table_entry_path_add(fib_index,
1361 &bgp_101_pfx,
1362 FIB_SOURCE_API,
1363 FIB_ENTRY_FLAG_NONE,
1364 FIB_PROTOCOL_IP4,
1365 &nh_1_1_1_1,
1366 ~0, // no index provided.
1367 fib_index, // nexthop in same fib as route
1368 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001369 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001370 FIB_ROUTE_PATH_FLAG_NONE);
1371
Neale Ranns3ee44042016-10-03 13:05:48 +01001372 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1373 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1374 tm->hw[0]->sw_if_index),
1375 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001376
1377 /*
1378 * +1 entry, but the recursive path-list is shared.
1379 */
1380 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1381 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001382 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001383 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001384 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001385 fib_entry_pool_size());
1386
1387 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001388 * An special route; one where the user (me) provides the
1389 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001390 */
1391 fib_prefix_t ex_pfx = {
1392 .fp_len = 32,
1393 .fp_proto = FIB_PROTOCOL_IP4,
1394 .fp_addr = {
1395 /* 4.4.4.4/32 */
1396 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1397 },
1398 };
1399
1400 fib_table_entry_special_add(fib_index,
1401 &ex_pfx,
1402 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001403 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001404 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001405 dpo = fib_entry_contribute_ip_forwarding(fei);
1406 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1407 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1408 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001409
1410 fib_table_entry_special_remove(fib_index,
1411 &ex_pfx,
1412 FIB_SOURCE_SPECIAL);
1413 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1414 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1415 "Exclusive reoute removed");
1416
1417 /*
1418 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1419 * adjacency through which the route will resovle
1420 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001421 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001422
1423 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1424 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001425 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001426 LOOKUP_INPUT_DST_ADDR,
1427 LOOKUP_TABLE_FROM_CONFIG,
1428 &ex_dpo);
1429
1430 fib_table_entry_special_dpo_add(fib_index,
1431 &ex_pfx,
1432 FIB_SOURCE_SPECIAL,
1433 FIB_ENTRY_FLAG_EXCLUSIVE,
1434 &ex_dpo);
1435 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1436 dpo = fib_entry_contribute_ip_forwarding(fei);
1437 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1438 "exclusive remote uses lookup DPO");
1439
Neale Ranns948e00f2016-10-20 13:39:34 +01001440 /*
1441 * update the exclusive to use a different DPO
1442 */
Neale Ranns450cd302016-11-09 17:49:42 +00001443 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001444 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1445 &ex_dpo);
1446 fib_table_entry_special_dpo_update(fib_index,
1447 &ex_pfx,
1448 FIB_SOURCE_SPECIAL,
1449 FIB_ENTRY_FLAG_EXCLUSIVE,
1450 &ex_dpo);
1451 dpo = fib_entry_contribute_ip_forwarding(fei);
1452 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1453 "exclusive remote uses now uses NULL DPO");
1454
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001455 fib_table_entry_special_remove(fib_index,
1456 &ex_pfx,
1457 FIB_SOURCE_SPECIAL);
1458 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1459 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1460 "Exclusive reoute removed");
1461 dpo_reset(&ex_dpo);
1462
1463 /*
1464 * Add a recursive route:
1465 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1466 */
1467 fib_prefix_t bgp_200_pfx = {
1468 .fp_len = 32,
1469 .fp_proto = FIB_PROTOCOL_IP4,
1470 .fp_addr = {
1471 /* 200.200.200.200/32 */
1472 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1473 },
1474 };
1475 /* via 1.1.1.2 */
1476 fib_prefix_t pfx_1_1_1_2_s_32 = {
1477 .fp_len = 32,
1478 .fp_proto = FIB_PROTOCOL_IP4,
1479 .fp_addr = {
1480 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1481 },
1482 };
1483
1484 fib_table_entry_path_add(fib_index,
1485 &bgp_200_pfx,
1486 FIB_SOURCE_API,
1487 FIB_ENTRY_FLAG_NONE,
1488 FIB_PROTOCOL_IP4,
1489 &pfx_1_1_1_2_s_32.fp_addr,
1490 ~0, // no index provided.
1491 fib_index, // nexthop in same fib as route
1492 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001493 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001494 FIB_ROUTE_PATH_FLAG_NONE);
1495
Neale Ranns3ee44042016-10-03 13:05:48 +01001496 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001497
1498 /*
1499 * the adj should be recursive via drop, since the route resolves via
1500 * the default route, which is itself a DROP
1501 */
1502 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1503 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1504 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001505 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1506 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001507
1508 /*
1509 * +2 entry and +1 shared-path-list
1510 */
1511 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1512 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001513 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001514 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001515 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001516 fib_entry_pool_size());
1517
1518 /*
1519 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001520 * The paths are sort by NH first. in this case the the path with greater
1521 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001522 */
1523 fib_prefix_t pfx_1_2_3_4_s_32 = {
1524 .fp_len = 32,
1525 .fp_proto = FIB_PROTOCOL_IP4,
1526 .fp_addr = {
1527 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1528 },
1529 };
1530 fib_table_entry_path_add(fib_index,
1531 &pfx_1_2_3_4_s_32,
1532 FIB_SOURCE_API,
1533 FIB_ENTRY_FLAG_NONE,
1534 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001535 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001536 tm->hw[0]->sw_if_index,
1537 ~0,
1538 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001539 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001540 FIB_ROUTE_PATH_FLAG_NONE);
1541 fei = fib_table_entry_path_add(fib_index,
1542 &pfx_1_2_3_4_s_32,
1543 FIB_SOURCE_API,
1544 FIB_ENTRY_FLAG_NONE,
1545 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001546 &nh_12_12_12_12,
1547 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001548 ~0,
1549 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001550 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001551 FIB_ROUTE_PATH_FLAG_NONE);
1552
1553 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1554 dpo = fib_entry_contribute_ip_forwarding(fei);
1555 lb = load_balance_get(dpo->dpoi_index);
1556 FIB_TEST((lb->lb_n_buckets == 4),
1557 "1.2.3.4/32 LB has %d bucket",
1558 lb->lb_n_buckets);
1559
Neale Ranns3ee44042016-10-03 13:05:48 +01001560 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1561 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1562 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1563 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001564
Neale Ranns3ee44042016-10-03 13:05:48 +01001565 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1566 tm->hw[0]->sw_if_index,
1567 tm->hw[1]->sw_if_index),
1568 "RPF list for 1.2.3.4/32 contains both adjs");
1569
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001570
1571 /*
1572 * Unequal Cost load-balance. 4:1 ratio.
1573 * fits in a 16 bucket LB with ratio 13:3
1574 */
1575 fib_prefix_t pfx_1_2_3_5_s_32 = {
1576 .fp_len = 32,
1577 .fp_proto = FIB_PROTOCOL_IP4,
1578 .fp_addr = {
1579 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1580 },
1581 };
1582 fib_table_entry_path_add(fib_index,
1583 &pfx_1_2_3_5_s_32,
1584 FIB_SOURCE_API,
1585 FIB_ENTRY_FLAG_NONE,
1586 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001587 &nh_12_12_12_12,
1588 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001589 ~0,
1590 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001591 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001592 FIB_ROUTE_PATH_FLAG_NONE);
1593 fei = fib_table_entry_path_add(fib_index,
1594 &pfx_1_2_3_5_s_32,
1595 FIB_SOURCE_API,
1596 FIB_ENTRY_FLAG_NONE,
1597 FIB_PROTOCOL_IP4,
1598 &nh_10_10_10_1,
1599 tm->hw[0]->sw_if_index,
1600 ~0,
1601 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001602 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001603 FIB_ROUTE_PATH_FLAG_NONE);
1604
1605 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1606 dpo = fib_entry_contribute_ip_forwarding(fei);
1607 lb = load_balance_get(dpo->dpoi_index);
1608 FIB_TEST((lb->lb_n_buckets == 16),
1609 "1.2.3.5/32 LB has %d bucket",
1610 lb->lb_n_buckets);
1611
1612 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1613 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1614 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1615 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1616 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1617 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1618 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1619 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1620 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1621 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1622 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1623 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1624 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001625 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1626 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1627 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1628
1629 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1630 tm->hw[0]->sw_if_index,
1631 tm->hw[1]->sw_if_index),
1632 "RPF list for 1.2.3.4/32 contains both adjs");
1633
1634 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001635 * Test UCMP with a large weight skew - this produces load-balance objects with large
1636 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1637 * laso testing the LB in placce modify code when number of buckets is large.
1638 */
1639 fib_prefix_t pfx_6_6_6_6_s_32 = {
1640 .fp_len = 32,
1641 .fp_proto = FIB_PROTOCOL_IP4,
1642 .fp_addr = {
1643 /* 1.1.1.1/32 */
1644 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1645 },
1646 };
1647 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
1648 .type = FT_LB_ADJ,
1649 .adj = {
1650 .adj = ai_01,
1651 },
1652 };
1653 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
1654 .type = FT_LB_ADJ,
1655 .adj = {
1656 .adj = ai_02,
1657 },
1658 };
1659 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1660 .type = FT_LB_ADJ,
1661 .adj = {
1662 .adj = ai_12_12_12_12,
1663 },
1664 };
1665 fib_table_entry_update_one_path(fib_index,
1666 &pfx_6_6_6_6_s_32,
1667 FIB_SOURCE_API,
1668 FIB_ENTRY_FLAG_NONE,
1669 FIB_PROTOCOL_IP4,
1670 &nh_10_10_10_1,
1671 tm->hw[0]->sw_if_index,
1672 ~0, // invalid fib index
1673 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001674 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001675 FIB_ROUTE_PATH_FLAG_NONE);
1676
1677 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1678 FIB_TEST(fib_test_validate_entry(fei,
1679 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1680 1,
1681 &ip_6_6_6_6_o_10_10_10_1),
1682 "6.6.6.6/32 via 10.10.10.1");
1683
1684 fib_table_entry_path_add(fib_index,
1685 &pfx_6_6_6_6_s_32,
1686 FIB_SOURCE_API,
1687 FIB_ENTRY_FLAG_NONE,
1688 FIB_PROTOCOL_IP4,
1689 &nh_10_10_10_2,
1690 tm->hw[0]->sw_if_index,
1691 ~0, // invalid fib index
1692 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001693 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001694 FIB_ROUTE_PATH_FLAG_NONE);
1695
1696 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1697 FIB_TEST(fib_test_validate_entry(fei,
1698 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1699 64,
1700 &ip_6_6_6_6_o_10_10_10_2,
1701 &ip_6_6_6_6_o_10_10_10_2,
1702 &ip_6_6_6_6_o_10_10_10_2,
1703 &ip_6_6_6_6_o_10_10_10_2,
1704 &ip_6_6_6_6_o_10_10_10_2,
1705 &ip_6_6_6_6_o_10_10_10_2,
1706 &ip_6_6_6_6_o_10_10_10_2,
1707 &ip_6_6_6_6_o_10_10_10_2,
1708 &ip_6_6_6_6_o_10_10_10_2,
1709 &ip_6_6_6_6_o_10_10_10_2,
1710 &ip_6_6_6_6_o_10_10_10_2,
1711 &ip_6_6_6_6_o_10_10_10_2,
1712 &ip_6_6_6_6_o_10_10_10_2,
1713 &ip_6_6_6_6_o_10_10_10_2,
1714 &ip_6_6_6_6_o_10_10_10_2,
1715 &ip_6_6_6_6_o_10_10_10_2,
1716 &ip_6_6_6_6_o_10_10_10_2,
1717 &ip_6_6_6_6_o_10_10_10_2,
1718 &ip_6_6_6_6_o_10_10_10_2,
1719 &ip_6_6_6_6_o_10_10_10_2,
1720 &ip_6_6_6_6_o_10_10_10_2,
1721 &ip_6_6_6_6_o_10_10_10_2,
1722 &ip_6_6_6_6_o_10_10_10_2,
1723 &ip_6_6_6_6_o_10_10_10_2,
1724 &ip_6_6_6_6_o_10_10_10_2,
1725 &ip_6_6_6_6_o_10_10_10_2,
1726 &ip_6_6_6_6_o_10_10_10_2,
1727 &ip_6_6_6_6_o_10_10_10_2,
1728 &ip_6_6_6_6_o_10_10_10_2,
1729 &ip_6_6_6_6_o_10_10_10_2,
1730 &ip_6_6_6_6_o_10_10_10_2,
1731 &ip_6_6_6_6_o_10_10_10_2,
1732 &ip_6_6_6_6_o_10_10_10_2,
1733 &ip_6_6_6_6_o_10_10_10_2,
1734 &ip_6_6_6_6_o_10_10_10_2,
1735 &ip_6_6_6_6_o_10_10_10_2,
1736 &ip_6_6_6_6_o_10_10_10_2,
1737 &ip_6_6_6_6_o_10_10_10_2,
1738 &ip_6_6_6_6_o_10_10_10_2,
1739 &ip_6_6_6_6_o_10_10_10_2,
1740 &ip_6_6_6_6_o_10_10_10_2,
1741 &ip_6_6_6_6_o_10_10_10_2,
1742 &ip_6_6_6_6_o_10_10_10_2,
1743 &ip_6_6_6_6_o_10_10_10_2,
1744 &ip_6_6_6_6_o_10_10_10_2,
1745 &ip_6_6_6_6_o_10_10_10_2,
1746 &ip_6_6_6_6_o_10_10_10_2,
1747 &ip_6_6_6_6_o_10_10_10_2,
1748 &ip_6_6_6_6_o_10_10_10_2,
1749 &ip_6_6_6_6_o_10_10_10_2,
1750 &ip_6_6_6_6_o_10_10_10_2,
1751 &ip_6_6_6_6_o_10_10_10_2,
1752 &ip_6_6_6_6_o_10_10_10_2,
1753 &ip_6_6_6_6_o_10_10_10_2,
1754 &ip_6_6_6_6_o_10_10_10_2,
1755 &ip_6_6_6_6_o_10_10_10_2,
1756 &ip_6_6_6_6_o_10_10_10_2,
1757 &ip_6_6_6_6_o_10_10_10_2,
1758 &ip_6_6_6_6_o_10_10_10_2,
1759 &ip_6_6_6_6_o_10_10_10_2,
1760 &ip_6_6_6_6_o_10_10_10_2,
1761 &ip_6_6_6_6_o_10_10_10_2,
1762 &ip_6_6_6_6_o_10_10_10_2,
1763 &ip_6_6_6_6_o_10_10_10_1),
1764 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1765
1766 fib_table_entry_path_add(fib_index,
1767 &pfx_6_6_6_6_s_32,
1768 FIB_SOURCE_API,
1769 FIB_ENTRY_FLAG_NONE,
1770 FIB_PROTOCOL_IP4,
1771 &nh_12_12_12_12,
1772 tm->hw[1]->sw_if_index,
1773 ~0, // invalid fib index
1774 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001775 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001776 FIB_ROUTE_PATH_FLAG_NONE);
1777
1778 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1779 FIB_TEST(fib_test_validate_entry(fei,
1780 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1781 128,
1782 &ip_6_6_6_6_o_10_10_10_1,
1783 &ip_6_6_6_6_o_10_10_10_2,
1784 &ip_6_6_6_6_o_10_10_10_2,
1785 &ip_6_6_6_6_o_10_10_10_2,
1786 &ip_6_6_6_6_o_10_10_10_2,
1787 &ip_6_6_6_6_o_10_10_10_2,
1788 &ip_6_6_6_6_o_10_10_10_2,
1789 &ip_6_6_6_6_o_10_10_10_2,
1790 &ip_6_6_6_6_o_10_10_10_2,
1791 &ip_6_6_6_6_o_10_10_10_2,
1792 &ip_6_6_6_6_o_10_10_10_2,
1793 &ip_6_6_6_6_o_10_10_10_2,
1794 &ip_6_6_6_6_o_10_10_10_2,
1795 &ip_6_6_6_6_o_10_10_10_2,
1796 &ip_6_6_6_6_o_10_10_10_2,
1797 &ip_6_6_6_6_o_10_10_10_2,
1798 &ip_6_6_6_6_o_10_10_10_2,
1799 &ip_6_6_6_6_o_10_10_10_2,
1800 &ip_6_6_6_6_o_10_10_10_2,
1801 &ip_6_6_6_6_o_10_10_10_2,
1802 &ip_6_6_6_6_o_10_10_10_2,
1803 &ip_6_6_6_6_o_10_10_10_2,
1804 &ip_6_6_6_6_o_10_10_10_2,
1805 &ip_6_6_6_6_o_10_10_10_2,
1806 &ip_6_6_6_6_o_10_10_10_2,
1807 &ip_6_6_6_6_o_10_10_10_2,
1808 &ip_6_6_6_6_o_10_10_10_2,
1809 &ip_6_6_6_6_o_10_10_10_2,
1810 &ip_6_6_6_6_o_10_10_10_2,
1811 &ip_6_6_6_6_o_10_10_10_2,
1812 &ip_6_6_6_6_o_10_10_10_2,
1813 &ip_6_6_6_6_o_10_10_10_2,
1814 &ip_6_6_6_6_o_10_10_10_2,
1815 &ip_6_6_6_6_o_10_10_10_2,
1816 &ip_6_6_6_6_o_10_10_10_2,
1817 &ip_6_6_6_6_o_10_10_10_2,
1818 &ip_6_6_6_6_o_10_10_10_2,
1819 &ip_6_6_6_6_o_10_10_10_2,
1820 &ip_6_6_6_6_o_10_10_10_2,
1821 &ip_6_6_6_6_o_10_10_10_2,
1822 &ip_6_6_6_6_o_10_10_10_2,
1823 &ip_6_6_6_6_o_10_10_10_2,
1824 &ip_6_6_6_6_o_10_10_10_2,
1825 &ip_6_6_6_6_o_10_10_10_2,
1826 &ip_6_6_6_6_o_10_10_10_2,
1827 &ip_6_6_6_6_o_10_10_10_2,
1828 &ip_6_6_6_6_o_10_10_10_2,
1829 &ip_6_6_6_6_o_10_10_10_2,
1830 &ip_6_6_6_6_o_10_10_10_2,
1831 &ip_6_6_6_6_o_10_10_10_2,
1832 &ip_6_6_6_6_o_10_10_10_2,
1833 &ip_6_6_6_6_o_10_10_10_2,
1834 &ip_6_6_6_6_o_10_10_10_2,
1835 &ip_6_6_6_6_o_10_10_10_2,
1836 &ip_6_6_6_6_o_10_10_10_2,
1837 &ip_6_6_6_6_o_10_10_10_2,
1838 &ip_6_6_6_6_o_10_10_10_2,
1839 &ip_6_6_6_6_o_10_10_10_2,
1840 &ip_6_6_6_6_o_10_10_10_2,
1841 &ip_6_6_6_6_o_10_10_10_2,
1842 &ip_6_6_6_6_o_10_10_10_2,
1843 &ip_6_6_6_6_o_10_10_10_2,
1844 &ip_6_6_6_6_o_10_10_10_2,
1845 &ip_6_6_6_6_o_10_10_10_2,
1846 &ip_6_6_6_6_o_10_10_10_2,
1847 &ip_6_6_6_6_o_12_12_12_12,
1848 &ip_6_6_6_6_o_12_12_12_12,
1849 &ip_6_6_6_6_o_12_12_12_12,
1850 &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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1911
1912 fib_table_entry_path_remove(fib_index,
1913 &pfx_6_6_6_6_s_32,
1914 FIB_SOURCE_API,
1915 FIB_PROTOCOL_IP4,
1916 &nh_12_12_12_12,
1917 tm->hw[1]->sw_if_index,
1918 ~0, // invalid fib index
1919 100,
1920 FIB_ROUTE_PATH_FLAG_NONE);
1921
1922 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1923 FIB_TEST(fib_test_validate_entry(fei,
1924 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1925 64,
1926 &ip_6_6_6_6_o_10_10_10_2,
1927 &ip_6_6_6_6_o_10_10_10_2,
1928 &ip_6_6_6_6_o_10_10_10_2,
1929 &ip_6_6_6_6_o_10_10_10_2,
1930 &ip_6_6_6_6_o_10_10_10_2,
1931 &ip_6_6_6_6_o_10_10_10_2,
1932 &ip_6_6_6_6_o_10_10_10_2,
1933 &ip_6_6_6_6_o_10_10_10_2,
1934 &ip_6_6_6_6_o_10_10_10_2,
1935 &ip_6_6_6_6_o_10_10_10_2,
1936 &ip_6_6_6_6_o_10_10_10_2,
1937 &ip_6_6_6_6_o_10_10_10_2,
1938 &ip_6_6_6_6_o_10_10_10_2,
1939 &ip_6_6_6_6_o_10_10_10_2,
1940 &ip_6_6_6_6_o_10_10_10_2,
1941 &ip_6_6_6_6_o_10_10_10_2,
1942 &ip_6_6_6_6_o_10_10_10_2,
1943 &ip_6_6_6_6_o_10_10_10_2,
1944 &ip_6_6_6_6_o_10_10_10_2,
1945 &ip_6_6_6_6_o_10_10_10_2,
1946 &ip_6_6_6_6_o_10_10_10_2,
1947 &ip_6_6_6_6_o_10_10_10_2,
1948 &ip_6_6_6_6_o_10_10_10_2,
1949 &ip_6_6_6_6_o_10_10_10_2,
1950 &ip_6_6_6_6_o_10_10_10_2,
1951 &ip_6_6_6_6_o_10_10_10_2,
1952 &ip_6_6_6_6_o_10_10_10_2,
1953 &ip_6_6_6_6_o_10_10_10_2,
1954 &ip_6_6_6_6_o_10_10_10_2,
1955 &ip_6_6_6_6_o_10_10_10_2,
1956 &ip_6_6_6_6_o_10_10_10_2,
1957 &ip_6_6_6_6_o_10_10_10_2,
1958 &ip_6_6_6_6_o_10_10_10_2,
1959 &ip_6_6_6_6_o_10_10_10_2,
1960 &ip_6_6_6_6_o_10_10_10_2,
1961 &ip_6_6_6_6_o_10_10_10_2,
1962 &ip_6_6_6_6_o_10_10_10_2,
1963 &ip_6_6_6_6_o_10_10_10_2,
1964 &ip_6_6_6_6_o_10_10_10_2,
1965 &ip_6_6_6_6_o_10_10_10_2,
1966 &ip_6_6_6_6_o_10_10_10_2,
1967 &ip_6_6_6_6_o_10_10_10_2,
1968 &ip_6_6_6_6_o_10_10_10_2,
1969 &ip_6_6_6_6_o_10_10_10_2,
1970 &ip_6_6_6_6_o_10_10_10_2,
1971 &ip_6_6_6_6_o_10_10_10_2,
1972 &ip_6_6_6_6_o_10_10_10_2,
1973 &ip_6_6_6_6_o_10_10_10_2,
1974 &ip_6_6_6_6_o_10_10_10_2,
1975 &ip_6_6_6_6_o_10_10_10_2,
1976 &ip_6_6_6_6_o_10_10_10_2,
1977 &ip_6_6_6_6_o_10_10_10_2,
1978 &ip_6_6_6_6_o_10_10_10_2,
1979 &ip_6_6_6_6_o_10_10_10_2,
1980 &ip_6_6_6_6_o_10_10_10_2,
1981 &ip_6_6_6_6_o_10_10_10_2,
1982 &ip_6_6_6_6_o_10_10_10_2,
1983 &ip_6_6_6_6_o_10_10_10_2,
1984 &ip_6_6_6_6_o_10_10_10_2,
1985 &ip_6_6_6_6_o_10_10_10_2,
1986 &ip_6_6_6_6_o_10_10_10_2,
1987 &ip_6_6_6_6_o_10_10_10_2,
1988 &ip_6_6_6_6_o_10_10_10_2,
1989 &ip_6_6_6_6_o_10_10_10_1),
1990 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1991
1992 fib_table_entry_path_remove(fib_index,
1993 &pfx_6_6_6_6_s_32,
1994 FIB_SOURCE_API,
1995 FIB_PROTOCOL_IP4,
1996 &nh_10_10_10_2,
1997 tm->hw[0]->sw_if_index,
1998 ~0, // invalid fib index
1999 100,
2000 FIB_ROUTE_PATH_FLAG_NONE);
2001
2002 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2003 FIB_TEST(fib_test_validate_entry(fei,
2004 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2005 1,
2006 &ip_6_6_6_6_o_10_10_10_1),
2007 "6.6.6.6/32 via 10.10.10.1");
2008
2009 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2010
2011 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01002012 * A recursive via the two unequal cost entries
2013 */
2014 fib_prefix_t bgp_44_s_32 = {
2015 .fp_len = 32,
2016 .fp_proto = FIB_PROTOCOL_IP4,
2017 .fp_addr = {
2018 /* 200.200.200.201/32 */
2019 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2020 },
2021 };
2022 fei = fib_table_entry_path_add(fib_index,
2023 &bgp_44_s_32,
2024 FIB_SOURCE_API,
2025 FIB_ENTRY_FLAG_NONE,
2026 FIB_PROTOCOL_IP4,
2027 &pfx_1_2_3_4_s_32.fp_addr,
2028 ~0,
2029 fib_index,
2030 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002031 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002032 FIB_ROUTE_PATH_FLAG_NONE);
2033 fei = fib_table_entry_path_add(fib_index,
2034 &bgp_44_s_32,
2035 FIB_SOURCE_API,
2036 FIB_ENTRY_FLAG_NONE,
2037 FIB_PROTOCOL_IP4,
2038 &pfx_1_2_3_5_s_32.fp_addr,
2039 ~0,
2040 fib_index,
2041 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002042 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002043 FIB_ROUTE_PATH_FLAG_NONE);
2044
2045 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2046 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2047 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2048 tm->hw[0]->sw_if_index,
2049 tm->hw[1]->sw_if_index),
2050 "RPF list for 1.2.3.4/32 contains both adjs");
2051
2052 /*
2053 * test the uRPF check functions
2054 */
Neale Ranns948e00f2016-10-20 13:39:34 +01002055 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01002056 index_t urpfi;
2057
2058 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2059 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2060
2061 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2062 "uRPF check for 68.68.68.68/32 on %d OK",
2063 tm->hw[0]->sw_if_index);
2064 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2065 "uRPF check for 68.68.68.68/32 on %d OK",
2066 tm->hw[1]->sw_if_index);
2067 FIB_TEST(!fib_urpf_check(urpfi, 99),
2068 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2069 99);
2070 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002071
2072 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002073 &bgp_44_s_32,
2074 FIB_SOURCE_API);
2075 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002076 &pfx_1_2_3_5_s_32,
2077 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002078 fib_table_entry_delete(fib_index,
2079 &pfx_1_2_3_4_s_32,
2080 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002081
2082 /*
2083 * Add a recursive route:
2084 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2085 */
2086 fib_prefix_t bgp_201_pfx = {
2087 .fp_len = 32,
2088 .fp_proto = FIB_PROTOCOL_IP4,
2089 .fp_addr = {
2090 /* 200.200.200.201/32 */
2091 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2092 },
2093 };
2094 /* via 1.1.1.200 */
2095 fib_prefix_t pfx_1_1_1_200_s_32 = {
2096 .fp_len = 32,
2097 .fp_proto = FIB_PROTOCOL_IP4,
2098 .fp_addr = {
2099 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2100 },
2101 };
2102
2103 fib_table_entry_path_add(fib_index,
2104 &bgp_201_pfx,
2105 FIB_SOURCE_API,
2106 FIB_ENTRY_FLAG_NONE,
2107 FIB_PROTOCOL_IP4,
2108 &pfx_1_1_1_200_s_32.fp_addr,
2109 ~0, // no index provided.
2110 fib_index, // nexthop in same fib as route
2111 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002112 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002113 FIB_ROUTE_PATH_FLAG_NONE);
2114
Neale Ranns3ee44042016-10-03 13:05:48 +01002115 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002116
2117 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2118 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2119 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002120 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2121 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002122
2123 /*
2124 * +2 entry (BGP & RR) and +1 shared-path-list
2125 */
2126 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2127 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002128 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002129 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002130 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002131 fib_entry_pool_size());
2132
2133 /*
2134 * insert a route that covers the missing 1.1.1.2/32. we epxect
2135 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2136 */
2137 fib_prefix_t pfx_1_1_1_0_s_24 = {
2138 .fp_len = 24,
2139 .fp_proto = FIB_PROTOCOL_IP4,
2140 .fp_addr = {
2141 /* 1.1.1.0/24 */
2142 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2143 },
2144 };
2145
2146 fib_table_entry_path_add(fib_index,
2147 &pfx_1_1_1_0_s_24,
2148 FIB_SOURCE_API,
2149 FIB_ENTRY_FLAG_NONE,
2150 FIB_PROTOCOL_IP4,
2151 &nh_10_10_10_1,
2152 tm->hw[0]->sw_if_index,
2153 ~0, // invalid fib index
2154 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002155 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002156 FIB_ROUTE_PATH_FLAG_NONE);
2157 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2158 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2159 ai = fib_entry_get_adj(fei);
2160 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2161 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2162 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2163 ai = fib_entry_get_adj(fei);
2164 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2165 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_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.200/24 resolves via 10.10.10.1");
2169
2170 /*
2171 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2172 */
2173 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2174 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002175 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002176 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002177 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002178 fib_entry_pool_size());
2179
2180 /*
2181 * the recursive adj for 200.200.200.200 should be updated.
2182 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002183 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2184 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2185 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2186 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2187 tm->hw[0]->sw_if_index),
2188 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002189
2190 /*
2191 * insert a more specific route than 1.1.1.0/24 that also covers the
2192 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2193 * 200.200.200.200 to resolve through it.
2194 */
2195 fib_prefix_t pfx_1_1_1_0_s_28 = {
2196 .fp_len = 28,
2197 .fp_proto = FIB_PROTOCOL_IP4,
2198 .fp_addr = {
2199 /* 1.1.1.0/24 */
2200 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2201 },
2202 };
2203
2204 fib_table_entry_path_add(fib_index,
2205 &pfx_1_1_1_0_s_28,
2206 FIB_SOURCE_API,
2207 FIB_ENTRY_FLAG_NONE,
2208 FIB_PROTOCOL_IP4,
2209 &nh_10_10_10_2,
2210 tm->hw[0]->sw_if_index,
2211 ~0, // invalid fib index
2212 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002213 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002214 FIB_ROUTE_PATH_FLAG_NONE);
2215 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2216 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2217 ai = fib_entry_get_adj(fei);
2218 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2219
2220 /*
2221 * +1 entry. +1 shared path-list
2222 */
2223 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2224 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002225 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002226 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002227 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002228 fib_entry_pool_size());
2229
2230 /*
2231 * the recursive adj for 200.200.200.200 should be updated.
2232 * 200.200.200.201 remains unchanged.
2233 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002234 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2235 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002236
2237 /*
2238 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2239 */
2240 fib_table_entry_path_remove(fib_index,
2241 &pfx_1_1_1_0_s_28,
2242 FIB_SOURCE_API,
2243 FIB_PROTOCOL_IP4,
2244 &nh_10_10_10_2,
2245 tm->hw[0]->sw_if_index,
2246 ~0,
2247 1,
2248 FIB_ROUTE_PATH_FLAG_NONE);
2249 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2250 FIB_NODE_INDEX_INVALID),
2251 "1.1.1.0/28 removed");
2252 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2253 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2254 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002255 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2256 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002257
2258 /*
2259 * -1 entry. -1 shared path-list
2260 */
2261 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2262 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002263 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002264 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002265 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002266 fib_entry_pool_size());
2267
2268 /*
2269 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2270 */
2271 fib_table_entry_path_remove(fib_index,
2272 &pfx_1_1_1_0_s_24,
2273 FIB_SOURCE_API,
2274 FIB_PROTOCOL_IP4,
2275 &nh_10_10_10_1,
2276 tm->hw[0]->sw_if_index,
2277 ~0,
2278 1,
2279 FIB_ROUTE_PATH_FLAG_NONE);
2280 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2281 FIB_NODE_INDEX_INVALID),
2282 "1.1.1.0/24 removed");
2283
2284 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2285 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2286 "1.1.1.2/32 route is DROP");
2287 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2288 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2289 "1.1.1.200/32 route is DROP");
2290
Neale Ranns3ee44042016-10-03 13:05:48 +01002291 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2292 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002293
2294 /*
2295 * -1 entry
2296 */
2297 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2298 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002299 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002300 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002301 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002302 fib_entry_pool_size());
2303
2304 /*
2305 * insert the missing 1.1.1.2/32
2306 */
2307 fei = fib_table_entry_path_add(fib_index,
2308 &pfx_1_1_1_2_s_32,
2309 FIB_SOURCE_API,
2310 FIB_ENTRY_FLAG_NONE,
2311 FIB_PROTOCOL_IP4,
2312 &nh_10_10_10_1,
2313 tm->hw[0]->sw_if_index,
2314 ~0, // invalid fib index
2315 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002316 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002317 FIB_ROUTE_PATH_FLAG_NONE);
2318 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2319 ai = fib_entry_get_adj(fei);
2320 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2321
Neale Ranns3ee44042016-10-03 13:05:48 +01002322 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2323 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002324
2325 /*
2326 * no change. 1.1.1.2/32 was already there RR sourced.
2327 */
2328 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2329 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002330 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002331 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002332 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002333 fib_entry_pool_size());
2334
2335 /*
2336 * remove 200.200.200.201/32 which does not have a valid via FIB
2337 */
2338 fib_table_entry_path_remove(fib_index,
2339 &bgp_201_pfx,
2340 FIB_SOURCE_API,
2341 FIB_PROTOCOL_IP4,
2342 &pfx_1_1_1_200_s_32.fp_addr,
2343 ~0, // no index provided.
2344 fib_index,
2345 1,
2346 FIB_ROUTE_PATH_FLAG_NONE);
2347
2348 /*
2349 * -2 entries (BGP and RR). -1 shared path-list;
2350 */
2351 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2352 FIB_NODE_INDEX_INVALID),
2353 "200.200.200.201/32 removed");
2354 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2355 FIB_NODE_INDEX_INVALID),
2356 "1.1.1.200/32 removed");
2357
2358 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2359 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002360 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002361 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002362 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002363 fib_entry_pool_size());
2364
2365 /*
2366 * remove 200.200.200.200/32 which does have a valid via FIB
2367 */
2368 fib_table_entry_path_remove(fib_index,
2369 &bgp_200_pfx,
2370 FIB_SOURCE_API,
2371 FIB_PROTOCOL_IP4,
2372 &pfx_1_1_1_2_s_32.fp_addr,
2373 ~0, // no index provided.
2374 fib_index,
2375 1,
2376 FIB_ROUTE_PATH_FLAG_NONE);
2377
2378 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2379 FIB_NODE_INDEX_INVALID),
2380 "200.200.200.200/32 removed");
2381 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2382 FIB_NODE_INDEX_INVALID),
2383 "1.1.1.2/32 still present");
2384
2385 /*
2386 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2387 */
2388 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2389 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002390 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002391 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002392 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002393 fib_entry_pool_size());
2394
2395 /*
2396 * A recursive prefix that has a 2 path load-balance.
2397 * It also shares a next-hop with other BGP prefixes and hence
2398 * test the ref counting of RR sourced prefixes and 2 level LB.
2399 */
2400 const fib_prefix_t bgp_102 = {
2401 .fp_len = 32,
2402 .fp_proto = FIB_PROTOCOL_IP4,
2403 .fp_addr = {
2404 /* 100.100.100.101/32 */
2405 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2406 },
2407 };
2408 fib_table_entry_path_add(fib_index,
2409 &bgp_102,
2410 FIB_SOURCE_API,
2411 FIB_ENTRY_FLAG_NONE,
2412 FIB_PROTOCOL_IP4,
2413 &pfx_1_1_1_1_s_32.fp_addr,
2414 ~0, // no index provided.
2415 fib_index, // same as route
2416 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002417 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002418 FIB_ROUTE_PATH_FLAG_NONE);
2419 fib_table_entry_path_add(fib_index,
2420 &bgp_102,
2421 FIB_SOURCE_API,
2422 FIB_ENTRY_FLAG_NONE,
2423 FIB_PROTOCOL_IP4,
2424 &pfx_1_1_1_2_s_32.fp_addr,
2425 ~0, // no index provided.
2426 fib_index, // same as route's FIB
2427 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002428 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002429 FIB_ROUTE_PATH_FLAG_NONE);
2430 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2431 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2432 dpo = fib_entry_contribute_ip_forwarding(fei);
2433
2434 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2435 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2436 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2437 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2438
2439 lb = load_balance_get(dpo->dpoi_index);
2440 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2441 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2442 "First via 10.10.10.1");
2443 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2444 "Second via 10.10.10.1");
2445
2446 fib_table_entry_path_remove(fib_index,
2447 &bgp_102,
2448 FIB_SOURCE_API,
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's FIB
2453 1,
2454 FIB_ROUTE_PATH_FLAG_NONE);
2455 fib_table_entry_path_remove(fib_index,
2456 &bgp_102,
2457 FIB_SOURCE_API,
2458 FIB_PROTOCOL_IP4,
2459 &pfx_1_1_1_2_s_32.fp_addr,
2460 ~0, // no index provided.
2461 fib_index, // same as route's FIB
2462 1,
2463 FIB_ROUTE_PATH_FLAG_NONE);
2464 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2465 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2466
2467 /*
2468 * remove the remaining recursives
2469 */
2470 fib_table_entry_path_remove(fib_index,
2471 &bgp_100_pfx,
2472 FIB_SOURCE_API,
2473 FIB_PROTOCOL_IP4,
2474 &pfx_1_1_1_1_s_32.fp_addr,
2475 ~0, // no index provided.
2476 fib_index, // same as route's FIB
2477 1,
2478 FIB_ROUTE_PATH_FLAG_NONE);
2479 fib_table_entry_path_remove(fib_index,
2480 &bgp_101_pfx,
2481 FIB_SOURCE_API,
2482 FIB_PROTOCOL_IP4,
2483 &pfx_1_1_1_1_s_32.fp_addr,
2484 ~0, // no index provided.
2485 fib_index, // same as route's FIB
2486 1,
2487 FIB_ROUTE_PATH_FLAG_NONE);
2488 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2489 FIB_NODE_INDEX_INVALID),
2490 "100.100.100.100/32 removed");
2491 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2492 FIB_NODE_INDEX_INVALID),
2493 "100.100.100.101/32 removed");
2494
2495 /*
2496 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2497 */
2498 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2499 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002500 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002501 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002502 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002503 fib_entry_pool_size());
2504
2505 /*
2506 * Add a recursive route via a connected cover, using an adj-fib that does exist
2507 */
2508 fib_table_entry_path_add(fib_index,
2509 &bgp_200_pfx,
2510 FIB_SOURCE_API,
2511 FIB_ENTRY_FLAG_NONE,
2512 FIB_PROTOCOL_IP4,
2513 &nh_10_10_10_1,
2514 ~0, // no index provided.
2515 fib_index, // Same as route's FIB
2516 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002517 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002518 FIB_ROUTE_PATH_FLAG_NONE);
2519
2520 /*
2521 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2522 */
2523 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2524 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002525 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002526 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002527 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002528 fib_entry_pool_size());
2529
2530 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2531 dpo = fib_entry_contribute_ip_forwarding(fei);
2532
2533 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2534 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2535
2536 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2537 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2538
2539 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2540 "Flags set on RR via existing attached");
2541
2542 /*
2543 * Add a recursive route via a connected cover, using and adj-fib that does
2544 * not exist
2545 */
2546 ip46_address_t nh_10_10_10_3 = {
2547 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2548 };
2549 fib_prefix_t pfx_10_10_10_3 = {
2550 .fp_len = 32,
2551 .fp_proto = FIB_PROTOCOL_IP4,
2552 .fp_addr = nh_10_10_10_3,
2553 };
2554
2555 fib_table_entry_path_add(fib_index,
2556 &bgp_201_pfx,
2557 FIB_SOURCE_API,
2558 FIB_ENTRY_FLAG_NONE,
2559 FIB_PROTOCOL_IP4,
2560 &nh_10_10_10_3,
2561 ~0, // no index provided.
2562 fib_index,
2563 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002564 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002565 FIB_ROUTE_PATH_FLAG_NONE);
2566
2567 /*
2568 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2569 * one unshared non-recursive via 10.10.10.3
2570 */
2571 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2572 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002573 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002574 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002575 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002576 fib_entry_pool_size());
2577
2578 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002579 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002580 &nh_10_10_10_3,
2581 tm->hw[0]->sw_if_index);
2582
2583 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2584 dpo = fib_entry_contribute_ip_forwarding(fei);
2585 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2586 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2587
2588 ai = fib_entry_get_adj(fei);
2589 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2590 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2591 fib_entry_get_flags(fei)),
2592 "Flags set on RR via non-existing attached");
2593
2594 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2595 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2596
2597 adj_unlock(ai_03);
2598
2599 /*
2600 * remove the recursives
2601 */
2602 fib_table_entry_path_remove(fib_index,
2603 &bgp_200_pfx,
2604 FIB_SOURCE_API,
2605 FIB_PROTOCOL_IP4,
2606 &nh_10_10_10_1,
2607 ~0, // no index provided.
2608 fib_index, // same as route's FIB
2609 1,
2610 FIB_ROUTE_PATH_FLAG_NONE);
2611 fib_table_entry_path_remove(fib_index,
2612 &bgp_201_pfx,
2613 FIB_SOURCE_API,
2614 FIB_PROTOCOL_IP4,
2615 &nh_10_10_10_3,
2616 ~0, // no index provided.
2617 fib_index, // same as route's FIB
2618 1,
2619 FIB_ROUTE_PATH_FLAG_NONE);
2620
2621 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2622 FIB_NODE_INDEX_INVALID),
2623 "200.200.200.201/32 removed");
2624 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2625 FIB_NODE_INDEX_INVALID),
2626 "200.200.200.200/32 removed");
2627 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2628 FIB_NODE_INDEX_INVALID),
2629 "10.10.10.3/32 removed");
2630
2631 /*
2632 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2633 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2634 */
2635 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2636 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002637 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002638 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002639 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002640 fib_entry_pool_size());
2641
2642
2643 /*
2644 * RECURSION LOOPS
2645 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2646 */
2647 fib_prefix_t pfx_5_5_5_5_s_32 = {
2648 .fp_len = 32,
2649 .fp_proto = FIB_PROTOCOL_IP4,
2650 .fp_addr = {
2651 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2652 },
2653 };
2654 fib_prefix_t pfx_5_5_5_6_s_32 = {
2655 .fp_len = 32,
2656 .fp_proto = FIB_PROTOCOL_IP4,
2657 .fp_addr = {
2658 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2659 },
2660 };
2661 fib_prefix_t pfx_5_5_5_7_s_32 = {
2662 .fp_len = 32,
2663 .fp_proto = FIB_PROTOCOL_IP4,
2664 .fp_addr = {
2665 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2666 },
2667 };
2668
2669 fib_table_entry_path_add(fib_index,
2670 &pfx_5_5_5_5_s_32,
2671 FIB_SOURCE_API,
2672 FIB_ENTRY_FLAG_NONE,
2673 FIB_PROTOCOL_IP4,
2674 &pfx_5_5_5_6_s_32.fp_addr,
2675 ~0, // no index provided.
2676 fib_index,
2677 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002678 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002679 FIB_ROUTE_PATH_FLAG_NONE);
2680 fib_table_entry_path_add(fib_index,
2681 &pfx_5_5_5_6_s_32,
2682 FIB_SOURCE_API,
2683 FIB_ENTRY_FLAG_NONE,
2684 FIB_PROTOCOL_IP4,
2685 &pfx_5_5_5_7_s_32.fp_addr,
2686 ~0, // no index provided.
2687 fib_index,
2688 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002689 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002690 FIB_ROUTE_PATH_FLAG_NONE);
2691 fib_table_entry_path_add(fib_index,
2692 &pfx_5_5_5_7_s_32,
2693 FIB_SOURCE_API,
2694 FIB_ENTRY_FLAG_NONE,
2695 FIB_PROTOCOL_IP4,
2696 &pfx_5_5_5_5_s_32.fp_addr,
2697 ~0, // no index provided.
2698 fib_index,
2699 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002700 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002701 FIB_ROUTE_PATH_FLAG_NONE);
2702 /*
2703 * +3 entries, +3 shared path-list
2704 */
2705 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2706 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002707 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002708 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002709 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002710 fib_entry_pool_size());
2711
2712 /*
2713 * All the entries have only looped paths, so they are all drop
2714 */
2715 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2716 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2717 "LB for 5.5.5.7/32 is via adj for DROP");
2718 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2719 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2720 "LB for 5.5.5.5/32 is via adj for DROP");
2721 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2722 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2723 "LB for 5.5.5.6/32 is via adj for DROP");
2724
2725 /*
2726 * provide 5.5.5.6/32 with alternate path.
2727 * this will allow only 5.5.5.6/32 to forward with this path, the others
2728 * are still drop since the loop is still present.
2729 */
2730 fib_table_entry_path_add(fib_index,
2731 &pfx_5_5_5_6_s_32,
2732 FIB_SOURCE_API,
2733 FIB_ENTRY_FLAG_NONE,
2734 FIB_PROTOCOL_IP4,
2735 &nh_10_10_10_1,
2736 tm->hw[0]->sw_if_index,
2737 ~0,
2738 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002739 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002740 FIB_ROUTE_PATH_FLAG_NONE);
2741
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002742 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2743 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2744
2745 lb = load_balance_get(dpo1->dpoi_index);
2746 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2747
2748 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2749 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2750 FIB_TEST((ai_01 == dpo2->dpoi_index),
2751 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2752
2753 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2754 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2755 "LB for 5.5.5.7/32 is via adj for DROP");
2756 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2757 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2758 "LB for 5.5.5.5/32 is via adj for DROP");
2759
2760 /*
2761 * remove the alternate path for 5.5.5.6/32
2762 * back to all drop
2763 */
2764 fib_table_entry_path_remove(fib_index,
2765 &pfx_5_5_5_6_s_32,
2766 FIB_SOURCE_API,
2767 FIB_PROTOCOL_IP4,
2768 &nh_10_10_10_1,
2769 tm->hw[0]->sw_if_index,
2770 ~0,
2771 1,
2772 FIB_ROUTE_PATH_FLAG_NONE);
2773
2774 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2775 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2776 "LB for 5.5.5.7/32 is via adj for DROP");
2777 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2778 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2779 "LB for 5.5.5.5/32 is via adj for DROP");
2780 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2781 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2782 "LB for 5.5.5.6/32 is via adj for DROP");
2783
2784 /*
2785 * break the loop by giving 5.5.5.5/32 a new set of paths
2786 * expect all to forward via this new path.
2787 */
2788 fib_table_entry_update_one_path(fib_index,
2789 &pfx_5_5_5_5_s_32,
2790 FIB_SOURCE_API,
2791 FIB_ENTRY_FLAG_NONE,
2792 FIB_PROTOCOL_IP4,
2793 &nh_10_10_10_1,
2794 tm->hw[0]->sw_if_index,
2795 ~0, // invalid fib index
2796 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002797 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002798 FIB_ROUTE_PATH_FLAG_NONE);
2799
2800 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2801 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2802 lb = load_balance_get(dpo1->dpoi_index);
2803 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2804
2805 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2806 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2807 FIB_TEST((ai_01 == dpo2->dpoi_index),
2808 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2809
2810 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2811 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2812
2813 lb = load_balance_get(dpo2->dpoi_index);
2814 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2815 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2816 "5.5.5.5.7 via 5.5.5.5");
2817
2818 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2819 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2820
2821 lb = load_balance_get(dpo1->dpoi_index);
2822 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2823 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2824 "5.5.5.5.6 via 5.5.5.7");
2825
2826 /*
2827 * revert back to the loop. so we can remove the prefixes with
2828 * the loop intact
2829 */
2830 fib_table_entry_update_one_path(fib_index,
2831 &pfx_5_5_5_5_s_32,
2832 FIB_SOURCE_API,
2833 FIB_ENTRY_FLAG_NONE,
2834 FIB_PROTOCOL_IP4,
2835 &pfx_5_5_5_6_s_32.fp_addr,
2836 ~0, // no index provided.
2837 fib_index,
2838 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002839 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002840 FIB_ROUTE_PATH_FLAG_NONE);
2841
2842 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2843 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2844 "LB for 5.5.5.7/32 is via adj for DROP");
2845 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2846 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2847 "LB for 5.5.5.5/32 is via adj for DROP");
2848 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2849 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2850 "LB for 5.5.5.6/32 is via adj for DROP");
2851
2852 /*
2853 * remove all the 5.5.5.x/32 prefixes
2854 */
2855 fib_table_entry_path_remove(fib_index,
2856 &pfx_5_5_5_5_s_32,
2857 FIB_SOURCE_API,
2858 FIB_PROTOCOL_IP4,
2859 &pfx_5_5_5_6_s_32.fp_addr,
2860 ~0, // no index provided.
2861 fib_index, // same as route's FIB
2862 1,
2863 FIB_ROUTE_PATH_FLAG_NONE);
2864 fib_table_entry_path_remove(fib_index,
2865 &pfx_5_5_5_6_s_32,
2866 FIB_SOURCE_API,
2867 FIB_PROTOCOL_IP4,
2868 &pfx_5_5_5_7_s_32.fp_addr,
2869 ~0, // no index provided.
2870 fib_index, // same as route's FIB
2871 1,
2872 FIB_ROUTE_PATH_FLAG_NONE);
2873 fib_table_entry_path_remove(fib_index,
2874 &pfx_5_5_5_7_s_32,
2875 FIB_SOURCE_API,
2876 FIB_PROTOCOL_IP4,
2877 &pfx_5_5_5_5_s_32.fp_addr,
2878 ~0, // no index provided.
2879 fib_index, // same as route's FIB
2880 1,
2881 FIB_ROUTE_PATH_FLAG_NONE);
2882 fib_table_entry_path_remove(fib_index,
2883 &pfx_5_5_5_6_s_32,
2884 FIB_SOURCE_API,
2885 FIB_PROTOCOL_IP4,
2886 &nh_10_10_10_2,
2887 ~0, // no index provided.
2888 fib_index, // same as route's FIB
2889 1,
2890 FIB_ROUTE_PATH_FLAG_NONE);
2891
2892 /*
2893 * -3 entries, -3 shared path-list
2894 */
2895 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2896 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002897 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002898 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002899 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002900 fib_entry_pool_size());
2901
2902 /*
2903 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2904 */
2905 fib_table_entry_path_add(fib_index,
2906 &pfx_5_5_5_6_s_32,
2907 FIB_SOURCE_API,
2908 FIB_ENTRY_FLAG_NONE,
2909 FIB_PROTOCOL_IP4,
2910 &pfx_5_5_5_6_s_32.fp_addr,
2911 ~0, // no index provided.
2912 fib_index,
2913 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002914 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002915 FIB_ROUTE_PATH_FLAG_NONE);
2916 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2917 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2918 "1-level 5.5.5.6/32 loop is via adj for DROP");
2919
2920 fib_table_entry_path_remove(fib_index,
2921 &pfx_5_5_5_6_s_32,
2922 FIB_SOURCE_API,
2923 FIB_PROTOCOL_IP4,
2924 &pfx_5_5_5_6_s_32.fp_addr,
2925 ~0, // no index provided.
2926 fib_index, // same as route's FIB
2927 1,
2928 FIB_ROUTE_PATH_FLAG_NONE);
2929 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2930 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2931 "1-level 5.5.5.6/32 loop is removed");
2932
2933 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002934 * A recursive route whose next-hop is covered by the prefix.
2935 * This would mean the via-fib, which inherits forwarding from its
2936 * cover, thus picks up forwarding from the prfix, which is via the
2937 * via-fib, and we have a loop.
2938 */
2939 fib_prefix_t pfx_23_23_23_0_s_24 = {
2940 .fp_len = 24,
2941 .fp_proto = FIB_PROTOCOL_IP4,
2942 .fp_addr = {
2943 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2944 },
2945 };
2946 fib_prefix_t pfx_23_23_23_23_s_32 = {
2947 .fp_len = 32,
2948 .fp_proto = FIB_PROTOCOL_IP4,
2949 .fp_addr = {
2950 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2951 },
2952 };
2953 fei = fib_table_entry_path_add(fib_index,
2954 &pfx_23_23_23_0_s_24,
2955 FIB_SOURCE_API,
2956 FIB_ENTRY_FLAG_NONE,
2957 FIB_PROTOCOL_IP4,
2958 &pfx_23_23_23_23_s_32.fp_addr,
2959 ~0, // recursive
2960 fib_index,
2961 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002962 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002963 FIB_ROUTE_PATH_FLAG_NONE);
2964 dpo = fib_entry_contribute_ip_forwarding(fei);
2965 FIB_TEST(load_balance_is_drop(dpo),
2966 "23.23.23.0/24 via covered is DROP");
2967 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2968
2969 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002970 * add-remove test. no change.
2971 */
2972 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2973 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002974 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002975 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002976 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002977 fib_entry_pool_size());
2978
2979 /*
2980 * A recursive route with recursion constraints.
2981 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2982 */
2983 fib_table_entry_path_add(fib_index,
2984 &bgp_200_pfx,
2985 FIB_SOURCE_API,
2986 FIB_ENTRY_FLAG_NONE,
2987 FIB_PROTOCOL_IP4,
2988 &nh_1_1_1_1,
2989 ~0,
2990 fib_index,
2991 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002992 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002993 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2994
2995 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2996 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2997
2998 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2999 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3000
3001 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3002 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3003
3004 /*
3005 * save the load-balance. we expect it to be inplace modified
3006 */
3007 lb = load_balance_get(dpo1->dpoi_index);
3008
3009 /*
3010 * add a covering prefix for the via fib that would otherwise serve
3011 * as the resolving route when the host is removed
3012 */
3013 fib_table_entry_path_add(fib_index,
3014 &pfx_1_1_1_0_s_28,
3015 FIB_SOURCE_API,
3016 FIB_ENTRY_FLAG_NONE,
3017 FIB_PROTOCOL_IP4,
3018 &nh_10_10_10_1,
3019 tm->hw[0]->sw_if_index,
3020 ~0, // invalid fib index
3021 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003022 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003023 FIB_ROUTE_PATH_FLAG_NONE);
3024 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3025 ai = fib_entry_get_adj(fei);
3026 FIB_TEST((ai == ai_01),
3027 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3028
3029 /*
3030 * remove the host via FIB - expect the BGP prefix to be drop
3031 */
3032 fib_table_entry_path_remove(fib_index,
3033 &pfx_1_1_1_1_s_32,
3034 FIB_SOURCE_API,
3035 FIB_PROTOCOL_IP4,
3036 &nh_10_10_10_1,
3037 tm->hw[0]->sw_if_index,
3038 ~0, // invalid fib index
3039 1,
3040 FIB_ROUTE_PATH_FLAG_NONE);
3041
3042 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3043 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3044
3045 /*
3046 * add the via-entry host reoute back. expect to resolve again
3047 */
3048 fib_table_entry_path_add(fib_index,
3049 &pfx_1_1_1_1_s_32,
3050 FIB_SOURCE_API,
3051 FIB_ENTRY_FLAG_NONE,
3052 FIB_PROTOCOL_IP4,
3053 &nh_10_10_10_1,
3054 tm->hw[0]->sw_if_index,
3055 ~0, // invalid fib index
3056 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003057 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003058 FIB_ROUTE_PATH_FLAG_NONE);
3059 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3060 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3061
3062 /*
3063 * add another path for the recursive. it will then have 2.
3064 */
3065 fib_prefix_t pfx_1_1_1_3_s_32 = {
3066 .fp_len = 32,
3067 .fp_proto = FIB_PROTOCOL_IP4,
3068 .fp_addr = {
3069 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3070 },
3071 };
3072 fib_table_entry_path_add(fib_index,
3073 &pfx_1_1_1_3_s_32,
3074 FIB_SOURCE_API,
3075 FIB_ENTRY_FLAG_NONE,
3076 FIB_PROTOCOL_IP4,
3077 &nh_10_10_10_2,
3078 tm->hw[0]->sw_if_index,
3079 ~0, // invalid fib index
3080 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003081 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003082 FIB_ROUTE_PATH_FLAG_NONE);
3083
3084 fib_table_entry_path_add(fib_index,
3085 &bgp_200_pfx,
3086 FIB_SOURCE_API,
3087 FIB_ENTRY_FLAG_NONE,
3088 FIB_PROTOCOL_IP4,
3089 &pfx_1_1_1_3_s_32.fp_addr,
3090 ~0,
3091 fib_index,
3092 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003093 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003094 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3095
Neale Rannsf12a83f2017-04-18 09:09:40 -07003096 /*
3097 * add a bunch load more entries using this path combo so that we get
3098 * an LB-map created.
3099 */
3100#define N_P 128
3101 fib_prefix_t bgp_78s[N_P];
3102 for (ii = 0; ii < N_P; ii++)
3103 {
3104 bgp_78s[ii].fp_len = 32;
3105 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3106 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3107
3108
3109 fib_table_entry_path_add(fib_index,
3110 &bgp_78s[ii],
3111 FIB_SOURCE_API,
3112 FIB_ENTRY_FLAG_NONE,
3113 FIB_PROTOCOL_IP4,
3114 &pfx_1_1_1_3_s_32.fp_addr,
3115 ~0,
3116 fib_index,
3117 1,
3118 NULL,
3119 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3120 fib_table_entry_path_add(fib_index,
3121 &bgp_78s[ii],
3122 FIB_SOURCE_API,
3123 FIB_ENTRY_FLAG_NONE,
3124 FIB_PROTOCOL_IP4,
3125 &nh_1_1_1_1,
3126 ~0,
3127 fib_index,
3128 1,
3129 NULL,
3130 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3131 }
3132
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003133 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3134 dpo = fib_entry_contribute_ip_forwarding(fei);
3135
3136 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3137 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3138 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3139 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3140 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3141 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3142 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3143 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3144
3145 /*
3146 * expect the lb-map used by the recursive's load-balance is using both buckets
3147 */
3148 load_balance_map_t *lbm;
3149 index_t lbmi;
3150
3151 lb = load_balance_get(dpo->dpoi_index);
3152 lbmi = lb->lb_map;
3153 load_balance_map_lock(lbmi);
3154 lbm = load_balance_map_get(lbmi);
3155
3156 FIB_TEST(lbm->lbm_buckets[0] == 0,
3157 "LB maps's bucket 0 is %d",
3158 lbm->lbm_buckets[0]);
3159 FIB_TEST(lbm->lbm_buckets[1] == 1,
3160 "LB maps's bucket 1 is %d",
3161 lbm->lbm_buckets[1]);
3162
3163 /*
3164 * withdraw one of the /32 via-entrys.
3165 * that ECMP path will be unresolved and forwarding should continue on the
3166 * other available path. this is an iBGP PIC edge failover.
3167 * Test the forwarding changes without re-fetching the adj from the
3168 * recursive entry. this ensures its the same one that is updated; i.e. an
3169 * inplace-modify.
3170 */
3171 fib_table_entry_path_remove(fib_index,
3172 &pfx_1_1_1_1_s_32,
3173 FIB_SOURCE_API,
3174 FIB_PROTOCOL_IP4,
3175 &nh_10_10_10_1,
3176 tm->hw[0]->sw_if_index,
3177 ~0, // invalid fib index
3178 1,
3179 FIB_ROUTE_PATH_FLAG_NONE);
3180
Neale Rannsf12a83f2017-04-18 09:09:40 -07003181 /* suspend so the update walk kicks int */
3182 vlib_process_suspend(vlib_get_main(), 1e-5);
3183
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003184 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3185 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3186 "post PIC 200.200.200.200/32 was inplace modified");
3187
3188 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3189 "post PIC adj for 200.200.200.200/32 is recursive"
3190 " via adj for 1.1.1.3");
3191
3192 /*
3193 * the LB maps that was locked above should have been modified to remove
3194 * the path that was down, and thus its bucket points to a path that is
3195 * still up.
3196 */
3197 FIB_TEST(lbm->lbm_buckets[0] == 1,
3198 "LB maps's bucket 0 is %d",
3199 lbm->lbm_buckets[0]);
3200 FIB_TEST(lbm->lbm_buckets[1] == 1,
3201 "LB maps's bucket 1 is %d",
3202 lbm->lbm_buckets[1]);
3203
Neale Ranns994dab42017-04-18 12:56:45 -07003204 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003205
3206 /*
3207 * add it back. again
3208 */
3209 fib_table_entry_path_add(fib_index,
3210 &pfx_1_1_1_1_s_32,
3211 FIB_SOURCE_API,
3212 FIB_ENTRY_FLAG_NONE,
3213 FIB_PROTOCOL_IP4,
3214 &nh_10_10_10_1,
3215 tm->hw[0]->sw_if_index,
3216 ~0, // invalid fib index
3217 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003218 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003219 FIB_ROUTE_PATH_FLAG_NONE);
3220
Neale Rannsf12a83f2017-04-18 09:09:40 -07003221 /* suspend so the update walk kicks in */
3222 vlib_process_suspend(vlib_get_main(), 1e-5);
3223
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003224 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3225 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3226 "via adj for 1.1.1.1");
3227 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3228 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3229 "via adj for 1.1.1.3");
3230
3231 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3232 dpo = fib_entry_contribute_ip_forwarding(fei);
3233 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3234 "post PIC 200.200.200.200/32 was inplace modified");
3235
3236 /*
3237 * add a 3rd path. this makes the LB 16 buckets.
3238 */
3239 fib_table_entry_path_add(fib_index,
3240 &bgp_200_pfx,
3241 FIB_SOURCE_API,
3242 FIB_ENTRY_FLAG_NONE,
3243 FIB_PROTOCOL_IP4,
3244 &pfx_1_1_1_2_s_32.fp_addr,
3245 ~0,
3246 fib_index,
3247 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003248 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003249 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003250 for (ii = 0; ii < N_P; ii++)
3251 {
3252 fib_table_entry_path_add(fib_index,
3253 &bgp_78s[ii],
3254 FIB_SOURCE_API,
3255 FIB_ENTRY_FLAG_NONE,
3256 FIB_PROTOCOL_IP4,
3257 &pfx_1_1_1_2_s_32.fp_addr,
3258 ~0,
3259 fib_index,
3260 1,
3261 NULL,
3262 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3263 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003264
3265 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3266 dpo = fib_entry_contribute_ip_forwarding(fei);
3267 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3268 "200.200.200.200/32 was inplace modified for 3rd path");
3269 FIB_TEST(16 == lb->lb_n_buckets,
3270 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3271
3272 lbmi = lb->lb_map;
3273 load_balance_map_lock(lbmi);
3274 lbm = load_balance_map_get(lbmi);
3275
3276 for (ii = 0; ii < 16; ii++)
3277 {
3278 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3279 "LB Map for 200.200.200.200/32 at %d is %d",
3280 ii, lbm->lbm_buckets[ii]);
3281 }
3282
3283 /*
3284 * trigger PIC by removing the first via-entry
3285 * the first 6 buckets of the map should map to the next 6
3286 */
3287 fib_table_entry_path_remove(fib_index,
3288 &pfx_1_1_1_1_s_32,
3289 FIB_SOURCE_API,
3290 FIB_PROTOCOL_IP4,
3291 &nh_10_10_10_1,
3292 tm->hw[0]->sw_if_index,
3293 ~0,
3294 1,
3295 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003296 /* suspend so the update walk kicks int */
3297 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003298
3299 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3300 dpo = fib_entry_contribute_ip_forwarding(fei);
3301 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3302 "200.200.200.200/32 was inplace modified for 3rd path");
3303 FIB_TEST(2 == lb->lb_n_buckets,
3304 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3305
3306 for (ii = 0; ii < 6; ii++)
3307 {
3308 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3309 "LB Map for 200.200.200.200/32 at %d is %d",
3310 ii, lbm->lbm_buckets[ii]);
3311 }
3312 for (ii = 6; ii < 16; ii++)
3313 {
3314 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3315 "LB Map for 200.200.200.200/32 at %d is %d",
3316 ii, lbm->lbm_buckets[ii]);
3317 }
Neale Ranns994dab42017-04-18 12:56:45 -07003318 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003319
3320 /*
3321 * tidy up
3322 */
3323 fib_table_entry_path_add(fib_index,
3324 &pfx_1_1_1_1_s_32,
3325 FIB_SOURCE_API,
3326 FIB_ENTRY_FLAG_NONE,
3327 FIB_PROTOCOL_IP4,
3328 &nh_10_10_10_1,
3329 tm->hw[0]->sw_if_index,
3330 ~0,
3331 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003332 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003333 FIB_ROUTE_PATH_FLAG_NONE);
3334
Neale Rannsf12a83f2017-04-18 09:09:40 -07003335 for (ii = 0; ii < N_P; ii++)
3336 {
3337 fib_table_entry_delete(fib_index,
3338 &bgp_78s[ii],
3339 FIB_SOURCE_API);
3340 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3341 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3342 "%U removed",
3343 format_fib_prefix, &bgp_78s[ii]);
3344 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003345 fib_table_entry_path_remove(fib_index,
3346 &bgp_200_pfx,
3347 FIB_SOURCE_API,
3348 FIB_PROTOCOL_IP4,
3349 &pfx_1_1_1_2_s_32.fp_addr,
3350 ~0,
3351 fib_index,
3352 1,
3353 MPLS_LABEL_INVALID);
3354 fib_table_entry_path_remove(fib_index,
3355 &bgp_200_pfx,
3356 FIB_SOURCE_API,
3357 FIB_PROTOCOL_IP4,
3358 &nh_1_1_1_1,
3359 ~0,
3360 fib_index,
3361 1,
3362 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3363 fib_table_entry_path_remove(fib_index,
3364 &bgp_200_pfx,
3365 FIB_SOURCE_API,
3366 FIB_PROTOCOL_IP4,
3367 &pfx_1_1_1_3_s_32.fp_addr,
3368 ~0,
3369 fib_index,
3370 1,
3371 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3372 fib_table_entry_delete(fib_index,
3373 &pfx_1_1_1_3_s_32,
3374 FIB_SOURCE_API);
3375 fib_table_entry_delete(fib_index,
3376 &pfx_1_1_1_0_s_28,
3377 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003378 /* suspend so the update walk kicks int */
3379 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003380 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3381 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3382 "1.1.1.1/28 removed");
3383 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3384 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3385 "1.1.1.3/32 removed");
3386 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3387 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3388 "200.200.200.200/32 removed");
3389
3390 /*
3391 * add-remove test. no change.
3392 */
3393 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3394 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003395 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003396 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003397 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003398 fib_entry_pool_size());
3399
3400 /*
3401 * A route whose paths are built up iteratively and then removed
3402 * all at once
3403 */
3404 fib_prefix_t pfx_4_4_4_4_s_32 = {
3405 .fp_len = 32,
3406 .fp_proto = FIB_PROTOCOL_IP4,
3407 .fp_addr = {
3408 /* 4.4.4.4/32 */
3409 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3410 },
3411 };
3412
3413 fib_table_entry_path_add(fib_index,
3414 &pfx_4_4_4_4_s_32,
3415 FIB_SOURCE_API,
3416 FIB_ENTRY_FLAG_NONE,
3417 FIB_PROTOCOL_IP4,
3418 &nh_10_10_10_1,
3419 tm->hw[0]->sw_if_index,
3420 ~0,
3421 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003422 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003423 FIB_ROUTE_PATH_FLAG_NONE);
3424 fib_table_entry_path_add(fib_index,
3425 &pfx_4_4_4_4_s_32,
3426 FIB_SOURCE_API,
3427 FIB_ENTRY_FLAG_NONE,
3428 FIB_PROTOCOL_IP4,
3429 &nh_10_10_10_2,
3430 tm->hw[0]->sw_if_index,
3431 ~0,
3432 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003433 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003434 FIB_ROUTE_PATH_FLAG_NONE);
3435 fib_table_entry_path_add(fib_index,
3436 &pfx_4_4_4_4_s_32,
3437 FIB_SOURCE_API,
3438 FIB_ENTRY_FLAG_NONE,
3439 FIB_PROTOCOL_IP4,
3440 &nh_10_10_10_3,
3441 tm->hw[0]->sw_if_index,
3442 ~0,
3443 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003444 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003445 FIB_ROUTE_PATH_FLAG_NONE);
3446 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3447 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3448 "4.4.4.4/32 present");
3449
3450 fib_table_entry_delete(fib_index,
3451 &pfx_4_4_4_4_s_32,
3452 FIB_SOURCE_API);
3453 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3454 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3455 "4.4.4.4/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 with multiple paths at once
3469 */
3470 fib_route_path_t *r_paths = NULL;
3471
3472 for (ii = 0; ii < 4; ii++)
3473 {
3474 fib_route_path_t r_path = {
3475 .frp_proto = FIB_PROTOCOL_IP4,
3476 .frp_addr = {
3477 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3478 },
3479 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3480 .frp_weight = 1,
3481 .frp_fib_index = ~0,
3482 };
3483 vec_add1(r_paths, r_path);
3484 }
3485
3486 fib_table_entry_update(fib_index,
3487 &pfx_4_4_4_4_s_32,
3488 FIB_SOURCE_API,
3489 FIB_ENTRY_FLAG_NONE,
3490 r_paths);
3491
3492 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3493 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3494 dpo = fib_entry_contribute_ip_forwarding(fei);
3495
3496 lb = load_balance_get(dpo->dpoi_index);
3497 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3498
3499 fib_table_entry_delete(fib_index,
3500 &pfx_4_4_4_4_s_32,
3501 FIB_SOURCE_API);
3502 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3503 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3504 "4.4.4.4/32 removed");
3505 vec_free(r_paths);
3506
3507 /*
3508 * add-remove test. no change.
3509 */
3510 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3511 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003512 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003513 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003514 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003515 fib_entry_pool_size());
3516
3517 /*
3518 * A route deag route
3519 */
3520 fib_table_entry_path_add(fib_index,
3521 &pfx_4_4_4_4_s_32,
3522 FIB_SOURCE_API,
3523 FIB_ENTRY_FLAG_NONE,
3524 FIB_PROTOCOL_IP4,
3525 &zero_addr,
3526 ~0,
3527 fib_index,
3528 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003529 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003530 FIB_ROUTE_PATH_FLAG_NONE);
3531
3532 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3533 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3534
3535 dpo = fib_entry_contribute_ip_forwarding(fei);
3536 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3537 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3538
3539 FIB_TEST((fib_index == lkd->lkd_fib_index),
3540 "4.4.4.4/32 is deag in %d %U",
3541 lkd->lkd_fib_index,
3542 format_dpo_id, dpo, 0);
3543
3544 fib_table_entry_delete(fib_index,
3545 &pfx_4_4_4_4_s_32,
3546 FIB_SOURCE_API);
3547 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3548 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3549 "4.4.4.4/32 removed");
3550 vec_free(r_paths);
3551
3552 /*
3553 * add-remove test. no change.
3554 */
3555 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3556 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003557 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003558 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003559 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003560 fib_entry_pool_size());
3561
3562 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003563 * Duplicate paths:
3564 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3565 */
3566 fib_prefix_t pfx_34_1_1_1_s_32 = {
3567 .fp_len = 32,
3568 .fp_proto = FIB_PROTOCOL_IP4,
3569 .fp_addr = {
3570 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3571 },
3572 };
3573 fib_prefix_t pfx_34_34_1_1_s_32 = {
3574 .fp_len = 32,
3575 .fp_proto = FIB_PROTOCOL_IP4,
3576 .fp_addr = {
3577 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3578 },
3579 };
3580 fei = fib_table_entry_path_add(fib_index,
3581 &pfx_34_1_1_1_s_32,
3582 FIB_SOURCE_API,
3583 FIB_ENTRY_FLAG_NONE,
3584 FIB_PROTOCOL_IP4,
3585 &pfx_34_34_1_1_s_32.fp_addr,
3586 ~0,
3587 fib_index,
3588 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003589 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003590 FIB_ROUTE_PATH_FLAG_NONE);
3591 fei = fib_table_entry_path_add(fib_index,
3592 &pfx_34_1_1_1_s_32,
3593 FIB_SOURCE_API,
3594 FIB_ENTRY_FLAG_NONE,
3595 FIB_PROTOCOL_IP4,
3596 &pfx_34_34_1_1_s_32.fp_addr,
3597 ~0,
3598 fib_index,
3599 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003600 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003601 FIB_ROUTE_PATH_FLAG_NONE);
3602 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3603 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3604
3605 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003606 * CLEANUP
3607 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3608 * all of which are via 10.10.10.1, Itf1
3609 */
3610 fib_table_entry_path_remove(fib_index,
3611 &pfx_1_1_1_2_s_32,
3612 FIB_SOURCE_API,
3613 FIB_PROTOCOL_IP4,
3614 &nh_10_10_10_1,
3615 tm->hw[0]->sw_if_index,
3616 ~0,
3617 1,
3618 FIB_ROUTE_PATH_FLAG_NONE);
3619 fib_table_entry_path_remove(fib_index,
3620 &pfx_1_1_1_1_s_32,
3621 FIB_SOURCE_API,
3622 FIB_PROTOCOL_IP4,
3623 &nh_10_10_10_1,
3624 tm->hw[0]->sw_if_index,
3625 ~0,
3626 1,
3627 FIB_ROUTE_PATH_FLAG_NONE);
3628 fib_table_entry_path_remove(fib_index,
3629 &pfx_1_1_2_0_s_24,
3630 FIB_SOURCE_API,
3631 FIB_PROTOCOL_IP4,
3632 &nh_10_10_10_1,
3633 tm->hw[0]->sw_if_index,
3634 ~0,
3635 1,
3636 FIB_ROUTE_PATH_FLAG_NONE);
3637
3638 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3639 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3640 "1.1.1.1/32 removed");
3641 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3642 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3643 "1.1.1.2/32 removed");
3644 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3645 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3646 "1.1.2.0/24 removed");
3647
3648 /*
3649 * -3 entries and -1 shared path-list
3650 */
3651 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3652 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003653 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003654 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003655 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003656 fib_entry_pool_size());
3657
3658 /*
3659 * An attached-host route. Expect to link to the incomplete adj
3660 */
3661 fib_prefix_t pfx_4_1_1_1_s_32 = {
3662 .fp_len = 32,
3663 .fp_proto = FIB_PROTOCOL_IP4,
3664 .fp_addr = {
3665 /* 4.1.1.1/32 */
3666 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3667 },
3668 };
3669 fib_table_entry_path_add(fib_index,
3670 &pfx_4_1_1_1_s_32,
3671 FIB_SOURCE_API,
3672 FIB_ENTRY_FLAG_NONE,
3673 FIB_PROTOCOL_IP4,
3674 &zero_addr,
3675 tm->hw[0]->sw_if_index,
3676 fib_index,
3677 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003678 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003679 FIB_ROUTE_PATH_FLAG_NONE);
3680
3681 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3682 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3683 ai = fib_entry_get_adj(fei);
3684
3685 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003686 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003687 &pfx_4_1_1_1_s_32.fp_addr,
3688 tm->hw[0]->sw_if_index);
3689 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3690 adj_unlock(ai2);
3691
3692 /*
3693 * +1 entry and +1 shared path-list
3694 */
3695 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3696 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003697 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003698 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003699 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003700 fib_entry_pool_size());
3701
3702 fib_table_entry_delete(fib_index,
3703 &pfx_4_1_1_1_s_32,
3704 FIB_SOURCE_API);
3705
3706 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3707 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003708 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003709 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003710 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003711 fib_entry_pool_size());
3712
3713 /*
3714 * add a v6 prefix via v4 next-hops
3715 */
3716 fib_prefix_t pfx_2001_s_64 = {
3717 .fp_len = 64,
3718 .fp_proto = FIB_PROTOCOL_IP6,
3719 .fp_addr = {
3720 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3721 },
3722 };
3723 fei = fib_table_entry_path_add(0, //default v6 table
3724 &pfx_2001_s_64,
3725 FIB_SOURCE_API,
3726 FIB_ENTRY_FLAG_NONE,
3727 FIB_PROTOCOL_IP4,
3728 &nh_10_10_10_1,
3729 tm->hw[0]->sw_if_index,
3730 fib_index,
3731 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003732 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003733 FIB_ROUTE_PATH_FLAG_NONE);
3734
3735 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3736 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3737 ai = fib_entry_get_adj(fei);
3738 adj = adj_get(ai);
3739 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3740 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003741 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003742 "2001::/64 is link type v6");
3743 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3744 "2001::/64 ADJ-adj is NH proto v4");
3745 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3746
Neale Ranns3ee44042016-10-03 13:05:48 +01003747 /*
3748 * add a uRPF exempt prefix:
3749 * test:
3750 * - it's forwarding is drop
3751 * - it's uRPF list is not empty
3752 * - the uRPF list for the default route (it's cover) is empty
3753 */
3754 fei = fib_table_entry_special_add(fib_index,
3755 &pfx_4_1_1_1_s_32,
3756 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003757 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003758 dpo = fib_entry_contribute_ip_forwarding(fei);
3759 FIB_TEST(load_balance_is_drop(dpo),
3760 "uRPF exempt 4.1.1.1/32 DROP");
3761 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3762 "uRPF list for exempt prefix has itf index 0");
3763 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3764 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3765 "uRPF list for 0.0.0.0/0 empty");
3766
3767 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003768
3769 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003770 * An adj-fib that fails the refinement criteria - no connected cover
3771 */
3772 fib_prefix_t pfx_12_10_10_2_s_32 = {
3773 .fp_len = 32,
3774 .fp_proto = FIB_PROTOCOL_IP4,
3775 .fp_addr = {
3776 /* 12.10.10.2 */
3777 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3778 },
3779 };
3780
3781 fib_table_entry_update_one_path(fib_index,
3782 &pfx_12_10_10_2_s_32,
3783 FIB_SOURCE_ADJ,
3784 FIB_ENTRY_FLAG_ATTACHED,
3785 FIB_PROTOCOL_IP4,
3786 &pfx_12_10_10_2_s_32.fp_addr,
3787 tm->hw[0]->sw_if_index,
3788 ~0, // invalid fib index
3789 1,
3790 NULL,
3791 FIB_ROUTE_PATH_FLAG_NONE);
3792
3793 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3794 dpo = fib_entry_contribute_ip_forwarding(fei);
3795 FIB_TEST(!dpo_id_is_valid(dpo),
3796 "no connected cover adj-fib fails refinement");
3797
3798 fib_table_entry_delete(fib_index,
3799 &pfx_12_10_10_2_s_32,
3800 FIB_SOURCE_ADJ);
3801
3802 /*
3803 * An adj-fib that fails the refinement criteria - cover is connected
3804 * but on a different interface
3805 */
3806 fib_prefix_t pfx_10_10_10_127_s_32 = {
3807 .fp_len = 32,
3808 .fp_proto = FIB_PROTOCOL_IP4,
3809 .fp_addr = {
3810 /* 10.10.10.127 */
3811 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3812 },
3813 };
3814
3815 fib_table_entry_update_one_path(fib_index,
3816 &pfx_10_10_10_127_s_32,
3817 FIB_SOURCE_ADJ,
3818 FIB_ENTRY_FLAG_ATTACHED,
3819 FIB_PROTOCOL_IP4,
3820 &pfx_10_10_10_127_s_32.fp_addr,
3821 tm->hw[1]->sw_if_index,
3822 ~0, // invalid fib index
3823 1,
3824 NULL,
3825 FIB_ROUTE_PATH_FLAG_NONE);
3826
3827 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3828 dpo = fib_entry_contribute_ip_forwarding(fei);
3829 FIB_TEST(!dpo_id_is_valid(dpo),
3830 "wrong interface adj-fib fails refinement");
3831
3832 fib_table_entry_delete(fib_index,
3833 &pfx_10_10_10_127_s_32,
3834 FIB_SOURCE_ADJ);
3835
3836 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003837 * CLEANUP
3838 * remove adj-fibs:
3839 */
3840 fib_table_entry_delete(fib_index,
3841 &pfx_10_10_10_1_s_32,
3842 FIB_SOURCE_ADJ);
3843 fib_table_entry_delete(fib_index,
3844 &pfx_10_10_10_2_s_32,
3845 FIB_SOURCE_ADJ);
3846 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3847 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3848 "10.10.10.1/32 adj-fib removed");
3849 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3850 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3851 "10.10.10.2/32 adj-fib removed");
3852
3853 /*
3854 * -2 entries and -2 non-shared path-list
3855 */
3856 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3857 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003858 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003859 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003860 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003861 fib_entry_pool_size());
3862
3863 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01003864 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003865 * These are the last locks on these adjs. they should thus go away.
3866 */
3867 adj_unlock(ai_02);
3868 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01003869 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003870
3871 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3872 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003873
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003874 /*
3875 * CLEANUP
3876 * remove the interface prefixes
3877 */
3878 local_pfx.fp_len = 32;
3879 fib_table_entry_special_remove(fib_index, &local_pfx,
3880 FIB_SOURCE_INTERFACE);
3881 fei = fib_table_lookup(fib_index, &local_pfx);
3882
3883 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3884 fib_table_lookup_exact_match(fib_index, &local_pfx),
3885 "10.10.10.10/32 adj-fib removed");
3886
3887 local_pfx.fp_len = 24;
3888 fib_table_entry_delete(fib_index, &local_pfx,
3889 FIB_SOURCE_INTERFACE);
3890
3891 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3892 fib_table_lookup_exact_match(fib_index, &local_pfx),
3893 "10.10.10.10/24 adj-fib removed");
3894
3895 /*
3896 * -2 entries and -2 non-shared path-list
3897 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07003898 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003899 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003900 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003901 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003902 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003903 fib_entry_pool_size());
3904
3905 /*
3906 * Last but not least, remove the VRF
3907 */
3908 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3909 FIB_PROTOCOL_IP4,
3910 FIB_SOURCE_API)),
3911 "NO API Source'd prefixes");
3912 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3913 FIB_PROTOCOL_IP4,
3914 FIB_SOURCE_RR)),
3915 "NO RR Source'd prefixes");
3916 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3917 FIB_PROTOCOL_IP4,
3918 FIB_SOURCE_INTERFACE)),
3919 "NO INterface Source'd prefixes");
3920
3921 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3922
3923 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3924 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003925 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003926 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003927 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003928 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003929 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01003930 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07003931 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07003932 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07003933 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
3934 pool_elts(load_balance_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003935
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003936 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003937}
3938
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003939static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003940fib_test_v6 (void)
3941{
3942 /*
3943 * In the default table check for the presence and correct forwarding
3944 * of the special entries
3945 */
3946 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
3947 const dpo_id_t *dpo, *dpo_drop;
3948 const ip_adjacency_t *adj;
3949 const receive_dpo_t *rd;
3950 test_main_t *tm;
3951 u32 fib_index;
3952 int ii;
3953
3954 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3955 adj_nbr_db_size());
3956
3957 /* via 2001:0:0:1::2 */
3958 ip46_address_t nh_2001_2 = {
3959 .ip6 = {
3960 .as_u64 = {
3961 [0] = clib_host_to_net_u64(0x2001000000000001),
3962 [1] = clib_host_to_net_u64(0x0000000000000002),
3963 },
3964 },
3965 };
3966
3967 tm = &test_main;
3968
3969 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
3970
3971 /* Find or create FIB table 11 */
3972 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
3973
3974 for (ii = 0; ii < 4; ii++)
3975 {
3976 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
3977 }
3978
3979 fib_prefix_t pfx_0_0 = {
3980 .fp_len = 0,
3981 .fp_proto = FIB_PROTOCOL_IP6,
3982 .fp_addr = {
3983 .ip6 = {
3984 {0, 0},
3985 },
3986 },
3987 };
3988
3989 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
3990 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
3991 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3992 "Default route is DROP");
3993
3994 dpo = fib_entry_contribute_ip_forwarding(dfrt);
3995 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3996 &ip6_main,
3997 1,
3998 &pfx_0_0.fp_addr.ip6)),
3999 "default-route; fwd and non-fwd tables match");
4000
4001 // FIXME - check specials.
4002
4003 /*
4004 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004005 * each with 2 entries and a v6 mfib with 4 path-lists.
4006 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004007 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004008#define ENPS (5+4)
4009#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004010 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004011 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004012 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004013 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004014 fib_entry_pool_size());
4015
4016 /*
4017 * add interface routes.
4018 * validate presence of /64 attached and /128 recieve.
4019 * test for the presence of the receive address in the glean and local adj
4020 *
4021 * receive on 2001:0:0:1::1/128
4022 */
4023 fib_prefix_t local_pfx = {
4024 .fp_len = 64,
4025 .fp_proto = FIB_PROTOCOL_IP6,
4026 .fp_addr = {
4027 .ip6 = {
4028 .as_u64 = {
4029 [0] = clib_host_to_net_u64(0x2001000000000001),
4030 [1] = clib_host_to_net_u64(0x0000000000000001),
4031 },
4032 },
4033 }
4034 };
4035
4036 fib_table_entry_update_one_path(fib_index, &local_pfx,
4037 FIB_SOURCE_INTERFACE,
4038 (FIB_ENTRY_FLAG_CONNECTED |
4039 FIB_ENTRY_FLAG_ATTACHED),
4040 FIB_PROTOCOL_IP6,
4041 NULL,
4042 tm->hw[0]->sw_if_index,
4043 ~0,
4044 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004045 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004046 FIB_ROUTE_PATH_FLAG_NONE);
4047 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4048
4049 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4050
4051 ai = fib_entry_get_adj(fei);
4052 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4053 adj = adj_get(ai);
4054 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4055 "attached interface adj is glean");
4056 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4057 &adj->sub_type.glean.receive_addr)),
4058 "attached interface adj is receive ok");
4059 dpo = fib_entry_contribute_ip_forwarding(fei);
4060 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4061 &ip6_main,
4062 1,
4063 &local_pfx.fp_addr.ip6)),
4064 "attached-route; fwd and non-fwd tables match");
4065
4066 local_pfx.fp_len = 128;
4067 fib_table_entry_update_one_path(fib_index, &local_pfx,
4068 FIB_SOURCE_INTERFACE,
4069 (FIB_ENTRY_FLAG_CONNECTED |
4070 FIB_ENTRY_FLAG_LOCAL),
4071 FIB_PROTOCOL_IP6,
4072 NULL,
4073 tm->hw[0]->sw_if_index,
4074 ~0, // invalid fib index
4075 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004076 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004077 FIB_ROUTE_PATH_FLAG_NONE);
4078 fei = fib_table_lookup(fib_index, &local_pfx);
4079
4080 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4081
4082 dpo = fib_entry_contribute_ip_forwarding(fei);
4083 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4084 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4085 "local interface adj is local");
4086 rd = receive_dpo_get(dpo->dpoi_index);
4087
4088 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4089 &rd->rd_addr)),
4090 "local interface adj is receive ok");
4091
4092 dpo = fib_entry_contribute_ip_forwarding(fei);
4093 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4094 &ip6_main,
4095 1,
4096 &local_pfx.fp_addr.ip6)),
4097 "local-route; fwd and non-fwd tables match");
4098
4099 /*
4100 * +2 entries. +2 unshared path-lists
4101 */
4102 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004103 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004104 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004105 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004106 fib_entry_pool_size());
4107
4108 /*
4109 * Modify the default route to be via an adj not yet known.
4110 * this sources the defalut route with the API source, which is
4111 * a higher preference to the DEFAULT_ROUTE source
4112 */
4113 fib_table_entry_path_add(fib_index, &pfx_0_0,
4114 FIB_SOURCE_API,
4115 FIB_ENTRY_FLAG_NONE,
4116 FIB_PROTOCOL_IP6,
4117 &nh_2001_2,
4118 tm->hw[0]->sw_if_index,
4119 ~0,
4120 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004121 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004122 FIB_ROUTE_PATH_FLAG_NONE);
4123 fei = fib_table_lookup(fib_index, &pfx_0_0);
4124
4125 FIB_TEST((fei == dfrt), "default route same index");
4126 ai = fib_entry_get_adj(fei);
4127 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4128 adj = adj_get(ai);
4129 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4130 "adj is incomplete");
4131 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4132 "adj nbr next-hop ok");
4133
4134 /*
4135 * find the adj in the shared db
4136 */
4137 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004138 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004139 &nh_2001_2,
4140 tm->hw[0]->sw_if_index);
4141 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4142 adj_unlock(locked_ai);
4143
4144 /*
4145 * no more entires. +1 shared path-list
4146 */
4147 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4148 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004149 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004150 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004151 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004152 fib_entry_pool_size());
4153
4154 /*
4155 * remove the API source from the default route. We expected
4156 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4157 */
4158 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4159 FIB_SOURCE_API,
4160 FIB_PROTOCOL_IP6,
4161 &nh_2001_2,
4162 tm->hw[0]->sw_if_index,
4163 ~0,
4164 1,
4165 FIB_ROUTE_PATH_FLAG_NONE);
4166 fei = fib_table_lookup(fib_index, &pfx_0_0);
4167
4168 FIB_TEST((fei == dfrt), "default route same index");
4169 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4170 "Default route is DROP");
4171
4172 /*
4173 * no more entires. -1 shared path-list
4174 */
4175 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4176 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004177 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004178 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004179 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004180 fib_entry_pool_size());
4181
4182 /*
4183 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4184 */
4185 fib_prefix_t pfx_2001_1_2_s_128 = {
4186 .fp_len = 128,
4187 .fp_proto = FIB_PROTOCOL_IP6,
4188 .fp_addr = {
4189 .ip6 = {
4190 .as_u64 = {
4191 [0] = clib_host_to_net_u64(0x2001000000000001),
4192 [1] = clib_host_to_net_u64(0x0000000000000002),
4193 },
4194 },
4195 }
4196 };
4197 fib_prefix_t pfx_2001_1_3_s_128 = {
4198 .fp_len = 128,
4199 .fp_proto = FIB_PROTOCOL_IP6,
4200 .fp_addr = {
4201 .ip6 = {
4202 .as_u64 = {
4203 [0] = clib_host_to_net_u64(0x2001000000000001),
4204 [1] = clib_host_to_net_u64(0x0000000000000003),
4205 },
4206 },
4207 }
4208 };
4209 u8 eth_addr[] = {
4210 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4211 };
4212
4213 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004214 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004215 &pfx_2001_1_2_s_128.fp_addr,
4216 tm->hw[0]->sw_if_index);
4217 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4218 adj = adj_get(ai_01);
4219 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4220 "adj is incomplete");
4221 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4222 &adj->sub_type.nbr.next_hop)),
4223 "adj nbr next-hop ok");
4224
Neale Rannsb80c5362016-10-08 13:03:40 +01004225 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4226 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004227 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4228 "adj is complete");
4229 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4230 &adj->sub_type.nbr.next_hop)),
4231 "adj nbr next-hop ok");
4232
4233 fib_table_entry_update_one_path(fib_index,
4234 &pfx_2001_1_2_s_128,
4235 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004236 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004237 FIB_PROTOCOL_IP6,
4238 &pfx_2001_1_2_s_128.fp_addr,
4239 tm->hw[0]->sw_if_index,
4240 ~0,
4241 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004242 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004243 FIB_ROUTE_PATH_FLAG_NONE);
4244
4245 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4246 ai = fib_entry_get_adj(fei);
4247 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4248
4249 eth_addr[5] = 0xb2;
4250
4251 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004252 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004253 &pfx_2001_1_3_s_128.fp_addr,
4254 tm->hw[0]->sw_if_index);
4255 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4256 adj = adj_get(ai_02);
4257 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4258 "adj is incomplete");
4259 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4260 &adj->sub_type.nbr.next_hop)),
4261 "adj nbr next-hop ok");
4262
Neale Rannsb80c5362016-10-08 13:03:40 +01004263 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4264 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004265 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4266 "adj is complete");
4267 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4268 &adj->sub_type.nbr.next_hop)),
4269 "adj nbr next-hop ok");
4270 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4271
4272 fib_table_entry_update_one_path(fib_index,
4273 &pfx_2001_1_3_s_128,
4274 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004275 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004276 FIB_PROTOCOL_IP6,
4277 &pfx_2001_1_3_s_128.fp_addr,
4278 tm->hw[0]->sw_if_index,
4279 ~0,
4280 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004281 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004282 FIB_ROUTE_PATH_FLAG_NONE);
4283
4284 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4285 ai = fib_entry_get_adj(fei);
4286 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4287
4288 /*
4289 * +2 entries, +2 unshread path-lists.
4290 */
4291 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4292 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004293 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004294 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004295 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004296 fib_entry_pool_size());
4297
4298 /*
4299 * Add a 2 routes via the first ADJ. ensure path-list sharing
4300 */
4301 fib_prefix_t pfx_2001_a_s_64 = {
4302 .fp_len = 64,
4303 .fp_proto = FIB_PROTOCOL_IP6,
4304 .fp_addr = {
4305 .ip6 = {
4306 .as_u64 = {
4307 [0] = clib_host_to_net_u64(0x200100000000000a),
4308 [1] = clib_host_to_net_u64(0x0000000000000000),
4309 },
4310 },
4311 }
4312 };
4313 fib_prefix_t pfx_2001_b_s_64 = {
4314 .fp_len = 64,
4315 .fp_proto = FIB_PROTOCOL_IP6,
4316 .fp_addr = {
4317 .ip6 = {
4318 .as_u64 = {
4319 [0] = clib_host_to_net_u64(0x200100000000000b),
4320 [1] = clib_host_to_net_u64(0x0000000000000000),
4321 },
4322 },
4323 }
4324 };
4325
4326 fib_table_entry_path_add(fib_index,
4327 &pfx_2001_a_s_64,
4328 FIB_SOURCE_API,
4329 FIB_ENTRY_FLAG_NONE,
4330 FIB_PROTOCOL_IP6,
4331 &nh_2001_2,
4332 tm->hw[0]->sw_if_index,
4333 ~0,
4334 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004335 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004336 FIB_ROUTE_PATH_FLAG_NONE);
4337 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4338 ai = fib_entry_get_adj(fei);
4339 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4340 fib_table_entry_path_add(fib_index,
4341 &pfx_2001_b_s_64,
4342 FIB_SOURCE_API,
4343 FIB_ENTRY_FLAG_NONE,
4344 FIB_PROTOCOL_IP6,
4345 &nh_2001_2,
4346 tm->hw[0]->sw_if_index,
4347 ~0,
4348 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004349 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004350 FIB_ROUTE_PATH_FLAG_NONE);
4351 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4352 ai = fib_entry_get_adj(fei);
4353 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4354
4355 /*
4356 * +2 entries, +1 shared path-list.
4357 */
4358 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4359 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004360 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004361 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004362 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004363 fib_entry_pool_size());
4364
4365 /*
4366 * add a v4 prefix via a v6 next-hop
4367 */
4368 fib_prefix_t pfx_1_1_1_1_s_32 = {
4369 .fp_len = 32,
4370 .fp_proto = FIB_PROTOCOL_IP4,
4371 .fp_addr = {
4372 .ip4.as_u32 = 0x01010101,
4373 },
4374 };
4375 fei = fib_table_entry_path_add(0, // default table
4376 &pfx_1_1_1_1_s_32,
4377 FIB_SOURCE_API,
4378 FIB_ENTRY_FLAG_NONE,
4379 FIB_PROTOCOL_IP6,
4380 &nh_2001_2,
4381 tm->hw[0]->sw_if_index,
4382 ~0,
4383 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004384 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004385 FIB_ROUTE_PATH_FLAG_NONE);
4386 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4387 "1.1.1.1/32 o v6 route present");
4388 ai = fib_entry_get_adj(fei);
4389 adj = adj_get(ai);
4390 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4391 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004392 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004393 "1.1.1.1/32 ADJ-adj is link type v4");
4394 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4395 "1.1.1.1/32 ADJ-adj is NH proto v6");
4396 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4397
4398 /*
4399 * An attached route
4400 */
4401 fib_prefix_t pfx_2001_c_s_64 = {
4402 .fp_len = 64,
4403 .fp_proto = FIB_PROTOCOL_IP6,
4404 .fp_addr = {
4405 .ip6 = {
4406 .as_u64 = {
4407 [0] = clib_host_to_net_u64(0x200100000000000c),
4408 [1] = clib_host_to_net_u64(0x0000000000000000),
4409 },
4410 },
4411 }
4412 };
4413 fib_table_entry_path_add(fib_index,
4414 &pfx_2001_c_s_64,
4415 FIB_SOURCE_CLI,
4416 FIB_ENTRY_FLAG_ATTACHED,
4417 FIB_PROTOCOL_IP6,
4418 NULL,
4419 tm->hw[0]->sw_if_index,
4420 ~0,
4421 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004422 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004423 FIB_ROUTE_PATH_FLAG_NONE);
4424 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4425 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4426 ai = fib_entry_get_adj(fei);
4427 adj = adj_get(ai);
4428 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4429 "2001:0:0:c/64 attached resolves via glean");
4430
4431 fib_table_entry_path_remove(fib_index,
4432 &pfx_2001_c_s_64,
4433 FIB_SOURCE_CLI,
4434 FIB_PROTOCOL_IP6,
4435 NULL,
4436 tm->hw[0]->sw_if_index,
4437 ~0,
4438 1,
4439 FIB_ROUTE_PATH_FLAG_NONE);
4440 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4441 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4442
4443 /*
4444 * Shutdown the interface on which we have a connected and through
4445 * which the routes are reachable.
4446 * This will result in the connected, adj-fibs, and routes linking to drop
4447 * The local/for-us prefix continues to receive.
4448 */
4449 clib_error_t * error;
4450
4451 error = vnet_sw_interface_set_flags(vnet_get_main(),
4452 tm->hw[0]->sw_if_index,
4453 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4454 FIB_TEST((NULL == error), "Interface shutdown OK");
4455
4456 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4457 dpo = fib_entry_contribute_ip_forwarding(fei);
4458 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4459 "2001::b/64 resolves via drop");
4460
4461 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4462 dpo = fib_entry_contribute_ip_forwarding(fei);
4463 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4464 "2001::a/64 resolves via drop");
4465 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4466 dpo = fib_entry_contribute_ip_forwarding(fei);
4467 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4468 "2001:0:0:1::3/64 resolves via drop");
4469 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4470 dpo = fib_entry_contribute_ip_forwarding(fei);
4471 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4472 "2001:0:0:1::2/64 resolves via drop");
4473 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4474 dpo = fib_entry_contribute_ip_forwarding(fei);
4475 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4476 "2001:0:0:1::1/128 not drop");
4477 local_pfx.fp_len = 64;
4478 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4479 dpo = fib_entry_contribute_ip_forwarding(fei);
4480 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4481 "2001:0:0:1/64 resolves via drop");
4482
4483 /*
4484 * no change
4485 */
4486 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4487 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004488 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004489 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004490 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004491 fib_entry_pool_size());
4492
4493 /*
4494 * shutdown one of the other interfaces, then add a connected.
4495 * and swap one of the routes to it.
4496 */
4497 error = vnet_sw_interface_set_flags(vnet_get_main(),
4498 tm->hw[1]->sw_if_index,
4499 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4500 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4501
4502 fib_prefix_t connected_pfx = {
4503 .fp_len = 64,
4504 .fp_proto = FIB_PROTOCOL_IP6,
4505 .fp_addr = {
4506 .ip6 = {
4507 /* 2001:0:0:2::1/64 */
4508 .as_u64 = {
4509 [0] = clib_host_to_net_u64(0x2001000000000002),
4510 [1] = clib_host_to_net_u64(0x0000000000000001),
4511 },
4512 },
4513 }
4514 };
4515 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4516 FIB_SOURCE_INTERFACE,
4517 (FIB_ENTRY_FLAG_CONNECTED |
4518 FIB_ENTRY_FLAG_ATTACHED),
4519 FIB_PROTOCOL_IP6,
4520 NULL,
4521 tm->hw[1]->sw_if_index,
4522 ~0,
4523 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004524 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004525 FIB_ROUTE_PATH_FLAG_NONE);
4526 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4527 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4528 dpo = fib_entry_contribute_ip_forwarding(fei);
4529 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4530 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4531 "2001:0:0:2/64 not resolves via drop");
4532
4533 connected_pfx.fp_len = 128;
4534 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4535 FIB_SOURCE_INTERFACE,
4536 (FIB_ENTRY_FLAG_CONNECTED |
4537 FIB_ENTRY_FLAG_LOCAL),
4538 FIB_PROTOCOL_IP6,
4539 NULL,
4540 tm->hw[0]->sw_if_index,
4541 ~0, // invalid fib index
4542 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004543 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004544 FIB_ROUTE_PATH_FLAG_NONE);
4545 fei = fib_table_lookup(fib_index, &connected_pfx);
4546
4547 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4548 dpo = fib_entry_contribute_ip_forwarding(fei);
4549 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4550 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4551 "local interface adj is local");
4552 rd = receive_dpo_get(dpo->dpoi_index);
4553 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4554 &rd->rd_addr)),
4555 "local interface adj is receive ok");
4556
4557 /*
4558 * +2 entries, +2 unshared path-lists
4559 */
4560 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4561 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004562 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004563 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004564 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004565 fib_entry_pool_size());
4566
4567
4568 /*
4569 * bring the interface back up. we expected the routes to return
4570 * to normal forwarding.
4571 */
4572 error = vnet_sw_interface_set_flags(vnet_get_main(),
4573 tm->hw[0]->sw_if_index,
4574 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4575 FIB_TEST((NULL == error), "Interface bring-up OK");
4576 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4577 ai = fib_entry_get_adj(fei);
4578 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4579 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4580 ai = fib_entry_get_adj(fei);
4581 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4582 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4583 ai = fib_entry_get_adj(fei);
4584 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4585 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4586 ai = fib_entry_get_adj(fei);
4587 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4588 local_pfx.fp_len = 64;
4589 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4590 ai = fib_entry_get_adj(fei);
4591 adj = adj_get(ai);
4592 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4593 "attached interface adj is glean");
4594
4595 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004596 * Same test as above, but this time the HW interface goes down
4597 */
4598 error = vnet_hw_interface_set_flags(vnet_get_main(),
4599 tm->hw_if_indicies[0],
4600 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4601 FIB_TEST((NULL == error), "Interface shutdown OK");
4602
4603 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4604 dpo = fib_entry_contribute_ip_forwarding(fei);
4605 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4606 "2001::b/64 resolves via drop");
4607 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4608 dpo = fib_entry_contribute_ip_forwarding(fei);
4609 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4610 "2001::a/64 resolves via drop");
4611 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4612 dpo = fib_entry_contribute_ip_forwarding(fei);
4613 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4614 "2001:0:0:1::3/128 resolves via drop");
4615 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4616 dpo = fib_entry_contribute_ip_forwarding(fei);
4617 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4618 "2001:0:0:1::2/128 resolves via drop");
4619 local_pfx.fp_len = 128;
4620 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4621 dpo = fib_entry_contribute_ip_forwarding(fei);
4622 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4623 "2001:0:0:1::1/128 not drop");
4624 local_pfx.fp_len = 64;
4625 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4626 dpo = fib_entry_contribute_ip_forwarding(fei);
4627 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4628 "2001:0:0:1/64 resolves via drop");
4629
4630 error = vnet_hw_interface_set_flags(vnet_get_main(),
4631 tm->hw_if_indicies[0],
4632 VNET_HW_INTERFACE_FLAG_LINK_UP);
4633 FIB_TEST((NULL == error), "Interface bring-up OK");
4634 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4635 ai = fib_entry_get_adj(fei);
4636 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4637 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4638 ai = fib_entry_get_adj(fei);
4639 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4640 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4641 ai = fib_entry_get_adj(fei);
4642 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4643 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4644 ai = fib_entry_get_adj(fei);
4645 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4646 local_pfx.fp_len = 64;
4647 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4648 ai = fib_entry_get_adj(fei);
4649 adj = adj_get(ai);
4650 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4651 "attached interface adj is glean");
4652
4653 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004654 * Delete the interface that the routes reolve through.
4655 * Again no routes are removed. They all point to drop.
4656 *
4657 * This is considered an error case. The control plane should
4658 * not remove interfaces through which routes resolve, but
4659 * such things can happen. ALL affected routes will drop.
4660 */
4661 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4662
4663 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4664 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4665 "2001::b/64 resolves via drop");
4666 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4667 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4668 "2001::b/64 resolves via drop");
4669 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4670 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4671 "2001:0:0:1::3/64 resolves via drop");
4672 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4673 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4674 "2001:0:0:1::2/64 resolves via drop");
4675 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4676 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4677 "2001:0:0:1::1/128 is drop");
4678 local_pfx.fp_len = 64;
4679 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4680 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4681 "2001:0:0:1/64 resolves via drop");
4682
4683 /*
4684 * no change
4685 */
4686 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4687 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004688 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004689 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004690 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004691 fib_entry_pool_size());
4692
4693 /*
4694 * Add the interface back. routes stay unresolved.
4695 */
4696 error = ethernet_register_interface(vnet_get_main(),
4697 test_interface_device_class.index,
4698 0 /* instance */,
4699 hw_address,
4700 &tm->hw_if_indicies[0],
4701 /* flag change */ 0);
4702
4703 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4704 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4705 "2001::b/64 resolves via drop");
4706 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4707 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4708 "2001::b/64 resolves via drop");
4709 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4710 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4711 "2001:0:0:1::3/64 resolves via drop");
4712 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4713 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4714 "2001:0:0:1::2/64 resolves via drop");
4715 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4716 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4717 "2001:0:0:1::1/128 is drop");
4718 local_pfx.fp_len = 64;
4719 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4720 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4721 "2001:0:0:1/64 resolves via drop");
4722
4723 /*
4724 * CLEANUP ALL the routes
4725 */
4726 fib_table_entry_delete(fib_index,
4727 &pfx_2001_c_s_64,
4728 FIB_SOURCE_API);
4729 fib_table_entry_delete(fib_index,
4730 &pfx_2001_a_s_64,
4731 FIB_SOURCE_API);
4732 fib_table_entry_delete(fib_index,
4733 &pfx_2001_b_s_64,
4734 FIB_SOURCE_API);
4735 fib_table_entry_delete(fib_index,
4736 &pfx_2001_1_3_s_128,
4737 FIB_SOURCE_ADJ);
4738 fib_table_entry_delete(fib_index,
4739 &pfx_2001_1_2_s_128,
4740 FIB_SOURCE_ADJ);
4741 local_pfx.fp_len = 64;
4742 fib_table_entry_delete(fib_index, &local_pfx,
4743 FIB_SOURCE_INTERFACE);
4744 local_pfx.fp_len = 128;
4745 fib_table_entry_special_remove(fib_index, &local_pfx,
4746 FIB_SOURCE_INTERFACE);
4747 connected_pfx.fp_len = 64;
4748 fib_table_entry_delete(fib_index, &connected_pfx,
4749 FIB_SOURCE_INTERFACE);
4750 connected_pfx.fp_len = 128;
4751 fib_table_entry_special_remove(fib_index, &connected_pfx,
4752 FIB_SOURCE_INTERFACE);
4753
4754 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4755 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4756 "2001::a/64 removed");
4757 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4758 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4759 "2001::b/64 removed");
4760 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4761 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4762 "2001:0:0:1::3/128 removed");
4763 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4764 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4765 "2001:0:0:1::3/128 removed");
4766 local_pfx.fp_len = 64;
4767 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4768 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4769 "2001:0:0:1/64 removed");
4770 local_pfx.fp_len = 128;
4771 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4772 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4773 "2001:0:0:1::1/128 removed");
4774 connected_pfx.fp_len = 64;
4775 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4776 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4777 "2001:0:0:2/64 removed");
4778 connected_pfx.fp_len = 128;
4779 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4780 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4781 "2001:0:0:2::1/128 removed");
4782
4783 /*
4784 * -8 entries. -7 path-lists (1 was shared).
4785 */
4786 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4787 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004788 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004789 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004790 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004791 fib_entry_pool_size());
4792
4793 /*
4794 * now remove the VRF
4795 */
4796 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4797
4798 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4799 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004800 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004801 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004802 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004803 fib_entry_pool_size());
4804
4805 adj_unlock(ai_02);
4806 adj_unlock(ai_01);
4807
4808 /*
4809 * return the interfaces to up state
4810 */
4811 error = vnet_sw_interface_set_flags(vnet_get_main(),
4812 tm->hw[0]->sw_if_index,
4813 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4814 error = vnet_sw_interface_set_flags(vnet_get_main(),
4815 tm->hw[1]->sw_if_index,
4816 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4817
4818 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4819 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004820
4821 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004822}
4823
4824/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004825 * Test Attached Exports
4826 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004827static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004828fib_test_ae (void)
4829{
4830 const dpo_id_t *dpo, *dpo_drop;
4831 const u32 fib_index = 0;
4832 fib_node_index_t fei;
4833 test_main_t *tm;
4834 ip4_main_t *im;
4835
4836 tm = &test_main;
4837 im = &ip4_main;
4838
4839 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4840 adj_nbr_db_size());
4841
4842 /*
4843 * add interface routes. We'll assume this works. It's more rigorously
4844 * tested elsewhere.
4845 */
4846 fib_prefix_t local_pfx = {
4847 .fp_len = 24,
4848 .fp_proto = FIB_PROTOCOL_IP4,
4849 .fp_addr = {
4850 .ip4 = {
4851 /* 10.10.10.10 */
4852 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4853 },
4854 },
4855 };
4856
4857 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4858 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4859
4860 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4861
4862 fib_table_entry_update_one_path(fib_index, &local_pfx,
4863 FIB_SOURCE_INTERFACE,
4864 (FIB_ENTRY_FLAG_CONNECTED |
4865 FIB_ENTRY_FLAG_ATTACHED),
4866 FIB_PROTOCOL_IP4,
4867 NULL,
4868 tm->hw[0]->sw_if_index,
4869 ~0,
4870 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004871 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004872 FIB_ROUTE_PATH_FLAG_NONE);
4873 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4874 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4875 "attached interface route present");
4876
4877 local_pfx.fp_len = 32;
4878 fib_table_entry_update_one_path(fib_index, &local_pfx,
4879 FIB_SOURCE_INTERFACE,
4880 (FIB_ENTRY_FLAG_CONNECTED |
4881 FIB_ENTRY_FLAG_LOCAL),
4882 FIB_PROTOCOL_IP4,
4883 NULL,
4884 tm->hw[0]->sw_if_index,
4885 ~0, // invalid fib index
4886 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004887 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004888 FIB_ROUTE_PATH_FLAG_NONE);
4889 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4890
4891 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4892 "local interface route present");
4893
4894 /*
4895 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4896 */
4897 fib_prefix_t pfx_10_10_10_1_s_32 = {
4898 .fp_len = 32,
4899 .fp_proto = FIB_PROTOCOL_IP4,
4900 .fp_addr = {
4901 /* 10.10.10.1 */
4902 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4903 },
4904 };
4905 fib_node_index_t ai;
4906
4907 fib_table_entry_update_one_path(fib_index,
4908 &pfx_10_10_10_1_s_32,
4909 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004910 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004911 FIB_PROTOCOL_IP4,
4912 &pfx_10_10_10_1_s_32.fp_addr,
4913 tm->hw[0]->sw_if_index,
4914 ~0, // invalid fib index
4915 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004916 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004917 FIB_ROUTE_PATH_FLAG_NONE);
4918
4919 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4920 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4921 ai = fib_entry_get_adj(fei);
4922
4923 /*
4924 * create another FIB table into which routes will be imported
4925 */
4926 u32 import_fib_index1;
4927
4928 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4929
4930 /*
4931 * Add an attached route in the import FIB
4932 */
4933 local_pfx.fp_len = 24;
4934 fib_table_entry_update_one_path(import_fib_index1,
4935 &local_pfx,
4936 FIB_SOURCE_API,
4937 FIB_ENTRY_FLAG_NONE,
4938 FIB_PROTOCOL_IP4,
4939 NULL,
4940 tm->hw[0]->sw_if_index,
4941 ~0, // invalid fib index
4942 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004943 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004944 FIB_ROUTE_PATH_FLAG_NONE);
4945 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4946 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4947
4948 /*
4949 * check for the presence of the adj-fibs in the import table
4950 */
4951 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4952 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4953 FIB_TEST((ai == fib_entry_get_adj(fei)),
4954 "adj-fib1 Import uses same adj as export");
4955
4956 /*
4957 * check for the presence of the local in the import table
4958 */
4959 local_pfx.fp_len = 32;
4960 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4961 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4962
4963 /*
4964 * Add another adj-fin in the export table. Expect this
4965 * to get magically exported;
4966 */
4967 fib_prefix_t pfx_10_10_10_2_s_32 = {
4968 .fp_len = 32,
4969 .fp_proto = FIB_PROTOCOL_IP4,
4970 .fp_addr = {
4971 /* 10.10.10.2 */
4972 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
4973 },
4974 };
4975
4976 fib_table_entry_update_one_path(fib_index,
4977 &pfx_10_10_10_2_s_32,
4978 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004979 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004980 FIB_PROTOCOL_IP4,
4981 &pfx_10_10_10_2_s_32.fp_addr,
4982 tm->hw[0]->sw_if_index,
4983 ~0, // invalid fib index
4984 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004985 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004986 FIB_ROUTE_PATH_FLAG_NONE);
4987 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
4988 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
4989 ai = fib_entry_get_adj(fei);
4990
4991 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4992 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4993 FIB_TEST((ai == fib_entry_get_adj(fei)),
4994 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00004995 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
4996 "ADJ-fib2 imported flags %d",
4997 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004998
4999 /*
5000 * create a 2nd FIB table into which routes will be imported
5001 */
5002 u32 import_fib_index2;
5003
5004 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
5005
5006 /*
5007 * Add an attached route in the import FIB
5008 */
5009 local_pfx.fp_len = 24;
5010 fib_table_entry_update_one_path(import_fib_index2,
5011 &local_pfx,
5012 FIB_SOURCE_API,
5013 FIB_ENTRY_FLAG_NONE,
5014 FIB_PROTOCOL_IP4,
5015 NULL,
5016 tm->hw[0]->sw_if_index,
5017 ~0, // invalid fib index
5018 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005019 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005020 FIB_ROUTE_PATH_FLAG_NONE);
5021 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5022 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5023
5024 /*
5025 * check for the presence of all the adj-fibs and local in the import table
5026 */
5027 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5028 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5029 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5030 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5031 local_pfx.fp_len = 32;
5032 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5033 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5034
5035 /*
5036 * add a 3rd adj-fib. expect it to be exported to both tables.
5037 */
5038 fib_prefix_t pfx_10_10_10_3_s_32 = {
5039 .fp_len = 32,
5040 .fp_proto = FIB_PROTOCOL_IP4,
5041 .fp_addr = {
5042 /* 10.10.10.3 */
5043 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5044 },
5045 };
5046
5047 fib_table_entry_update_one_path(fib_index,
5048 &pfx_10_10_10_3_s_32,
5049 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00005050 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005051 FIB_PROTOCOL_IP4,
5052 &pfx_10_10_10_3_s_32.fp_addr,
5053 tm->hw[0]->sw_if_index,
5054 ~0, // invalid fib index
5055 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005056 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005057 FIB_ROUTE_PATH_FLAG_NONE);
5058 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5059 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5060 ai = fib_entry_get_adj(fei);
5061
5062 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5063 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5064 FIB_TEST((ai == fib_entry_get_adj(fei)),
5065 "Import uses same adj as export");
5066 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5067 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5068 FIB_TEST((ai == fib_entry_get_adj(fei)),
5069 "Import uses same adj as export");
5070
5071 /*
5072 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5073 */
5074 fib_table_entry_delete(fib_index,
5075 &pfx_10_10_10_3_s_32,
5076 FIB_SOURCE_ADJ);
5077
5078 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5079 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5080
5081 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5082 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5083
5084 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5085 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5086
5087 /*
5088 * remove the attached route from the 2nd FIB. expect the imported
5089 * entires to be removed
5090 */
5091 local_pfx.fp_len = 24;
5092 fib_table_entry_delete(import_fib_index2,
5093 &local_pfx,
5094 FIB_SOURCE_API);
5095 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5096 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5097
5098 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5099 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5100 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5101 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5102 local_pfx.fp_len = 32;
5103 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5104 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5105
5106 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5107 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5108 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5109 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5110 local_pfx.fp_len = 32;
5111 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5112 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5113
5114 /*
5115 * modify the route in FIB1 so it is no longer attached. expect the imported
5116 * entires to be removed
5117 */
5118 local_pfx.fp_len = 24;
5119 fib_table_entry_update_one_path(import_fib_index1,
5120 &local_pfx,
5121 FIB_SOURCE_API,
5122 FIB_ENTRY_FLAG_NONE,
5123 FIB_PROTOCOL_IP4,
5124 &pfx_10_10_10_2_s_32.fp_addr,
5125 tm->hw[0]->sw_if_index,
5126 ~0, // invalid fib index
5127 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005128 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005129 FIB_ROUTE_PATH_FLAG_NONE);
5130 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5131 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5132 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5133 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5134 local_pfx.fp_len = 32;
5135 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5136 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5137
5138 /*
5139 * modify it back to attached. expect the adj-fibs back
5140 */
5141 local_pfx.fp_len = 24;
5142 fib_table_entry_update_one_path(import_fib_index1,
5143 &local_pfx,
5144 FIB_SOURCE_API,
5145 FIB_ENTRY_FLAG_NONE,
5146 FIB_PROTOCOL_IP4,
5147 NULL,
5148 tm->hw[0]->sw_if_index,
5149 ~0, // invalid fib index
5150 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005151 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005152 FIB_ROUTE_PATH_FLAG_NONE);
5153 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5154 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5155 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5156 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5157 local_pfx.fp_len = 32;
5158 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5159 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5160
5161 /*
5162 * add a covering attached next-hop for the interface address, so we have
5163 * a valid adj to find when we check the forwarding tables
5164 */
5165 fib_prefix_t pfx_10_0_0_0_s_8 = {
5166 .fp_len = 8,
5167 .fp_proto = FIB_PROTOCOL_IP4,
5168 .fp_addr = {
5169 /* 10.0.0.0 */
5170 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5171 },
5172 };
5173
5174 fei = fib_table_entry_update_one_path(fib_index,
5175 &pfx_10_0_0_0_s_8,
5176 FIB_SOURCE_API,
5177 FIB_ENTRY_FLAG_NONE,
5178 FIB_PROTOCOL_IP4,
5179 &pfx_10_10_10_3_s_32.fp_addr,
5180 tm->hw[0]->sw_if_index,
5181 ~0, // invalid fib index
5182 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005183 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005184 FIB_ROUTE_PATH_FLAG_NONE);
5185 dpo = fib_entry_contribute_ip_forwarding(fei);
5186
5187 /*
5188 * remove the route in the export fib. expect the adj-fibs to be removed
5189 */
5190 local_pfx.fp_len = 24;
5191 fib_table_entry_delete(fib_index,
5192 &local_pfx,
5193 FIB_SOURCE_INTERFACE);
5194
5195 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5196 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5197 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5198 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5199 local_pfx.fp_len = 32;
5200 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5201 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5202
5203 /*
5204 * the adj-fibs in the export VRF are present in the FIB table,
5205 * but not installed in forwarding, since they have no attached cover.
5206 * Consequently a lookup in the MTRIE gives the adj for the covering
5207 * route 10.0.0.0/8.
5208 */
5209 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5210 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5211
5212 index_t lbi;
5213 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5214 FIB_TEST(lbi == dpo->dpoi_index,
5215 "10.10.10.1 forwards on \n%U not \n%U",
5216 format_load_balance, lbi, 0,
5217 format_dpo_id, dpo, 0);
5218 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5219 FIB_TEST(lbi == dpo->dpoi_index,
5220 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5221 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5222 FIB_TEST(lbi == dpo->dpoi_index,
5223 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5224
5225 /*
5226 * add the export prefix back, but not as attached.
5227 * No adj-fibs in export nor import tables
5228 */
5229 local_pfx.fp_len = 24;
5230 fei = fib_table_entry_update_one_path(fib_index,
5231 &local_pfx,
5232 FIB_SOURCE_API,
5233 FIB_ENTRY_FLAG_NONE,
5234 FIB_PROTOCOL_IP4,
5235 &pfx_10_10_10_1_s_32.fp_addr,
5236 tm->hw[0]->sw_if_index,
5237 ~0, // invalid fib index
5238 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005239 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005240 FIB_ROUTE_PATH_FLAG_NONE);
5241 dpo = fib_entry_contribute_ip_forwarding(fei);
5242
5243 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5244 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5245 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5246 FIB_TEST(lbi == dpo->dpoi_index,
5247 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5248 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5249 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5250 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5251 FIB_TEST(lbi == dpo->dpoi_index,
5252 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5253
5254 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5255 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5256 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5257 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5258 local_pfx.fp_len = 32;
5259 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5260 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5261
5262 /*
5263 * modify the export prefix so it is attached. expect all covereds to return
5264 */
5265 local_pfx.fp_len = 24;
5266 fib_table_entry_update_one_path(fib_index,
5267 &local_pfx,
5268 FIB_SOURCE_API,
5269 FIB_ENTRY_FLAG_NONE,
5270 FIB_PROTOCOL_IP4,
5271 NULL,
5272 tm->hw[0]->sw_if_index,
5273 ~0, // invalid fib index
5274 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005275 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005276 FIB_ROUTE_PATH_FLAG_NONE);
5277
5278 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5279 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5280 dpo = fib_entry_contribute_ip_forwarding(fei);
5281 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5282 "Adj-fib1 is not drop in export");
5283 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5284 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5285 local_pfx.fp_len = 32;
5286 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5287 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5288 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5289 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5290 dpo = fib_entry_contribute_ip_forwarding(fei);
5291 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5292 "Adj-fib1 is not drop in export");
5293 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5294 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5295 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5296 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5297 local_pfx.fp_len = 32;
5298 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5299 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5300
5301 /*
5302 * modify the export prefix so connected. no change.
5303 */
5304 local_pfx.fp_len = 24;
5305 fib_table_entry_update_one_path(fib_index, &local_pfx,
5306 FIB_SOURCE_INTERFACE,
5307 (FIB_ENTRY_FLAG_CONNECTED |
5308 FIB_ENTRY_FLAG_ATTACHED),
5309 FIB_PROTOCOL_IP4,
5310 NULL,
5311 tm->hw[0]->sw_if_index,
5312 ~0,
5313 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005314 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005315 FIB_ROUTE_PATH_FLAG_NONE);
5316
5317 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5318 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5319 dpo = fib_entry_contribute_ip_forwarding(fei);
5320 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5321 "Adj-fib1 is not drop in export");
5322 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5323 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5324 local_pfx.fp_len = 32;
5325 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5326 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5327 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5328 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5329 dpo = fib_entry_contribute_ip_forwarding(fei);
5330 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5331 "Adj-fib1 is not drop in export");
5332 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5333 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5334 local_pfx.fp_len = 32;
5335 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5336 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5337
5338 /*
5339 * CLEANUP
5340 */
5341 fib_table_entry_delete(fib_index,
5342 &pfx_10_0_0_0_s_8,
5343 FIB_SOURCE_API);
5344 fib_table_entry_delete(fib_index,
5345 &pfx_10_10_10_1_s_32,
5346 FIB_SOURCE_ADJ);
5347 fib_table_entry_delete(fib_index,
5348 &pfx_10_10_10_2_s_32,
5349 FIB_SOURCE_ADJ);
5350 local_pfx.fp_len = 32;
5351 fib_table_entry_delete(fib_index,
5352 &local_pfx,
5353 FIB_SOURCE_INTERFACE);
5354 local_pfx.fp_len = 24;
5355 fib_table_entry_delete(fib_index,
5356 &local_pfx,
5357 FIB_SOURCE_API);
5358 fib_table_entry_delete(fib_index,
5359 &local_pfx,
5360 FIB_SOURCE_INTERFACE);
5361 local_pfx.fp_len = 24;
5362 fib_table_entry_delete(import_fib_index1,
5363 &local_pfx,
5364 FIB_SOURCE_API);
5365
5366 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5367 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5368
5369 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5370 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005371
5372 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005373}
5374
Neale Rannsad422ed2016-11-02 14:20:04 +00005375
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005376/*
5377 * Test the recursive route route handling for GRE tunnels
5378 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005379static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005380fib_test_label (void)
5381{
5382 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;
5383 const u32 fib_index = 0;
5384 test_main_t *tm;
5385 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005386 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005387
5388 lb_count = pool_elts(load_balance_pool);
5389 tm = &test_main;
5390 im = &ip4_main;
5391
5392 /*
5393 * add interface routes. We'll assume this works. It's more rigorously
5394 * tested elsewhere.
5395 */
5396 fib_prefix_t local0_pfx = {
5397 .fp_len = 24,
5398 .fp_proto = FIB_PROTOCOL_IP4,
5399 .fp_addr = {
5400 .ip4 = {
5401 /* 10.10.10.10 */
5402 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5403 },
5404 },
5405 };
5406
5407 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5408 adj_nbr_db_size());
5409
5410 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5411 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5412
5413 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5414 FIB_SOURCE_INTERFACE,
5415 (FIB_ENTRY_FLAG_CONNECTED |
5416 FIB_ENTRY_FLAG_ATTACHED),
5417 FIB_PROTOCOL_IP4,
5418 NULL,
5419 tm->hw[0]->sw_if_index,
5420 ~0,
5421 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005422 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005423 FIB_ROUTE_PATH_FLAG_NONE);
5424 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5425 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5426 "attached interface route present");
5427
5428 local0_pfx.fp_len = 32;
5429 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5430 FIB_SOURCE_INTERFACE,
5431 (FIB_ENTRY_FLAG_CONNECTED |
5432 FIB_ENTRY_FLAG_LOCAL),
5433 FIB_PROTOCOL_IP4,
5434 NULL,
5435 tm->hw[0]->sw_if_index,
5436 ~0, // invalid fib index
5437 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005438 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005439 FIB_ROUTE_PATH_FLAG_NONE);
5440 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5441
5442 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5443 "local interface route present");
5444
5445 fib_prefix_t local1_pfx = {
5446 .fp_len = 24,
5447 .fp_proto = FIB_PROTOCOL_IP4,
5448 .fp_addr = {
5449 .ip4 = {
5450 /* 10.10.11.10 */
5451 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5452 },
5453 },
5454 };
5455
5456 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5457 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5458
5459 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5460 FIB_SOURCE_INTERFACE,
5461 (FIB_ENTRY_FLAG_CONNECTED |
5462 FIB_ENTRY_FLAG_ATTACHED),
5463 FIB_PROTOCOL_IP4,
5464 NULL,
5465 tm->hw[1]->sw_if_index,
5466 ~0,
5467 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005468 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005469 FIB_ROUTE_PATH_FLAG_NONE);
5470 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5471 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5472 "attached interface route present");
5473
5474 local1_pfx.fp_len = 32;
5475 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5476 FIB_SOURCE_INTERFACE,
5477 (FIB_ENTRY_FLAG_CONNECTED |
5478 FIB_ENTRY_FLAG_LOCAL),
5479 FIB_PROTOCOL_IP4,
5480 NULL,
5481 tm->hw[1]->sw_if_index,
5482 ~0, // invalid fib index
5483 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005484 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005485 FIB_ROUTE_PATH_FLAG_NONE);
5486 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5487
5488 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5489 "local interface route present");
5490
5491 ip46_address_t nh_10_10_10_1 = {
5492 .ip4 = {
5493 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5494 },
5495 };
5496 ip46_address_t nh_10_10_11_1 = {
5497 .ip4 = {
5498 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5499 },
5500 };
5501 ip46_address_t nh_10_10_11_2 = {
5502 .ip4 = {
5503 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5504 },
5505 };
5506
5507 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005508 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005509 &nh_10_10_11_1,
5510 tm->hw[1]->sw_if_index);
5511 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005512 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005513 &nh_10_10_11_2,
5514 tm->hw[1]->sw_if_index);
5515 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005516 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005517 &nh_10_10_10_1,
5518 tm->hw[0]->sw_if_index);
5519 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005520 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005521 &nh_10_10_11_2,
5522 tm->hw[1]->sw_if_index);
5523 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005524 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005525 &nh_10_10_11_1,
5526 tm->hw[1]->sw_if_index);
5527
5528 /*
5529 * Add an etry with one path with a real out-going label
5530 */
5531 fib_prefix_t pfx_1_1_1_1_s_32 = {
5532 .fp_len = 32,
5533 .fp_proto = FIB_PROTOCOL_IP4,
5534 .fp_addr = {
5535 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5536 },
5537 };
5538 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5539 .type = FT_LB_LABEL_O_ADJ,
5540 .label_o_adj = {
5541 .adj = ai_mpls_10_10_10_1,
5542 .label = 99,
5543 .eos = MPLS_EOS,
5544 },
5545 };
5546 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5547 .type = FT_LB_LABEL_O_ADJ,
5548 .label_o_adj = {
5549 .adj = ai_mpls_10_10_10_1,
5550 .label = 99,
5551 .eos = MPLS_NON_EOS,
5552 },
5553 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005554 mpls_label_t *l99 = NULL;
5555 vec_add1(l99, 99);
5556
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005557 fib_table_entry_update_one_path(fib_index,
5558 &pfx_1_1_1_1_s_32,
5559 FIB_SOURCE_API,
5560 FIB_ENTRY_FLAG_NONE,
5561 FIB_PROTOCOL_IP4,
5562 &nh_10_10_10_1,
5563 tm->hw[0]->sw_if_index,
5564 ~0, // invalid fib index
5565 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005566 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005567 FIB_ROUTE_PATH_FLAG_NONE);
5568
5569 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5570 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5571
5572 FIB_TEST(fib_test_validate_entry(fei,
5573 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5574 1,
5575 &l99_eos_o_10_10_10_1),
5576 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5577
5578 /*
5579 * add a path with an implicit NULL label
5580 */
5581 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5582 .type = FT_LB_ADJ,
5583 .adj = {
5584 .adj = ai_v4_10_10_11_1,
5585 },
5586 };
5587 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5588 .type = FT_LB_ADJ,
5589 .adj = {
5590 .adj = ai_mpls_10_10_11_1,
5591 },
5592 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005593 mpls_label_t *l_imp_null = NULL;
5594 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005595
5596 fei = fib_table_entry_path_add(fib_index,
5597 &pfx_1_1_1_1_s_32,
5598 FIB_SOURCE_API,
5599 FIB_ENTRY_FLAG_NONE,
5600 FIB_PROTOCOL_IP4,
5601 &nh_10_10_11_1,
5602 tm->hw[1]->sw_if_index,
5603 ~0, // invalid fib index
5604 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005605 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005606 FIB_ROUTE_PATH_FLAG_NONE);
5607
5608 FIB_TEST(fib_test_validate_entry(fei,
5609 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5610 2,
5611 &l99_eos_o_10_10_10_1,
5612 &a_o_10_10_11_1),
5613 "1.1.1.1/32 LB 2 buckets via: "
5614 "label 99 over 10.10.10.1, "
5615 "adj over 10.10.11.1");
5616
5617 /*
5618 * assign the route a local label
5619 */
5620 fib_table_entry_local_label_add(fib_index,
5621 &pfx_1_1_1_1_s_32,
5622 24001);
5623
5624 fib_prefix_t pfx_24001_eos = {
5625 .fp_proto = FIB_PROTOCOL_MPLS,
5626 .fp_label = 24001,
5627 .fp_eos = MPLS_EOS,
5628 };
5629 fib_prefix_t pfx_24001_neos = {
5630 .fp_proto = FIB_PROTOCOL_MPLS,
5631 .fp_label = 24001,
5632 .fp_eos = MPLS_NON_EOS,
5633 };
5634
5635 /*
5636 * The EOS entry should link to both the paths,
5637 * and use an ip adj for the imp-null
5638 * The NON-EOS entry should link to both the paths,
5639 * and use an mpls adj for the imp-null
5640 */
5641 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5642 &pfx_24001_eos);
5643 FIB_TEST(fib_test_validate_entry(fei,
5644 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5645 2,
5646 &l99_eos_o_10_10_10_1,
5647 &a_o_10_10_11_1),
5648 "24001/eos LB 2 buckets via: "
5649 "label 99 over 10.10.10.1, "
5650 "adj over 10.10.11.1");
5651
5652
5653 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5654 &pfx_24001_neos);
5655 FIB_TEST(fib_test_validate_entry(fei,
5656 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5657 2,
5658 &l99_neos_o_10_10_10_1,
5659 &a_mpls_o_10_10_11_1),
5660 "24001/neos LB 1 bucket via: "
5661 "label 99 over 10.10.10.1 ",
5662 "mpls-adj via 10.10.11.1");
5663
5664 /*
5665 * add an unlabelled path, this is excluded from the neos chains,
5666 */
5667 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5668 .type = FT_LB_ADJ,
5669 .adj = {
5670 .adj = ai_v4_10_10_11_2,
5671 },
5672 };
5673
5674 fei = fib_table_entry_path_add(fib_index,
5675 &pfx_1_1_1_1_s_32,
5676 FIB_SOURCE_API,
5677 FIB_ENTRY_FLAG_NONE,
5678 FIB_PROTOCOL_IP4,
5679 &nh_10_10_11_2,
5680 tm->hw[1]->sw_if_index,
5681 ~0, // invalid fib index
5682 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005683 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005684 FIB_ROUTE_PATH_FLAG_NONE);
5685
5686 FIB_TEST(fib_test_validate_entry(fei,
5687 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5688 16, // 3 choices spread over 16 buckets
5689 &l99_eos_o_10_10_10_1,
5690 &l99_eos_o_10_10_10_1,
5691 &l99_eos_o_10_10_10_1,
5692 &l99_eos_o_10_10_10_1,
5693 &l99_eos_o_10_10_10_1,
5694 &l99_eos_o_10_10_10_1,
5695 &a_o_10_10_11_1,
5696 &a_o_10_10_11_1,
5697 &a_o_10_10_11_1,
5698 &a_o_10_10_11_1,
5699 &a_o_10_10_11_1,
5700 &adj_o_10_10_11_2,
5701 &adj_o_10_10_11_2,
5702 &adj_o_10_10_11_2,
5703 &adj_o_10_10_11_2,
5704 &adj_o_10_10_11_2),
5705 "1.1.1.1/32 LB 16 buckets via: "
5706 "label 99 over 10.10.10.1, "
5707 "adj over 10.10.11.1",
5708 "adj over 10.10.11.2");
5709
5710 /*
5711 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5712 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005713 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005714 fib_entry_contribute_forwarding(fei,
5715 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5716 &non_eos_1_1_1_1);
5717
5718 /*
5719 * n-eos has only the 2 labelled paths
5720 */
5721 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5722 &pfx_24001_neos);
5723
5724 FIB_TEST(fib_test_validate_entry(fei,
5725 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5726 2,
5727 &l99_neos_o_10_10_10_1,
5728 &a_mpls_o_10_10_11_1),
5729 "24001/neos LB 2 buckets via: "
5730 "label 99 over 10.10.10.1, "
5731 "adj-mpls over 10.10.11.2");
5732
5733 /*
5734 * A labelled recursive
5735 */
5736 fib_prefix_t pfx_2_2_2_2_s_32 = {
5737 .fp_len = 32,
5738 .fp_proto = FIB_PROTOCOL_IP4,
5739 .fp_addr = {
5740 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5741 },
5742 };
5743 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5744 .type = FT_LB_LABEL_O_LB,
5745 .label_o_lb = {
5746 .lb = non_eos_1_1_1_1.dpoi_index,
5747 .label = 1600,
5748 .eos = MPLS_EOS,
5749 },
5750 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005751 mpls_label_t *l1600 = NULL;
5752 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005753
5754 fib_table_entry_update_one_path(fib_index,
5755 &pfx_2_2_2_2_s_32,
5756 FIB_SOURCE_API,
5757 FIB_ENTRY_FLAG_NONE,
5758 FIB_PROTOCOL_IP4,
5759 &pfx_1_1_1_1_s_32.fp_addr,
5760 ~0,
5761 fib_index,
5762 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005763 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005764 FIB_ROUTE_PATH_FLAG_NONE);
5765
5766 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5767 FIB_TEST(fib_test_validate_entry(fei,
5768 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5769 1,
5770 &l1600_eos_o_1_1_1_1),
5771 "2.2.2.2.2/32 LB 1 buckets via: "
5772 "label 1600 over 1.1.1.1");
5773
Neale Ranns948e00f2016-10-20 13:39:34 +01005774 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005775 index_t urpfi;
5776
5777 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5778 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5779
5780 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5781 "uRPF check for 2.2.2.2/32 on %d OK",
5782 tm->hw[0]->sw_if_index);
5783 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5784 "uRPF check for 2.2.2.2/32 on %d OK",
5785 tm->hw[1]->sw_if_index);
5786 FIB_TEST(!fib_urpf_check(urpfi, 99),
5787 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5788 99);
5789
5790 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5791 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5792 "Shared uRPF on IP and non-EOS chain");
5793
5794 dpo_reset(&dpo_44);
5795
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005796 /*
5797 * we are holding a lock on the non-eos LB of the via-entry.
5798 * do a PIC-core failover by shutting the link of the via-entry.
5799 *
5800 * shut down the link with the valid label
5801 */
5802 vnet_sw_interface_set_flags(vnet_get_main(),
5803 tm->hw[0]->sw_if_index,
5804 0);
5805
5806 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5807 FIB_TEST(fib_test_validate_entry(fei,
5808 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5809 2,
5810 &a_o_10_10_11_1,
5811 &adj_o_10_10_11_2),
5812 "1.1.1.1/32 LB 2 buckets via: "
5813 "adj over 10.10.11.1, ",
5814 "adj-v4 over 10.10.11.2");
5815
5816 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5817 &pfx_24001_eos);
5818 FIB_TEST(fib_test_validate_entry(fei,
5819 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5820 2,
5821 &a_o_10_10_11_1,
5822 &adj_o_10_10_11_2),
5823 "24001/eos LB 2 buckets via: "
5824 "adj over 10.10.11.1, ",
5825 "adj-v4 over 10.10.11.2");
5826
5827 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5828 &pfx_24001_neos);
5829 FIB_TEST(fib_test_validate_entry(fei,
5830 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5831 1,
5832 &a_mpls_o_10_10_11_1),
5833 "24001/neos LB 1 buckets via: "
5834 "adj-mpls over 10.10.11.2");
5835
5836 /*
5837 * test that the pre-failover load-balance has been in-place
5838 * modified
5839 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005840 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005841 fib_entry_contribute_forwarding(fei,
5842 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5843 &current);
5844
5845 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5846 &current),
5847 "PIC-core LB inplace modified %U %U",
5848 format_dpo_id, &non_eos_1_1_1_1, 0,
5849 format_dpo_id, &current, 0);
5850
5851 dpo_reset(&non_eos_1_1_1_1);
5852 dpo_reset(&current);
5853
5854 /*
5855 * no-shut the link with the valid label
5856 */
5857 vnet_sw_interface_set_flags(vnet_get_main(),
5858 tm->hw[0]->sw_if_index,
5859 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5860
5861 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5862 FIB_TEST(fib_test_validate_entry(fei,
5863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5864 16, // 3 choices spread over 16 buckets
5865 &l99_eos_o_10_10_10_1,
5866 &l99_eos_o_10_10_10_1,
5867 &l99_eos_o_10_10_10_1,
5868 &l99_eos_o_10_10_10_1,
5869 &l99_eos_o_10_10_10_1,
5870 &l99_eos_o_10_10_10_1,
5871 &a_o_10_10_11_1,
5872 &a_o_10_10_11_1,
5873 &a_o_10_10_11_1,
5874 &a_o_10_10_11_1,
5875 &a_o_10_10_11_1,
5876 &adj_o_10_10_11_2,
5877 &adj_o_10_10_11_2,
5878 &adj_o_10_10_11_2,
5879 &adj_o_10_10_11_2,
5880 &adj_o_10_10_11_2),
5881 "1.1.1.1/32 LB 16 buckets via: "
5882 "label 99 over 10.10.10.1, "
5883 "adj over 10.10.11.1",
5884 "adj-v4 over 10.10.11.2");
5885
5886
5887 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5888 &pfx_24001_eos);
5889 FIB_TEST(fib_test_validate_entry(fei,
5890 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5891 16, // 3 choices spread over 16 buckets
5892 &l99_eos_o_10_10_10_1,
5893 &l99_eos_o_10_10_10_1,
5894 &l99_eos_o_10_10_10_1,
5895 &l99_eos_o_10_10_10_1,
5896 &l99_eos_o_10_10_10_1,
5897 &l99_eos_o_10_10_10_1,
5898 &a_o_10_10_11_1,
5899 &a_o_10_10_11_1,
5900 &a_o_10_10_11_1,
5901 &a_o_10_10_11_1,
5902 &a_o_10_10_11_1,
5903 &adj_o_10_10_11_2,
5904 &adj_o_10_10_11_2,
5905 &adj_o_10_10_11_2,
5906 &adj_o_10_10_11_2,
5907 &adj_o_10_10_11_2),
5908 "24001/eos LB 16 buckets via: "
5909 "label 99 over 10.10.10.1, "
5910 "adj over 10.10.11.1",
5911 "adj-v4 over 10.10.11.2");
5912
5913 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5914 &pfx_24001_neos);
5915 FIB_TEST(fib_test_validate_entry(fei,
5916 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5917 2,
5918 &l99_neos_o_10_10_10_1,
5919 &a_mpls_o_10_10_11_1),
5920 "24001/neos LB 2 buckets via: "
5921 "label 99 over 10.10.10.1, "
5922 "adj-mpls over 10.10.11.2");
5923
5924 /*
5925 * remove the first path with the valid label
5926 */
5927 fib_table_entry_path_remove(fib_index,
5928 &pfx_1_1_1_1_s_32,
5929 FIB_SOURCE_API,
5930 FIB_PROTOCOL_IP4,
5931 &nh_10_10_10_1,
5932 tm->hw[0]->sw_if_index,
5933 ~0, // invalid fib index
5934 1,
5935 FIB_ROUTE_PATH_FLAG_NONE);
5936
5937 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5938 FIB_TEST(fib_test_validate_entry(fei,
5939 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5940 2,
5941 &a_o_10_10_11_1,
5942 &adj_o_10_10_11_2),
5943 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07005944 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005945 "adj-v4 over 10.10.11.2");
5946
5947 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5948 &pfx_24001_eos);
5949 FIB_TEST(fib_test_validate_entry(fei,
5950 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5951 2,
5952 &a_o_10_10_11_1,
5953 &adj_o_10_10_11_2),
5954 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07005955 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005956 "adj-v4 over 10.10.11.2");
5957
5958 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5959 &pfx_24001_neos);
5960
5961 FIB_TEST(fib_test_validate_entry(fei,
5962 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5963 1,
5964 &a_mpls_o_10_10_11_1),
5965 "24001/neos LB 1 buckets via: "
5966 "adj-mpls over 10.10.11.2");
5967
5968 /*
5969 * remove the other path with a valid label
5970 */
5971 fib_test_lb_bucket_t bucket_drop = {
5972 .type = FT_LB_SPECIAL,
5973 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005974 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005975 },
5976 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07005977 fib_test_lb_bucket_t mpls_bucket_drop = {
5978 .type = FT_LB_SPECIAL,
5979 .special = {
5980 .adj = DPO_PROTO_MPLS,
5981 },
5982 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005983
5984 fib_table_entry_path_remove(fib_index,
5985 &pfx_1_1_1_1_s_32,
5986 FIB_SOURCE_API,
5987 FIB_PROTOCOL_IP4,
5988 &nh_10_10_11_1,
5989 tm->hw[1]->sw_if_index,
5990 ~0, // invalid fib index
5991 1,
5992 FIB_ROUTE_PATH_FLAG_NONE);
5993
5994 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5995 FIB_TEST(fib_test_validate_entry(fei,
5996 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5997 1,
5998 &adj_o_10_10_11_2),
5999 "1.1.1.1/32 LB 1 buckets via: "
6000 "adj over 10.10.11.2");
6001
6002 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6003 &pfx_24001_eos);
6004 FIB_TEST(fib_test_validate_entry(fei,
6005 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6006 1,
6007 &adj_o_10_10_11_2),
6008 "24001/eos LB 1 buckets via: "
6009 "adj over 10.10.11.2");
6010
6011 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6012 &pfx_24001_neos);
6013 FIB_TEST(fib_test_validate_entry(fei,
6014 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006015 1,
6016 &mpls_bucket_drop),
6017 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006018
6019 /*
6020 * add back the path with the valid label
6021 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006022 l99 = NULL;
6023 vec_add1(l99, 99);
6024
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006025 fib_table_entry_path_add(fib_index,
6026 &pfx_1_1_1_1_s_32,
6027 FIB_SOURCE_API,
6028 FIB_ENTRY_FLAG_NONE,
6029 FIB_PROTOCOL_IP4,
6030 &nh_10_10_10_1,
6031 tm->hw[0]->sw_if_index,
6032 ~0, // invalid fib index
6033 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006034 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006035 FIB_ROUTE_PATH_FLAG_NONE);
6036
6037 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6038 FIB_TEST(fib_test_validate_entry(fei,
6039 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6040 2,
6041 &l99_eos_o_10_10_10_1,
6042 &adj_o_10_10_11_2),
6043 "1.1.1.1/32 LB 2 buckets via: "
6044 "label 99 over 10.10.10.1, "
6045 "adj over 10.10.11.2");
6046
6047 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6048 &pfx_24001_eos);
6049 FIB_TEST(fib_test_validate_entry(fei,
6050 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6051 2,
6052 &l99_eos_o_10_10_10_1,
6053 &adj_o_10_10_11_2),
6054 "24001/eos LB 2 buckets via: "
6055 "label 99 over 10.10.10.1, "
6056 "adj over 10.10.11.2");
6057
6058 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6059 &pfx_24001_neos);
6060 FIB_TEST(fib_test_validate_entry(fei,
6061 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6062 1,
6063 &l99_neos_o_10_10_10_1),
6064 "24001/neos LB 1 buckets via: "
6065 "label 99 over 10.10.10.1");
6066
6067 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006068 * change the local label
6069 */
6070 fib_table_entry_local_label_add(fib_index,
6071 &pfx_1_1_1_1_s_32,
6072 25005);
6073
6074 fib_prefix_t pfx_25005_eos = {
6075 .fp_proto = FIB_PROTOCOL_MPLS,
6076 .fp_label = 25005,
6077 .fp_eos = MPLS_EOS,
6078 };
6079 fib_prefix_t pfx_25005_neos = {
6080 .fp_proto = FIB_PROTOCOL_MPLS,
6081 .fp_label = 25005,
6082 .fp_eos = MPLS_NON_EOS,
6083 };
6084
6085 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6086 fib_table_lookup(fib_index, &pfx_24001_eos)),
6087 "24001/eos removed after label change");
6088 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6089 fib_table_lookup(fib_index, &pfx_24001_neos)),
6090 "24001/eos removed after label change");
6091
6092 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6093 &pfx_25005_eos);
6094 FIB_TEST(fib_test_validate_entry(fei,
6095 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6096 2,
6097 &l99_eos_o_10_10_10_1,
6098 &adj_o_10_10_11_2),
6099 "25005/eos LB 2 buckets via: "
6100 "label 99 over 10.10.10.1, "
6101 "adj over 10.10.11.2");
6102
6103 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6104 &pfx_25005_neos);
6105 FIB_TEST(fib_test_validate_entry(fei,
6106 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6107 1,
6108 &l99_neos_o_10_10_10_1),
6109 "25005/neos LB 1 buckets via: "
6110 "label 99 over 10.10.10.1");
6111
6112 /*
6113 * remove the local label.
6114 * the check that the MPLS entries are gone is done by the fact the
6115 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006116 */
6117 fib_table_entry_local_label_remove(fib_index,
6118 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006119 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006120
6121 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6122 FIB_TEST(fib_test_validate_entry(fei,
6123 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6124 2,
6125 &l99_eos_o_10_10_10_1,
6126 &adj_o_10_10_11_2),
6127 "24001/eos LB 2 buckets via: "
6128 "label 99 over 10.10.10.1, "
6129 "adj over 10.10.11.2");
6130
6131 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6132 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6133 "No more MPLS FIB entries => table removed");
6134
6135 /*
6136 * add another via-entry for the recursive
6137 */
6138 fib_prefix_t pfx_1_1_1_2_s_32 = {
6139 .fp_len = 32,
6140 .fp_proto = FIB_PROTOCOL_IP4,
6141 .fp_addr = {
6142 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6143 },
6144 };
6145 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6146 .type = FT_LB_LABEL_O_ADJ,
6147 .label_o_adj = {
6148 .adj = ai_mpls_10_10_10_1,
6149 .label = 101,
6150 .eos = MPLS_EOS,
6151 },
6152 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006153 mpls_label_t *l101 = NULL;
6154 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006155
6156 fei = fib_table_entry_update_one_path(fib_index,
6157 &pfx_1_1_1_2_s_32,
6158 FIB_SOURCE_API,
6159 FIB_ENTRY_FLAG_NONE,
6160 FIB_PROTOCOL_IP4,
6161 &nh_10_10_10_1,
6162 tm->hw[0]->sw_if_index,
6163 ~0, // invalid fib index
6164 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006165 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006166 FIB_ROUTE_PATH_FLAG_NONE);
6167
6168 FIB_TEST(fib_test_validate_entry(fei,
6169 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6170 1,
6171 &l101_eos_o_10_10_10_1),
6172 "1.1.1.2/32 LB 1 buckets via: "
6173 "label 101 over 10.10.10.1");
6174
Neale Ranns948e00f2016-10-20 13:39:34 +01006175 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006176 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6177 &pfx_1_1_1_1_s_32),
6178 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6179 &non_eos_1_1_1_1);
6180 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6181 &pfx_1_1_1_2_s_32),
6182 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6183 &non_eos_1_1_1_2);
6184
6185 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6186 .type = FT_LB_LABEL_O_LB,
6187 .label_o_lb = {
6188 .lb = non_eos_1_1_1_2.dpoi_index,
6189 .label = 1601,
6190 .eos = MPLS_EOS,
6191 },
6192 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006193 mpls_label_t *l1601 = NULL;
6194 vec_add1(l1601, 1601);
6195
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006196 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6197
6198 fei = fib_table_entry_path_add(fib_index,
6199 &pfx_2_2_2_2_s_32,
6200 FIB_SOURCE_API,
6201 FIB_ENTRY_FLAG_NONE,
6202 FIB_PROTOCOL_IP4,
6203 &pfx_1_1_1_2_s_32.fp_addr,
6204 ~0,
6205 fib_index,
6206 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006207 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006208 FIB_ROUTE_PATH_FLAG_NONE);
6209
6210 FIB_TEST(fib_test_validate_entry(fei,
6211 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6212 2,
6213 &l1600_eos_o_1_1_1_1,
6214 &l1601_eos_o_1_1_1_2),
6215 "2.2.2.2/32 LB 2 buckets via: "
6216 "label 1600 via 1.1,1.1, "
6217 "label 16001 via 1.1.1.2");
6218
6219 /*
6220 * update the via-entry so it no longer has an imp-null path.
6221 * the LB for the recursive can use an imp-null
6222 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006223 l_imp_null = NULL;
6224 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6225
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006226 fei = fib_table_entry_update_one_path(fib_index,
6227 &pfx_1_1_1_2_s_32,
6228 FIB_SOURCE_API,
6229 FIB_ENTRY_FLAG_NONE,
6230 FIB_PROTOCOL_IP4,
6231 &nh_10_10_11_1,
6232 tm->hw[1]->sw_if_index,
6233 ~0, // invalid fib index
6234 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006235 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006236 FIB_ROUTE_PATH_FLAG_NONE);
6237
6238 FIB_TEST(fib_test_validate_entry(fei,
6239 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6240 1,
6241 &a_o_10_10_11_1),
6242 "1.1.1.2/32 LB 1 buckets via: "
6243 "adj 10.10.11.1");
6244
6245 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6246 FIB_TEST(fib_test_validate_entry(fei,
6247 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6248 2,
6249 &l1600_eos_o_1_1_1_1,
6250 &l1601_eos_o_1_1_1_2),
6251 "2.2.2.2/32 LB 2 buckets via: "
6252 "label 1600 via 1.1,1.1, "
6253 "label 16001 via 1.1.1.2");
6254
6255 /*
6256 * update the via-entry so it no longer has labelled paths.
6257 * the LB for the recursive should exclue this via form its LB
6258 */
6259 fei = fib_table_entry_update_one_path(fib_index,
6260 &pfx_1_1_1_2_s_32,
6261 FIB_SOURCE_API,
6262 FIB_ENTRY_FLAG_NONE,
6263 FIB_PROTOCOL_IP4,
6264 &nh_10_10_11_1,
6265 tm->hw[1]->sw_if_index,
6266 ~0, // invalid fib index
6267 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006268 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006269 FIB_ROUTE_PATH_FLAG_NONE);
6270
6271 FIB_TEST(fib_test_validate_entry(fei,
6272 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6273 1,
6274 &a_o_10_10_11_1),
6275 "1.1.1.2/32 LB 1 buckets via: "
6276 "adj 10.10.11.1");
6277
6278 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6279 FIB_TEST(fib_test_validate_entry(fei,
6280 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6281 1,
6282 &l1600_eos_o_1_1_1_1),
6283 "2.2.2.2/32 LB 1 buckets via: "
6284 "label 1600 via 1.1,1.1");
6285
6286 dpo_reset(&non_eos_1_1_1_1);
6287 dpo_reset(&non_eos_1_1_1_2);
6288
6289 /*
6290 * Add a recursive with no out-labels. We expect to use the IP of the via
6291 */
6292 fib_prefix_t pfx_2_2_2_3_s_32 = {
6293 .fp_len = 32,
6294 .fp_proto = FIB_PROTOCOL_IP4,
6295 .fp_addr = {
6296 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6297 },
6298 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006299 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006300
6301 fib_table_entry_update_one_path(fib_index,
6302 &pfx_2_2_2_3_s_32,
6303 FIB_SOURCE_API,
6304 FIB_ENTRY_FLAG_NONE,
6305 FIB_PROTOCOL_IP4,
6306 &pfx_1_1_1_1_s_32.fp_addr,
6307 ~0,
6308 fib_index,
6309 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006310 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006311 FIB_ROUTE_PATH_FLAG_NONE);
6312
6313 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6314 &pfx_1_1_1_1_s_32),
6315 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6316 &ip_1_1_1_1);
6317
6318 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6319 .type = FT_LB_O_LB,
6320 .lb = {
6321 .lb = ip_1_1_1_1.dpoi_index,
6322 },
6323 };
6324
6325 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6326 FIB_TEST(fib_test_validate_entry(fei,
6327 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6328 1,
6329 &ip_o_1_1_1_1),
6330 "2.2.2.2.3/32 LB 1 buckets via: "
6331 "ip 1.1.1.1");
6332
6333 /*
6334 * Add a recursive with an imp-null out-label.
6335 * We expect to use the IP of the via
6336 */
6337 fib_prefix_t pfx_2_2_2_4_s_32 = {
6338 .fp_len = 32,
6339 .fp_proto = FIB_PROTOCOL_IP4,
6340 .fp_addr = {
6341 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6342 },
6343 };
6344
6345 fib_table_entry_update_one_path(fib_index,
6346 &pfx_2_2_2_4_s_32,
6347 FIB_SOURCE_API,
6348 FIB_ENTRY_FLAG_NONE,
6349 FIB_PROTOCOL_IP4,
6350 &pfx_1_1_1_1_s_32.fp_addr,
6351 ~0,
6352 fib_index,
6353 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006354 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006355 FIB_ROUTE_PATH_FLAG_NONE);
6356
6357 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6358 FIB_TEST(fib_test_validate_entry(fei,
6359 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6360 1,
6361 &ip_o_1_1_1_1),
6362 "2.2.2.2.4/32 LB 1 buckets via: "
6363 "ip 1.1.1.1");
6364
6365 dpo_reset(&ip_1_1_1_1);
6366
6367 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006368 * Create an entry with a deep label stack
6369 */
6370 fib_prefix_t pfx_2_2_5_5_s_32 = {
6371 .fp_len = 32,
6372 .fp_proto = FIB_PROTOCOL_IP4,
6373 .fp_addr = {
6374 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6375 },
6376 };
6377 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6378 .type = FT_LB_LABEL_STACK_O_ADJ,
6379 .label_stack_o_adj = {
6380 .adj = ai_mpls_10_10_11_1,
6381 .label_stack_size = 8,
6382 .label_stack = {
6383 200, 201, 202, 203, 204, 205, 206, 207
6384 },
6385 .eos = MPLS_EOS,
6386 },
6387 };
6388 mpls_label_t *label_stack = NULL;
6389 vec_validate(label_stack, 7);
6390 for (ii = 0; ii < 8; ii++)
6391 {
6392 label_stack[ii] = ii + 200;
6393 }
6394
6395 fei = fib_table_entry_update_one_path(fib_index,
6396 &pfx_2_2_5_5_s_32,
6397 FIB_SOURCE_API,
6398 FIB_ENTRY_FLAG_NONE,
6399 FIB_PROTOCOL_IP4,
6400 &nh_10_10_11_1,
6401 tm->hw[1]->sw_if_index,
6402 ~0, // invalid fib index
6403 1,
6404 label_stack,
6405 FIB_ROUTE_PATH_FLAG_NONE);
6406
6407 FIB_TEST(fib_test_validate_entry(fei,
6408 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6409 1,
6410 &ls_eos_o_10_10_10_1),
6411 "2.2.5.5/32 LB 1 buckets via: "
6412 "adj 10.10.11.1");
6413 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6414
6415 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006416 * cleanup
6417 */
6418 fib_table_entry_delete(fib_index,
6419 &pfx_1_1_1_2_s_32,
6420 FIB_SOURCE_API);
6421
6422 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6423 FIB_TEST(fib_test_validate_entry(fei,
6424 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6425 1,
6426 &l1600_eos_o_1_1_1_1),
6427 "2.2.2.2/32 LB 1 buckets via: "
6428 "label 1600 via 1.1,1.1");
6429
6430 fib_table_entry_delete(fib_index,
6431 &pfx_1_1_1_1_s_32,
6432 FIB_SOURCE_API);
6433
6434 FIB_TEST(fib_test_validate_entry(fei,
6435 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6436 1,
6437 &bucket_drop),
6438 "2.2.2.2/32 LB 1 buckets via: DROP");
6439
6440 fib_table_entry_delete(fib_index,
6441 &pfx_2_2_2_2_s_32,
6442 FIB_SOURCE_API);
6443 fib_table_entry_delete(fib_index,
6444 &pfx_2_2_2_3_s_32,
6445 FIB_SOURCE_API);
6446 fib_table_entry_delete(fib_index,
6447 &pfx_2_2_2_4_s_32,
6448 FIB_SOURCE_API);
6449
6450 adj_unlock(ai_mpls_10_10_10_1);
6451 adj_unlock(ai_mpls_10_10_11_2);
6452 adj_unlock(ai_v4_10_10_11_1);
6453 adj_unlock(ai_v4_10_10_11_2);
6454 adj_unlock(ai_mpls_10_10_11_1);
6455
6456 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6457 adj_nbr_db_size());
6458
6459 local0_pfx.fp_len = 32;
6460 fib_table_entry_delete(fib_index,
6461 &local0_pfx,
6462 FIB_SOURCE_INTERFACE);
6463 local0_pfx.fp_len = 24;
6464 fib_table_entry_delete(fib_index,
6465 &local0_pfx,
6466 FIB_SOURCE_INTERFACE);
6467 local1_pfx.fp_len = 32;
6468 fib_table_entry_delete(fib_index,
6469 &local1_pfx,
6470 FIB_SOURCE_INTERFACE);
6471 local1_pfx.fp_len = 24;
6472 fib_table_entry_delete(fib_index,
6473 &local1_pfx,
6474 FIB_SOURCE_INTERFACE);
6475
6476 /*
6477 * +1 for the drop LB in the MPLS tables.
6478 */
6479 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6480 "Load-balance resources freed %d of %d",
6481 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006482
6483 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006484}
6485
6486#define N_TEST_CHILDREN 4
6487#define PARENT_INDEX 0
6488
6489typedef struct fib_node_test_t_
6490{
6491 fib_node_t node;
6492 u32 sibling;
6493 u32 index;
6494 fib_node_back_walk_ctx_t *ctxs;
6495 u32 destroyed;
6496} fib_node_test_t;
6497
6498static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6499
6500#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6501
6502#define FOR_EACH_TEST_CHILD(_tc) \
6503 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6504 ii < N_TEST_CHILDREN+1; \
6505 ii++, (_tc) = &fib_test_nodes[ii])
6506
6507static fib_node_t *
6508fib_test_child_get_node (fib_node_index_t index)
6509{
6510 return (&fib_test_nodes[index].node);
6511}
6512
6513static int fib_test_walk_spawns_walks;
6514
6515static fib_node_back_walk_rc_t
6516fib_test_child_back_walk_notify (fib_node_t *node,
6517 fib_node_back_walk_ctx_t *ctx)
6518{
6519 fib_node_test_t *tc = (fib_node_test_t*) node;
6520
6521 vec_add1(tc->ctxs, *ctx);
6522
6523 if (1 == fib_test_walk_spawns_walks)
6524 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6525 if (2 == fib_test_walk_spawns_walks)
6526 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6527 FIB_WALK_PRIORITY_HIGH, ctx);
6528
6529 return (FIB_NODE_BACK_WALK_CONTINUE);
6530}
6531
6532static void
6533fib_test_child_last_lock_gone (fib_node_t *node)
6534{
6535 fib_node_test_t *tc = (fib_node_test_t *)node;
6536
6537 tc->destroyed = 1;
6538}
6539
6540/**
6541 * The FIB walk's graph node virtual function table
6542 */
6543static const fib_node_vft_t fib_test_child_vft = {
6544 .fnv_get = fib_test_child_get_node,
6545 .fnv_last_lock = fib_test_child_last_lock_gone,
6546 .fnv_back_walk = fib_test_child_back_walk_notify,
6547};
6548
6549/*
6550 * the function (that should have been static but isn't so I can do this)
6551 * that processes the walk from the async queue,
6552 */
6553f64 fib_walk_process_queues(vlib_main_t * vm,
6554 const f64 quota);
6555u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6556
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006557static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006558fib_test_walk (void)
6559{
6560 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6561 fib_node_test_t *tc;
6562 vlib_main_t *vm;
6563 u32 ii;
6564
6565 vm = vlib_get_main();
6566 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6567
6568 /*
6569 * init a fake node on which we will add children
6570 */
6571 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6572 FIB_NODE_TYPE_TEST);
6573
6574 FOR_EACH_TEST_CHILD(tc)
6575 {
6576 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6577 fib_node_lock(&tc->node);
6578 tc->ctxs = NULL;
6579 tc->index = ii;
6580 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6581 PARENT_INDEX,
6582 FIB_NODE_TYPE_TEST, ii);
6583 }
6584
6585 /*
6586 * enqueue a walk across the parents children.
6587 */
Neale Ranns450cd302016-11-09 17:49:42 +00006588 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006589
6590 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6591 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6592 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6593 "Parent has %d children pre-walk",
6594 fib_node_list_get_size(PARENT()->fn_children));
6595
6596 /*
6597 * give the walk a large amount of time so it gets to the end
6598 */
6599 fib_walk_process_queues(vm, 1);
6600
6601 FOR_EACH_TEST_CHILD(tc)
6602 {
6603 FIB_TEST(1 == vec_len(tc->ctxs),
6604 "%d child visitsed %d times",
6605 ii, vec_len(tc->ctxs));
6606 vec_free(tc->ctxs);
6607 }
6608 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6609 "Queue is empty post walk");
6610 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6611 "Parent has %d children post walk",
6612 fib_node_list_get_size(PARENT()->fn_children));
6613
6614 /*
6615 * walk again. should be no increase in the number of visits, since
6616 * the walk will have terminated.
6617 */
6618 fib_walk_process_queues(vm, 1);
6619
6620 FOR_EACH_TEST_CHILD(tc)
6621 {
6622 FIB_TEST(0 == vec_len(tc->ctxs),
6623 "%d child visitsed %d times",
6624 ii, vec_len(tc->ctxs));
6625 }
6626
6627 /*
6628 * schedule a low and hig priority walk. expect the high to be performed
6629 * before the low.
6630 * schedule the high prio walk first so that it is further from the head
6631 * of the dependency list. that way it won't merge with the low one.
6632 */
6633 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6634 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6635
6636 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6637 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6638 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6639 FIB_WALK_PRIORITY_LOW, &low_ctx);
6640
6641 fib_walk_process_queues(vm, 1);
6642
6643 FOR_EACH_TEST_CHILD(tc)
6644 {
6645 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6646 "%d child visitsed by high prio walk", ii);
6647 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6648 "%d child visitsed by low prio walk", ii);
6649 vec_free(tc->ctxs);
6650 }
6651 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6652 "Queue is empty post prio walk");
6653 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6654 "Parent has %d children post prio walk",
6655 fib_node_list_get_size(PARENT()->fn_children));
6656
6657 /*
6658 * schedule 2 walks of the same priority that can be megred.
6659 * expect that each child is thus visited only once.
6660 */
6661 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6662 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6663
6664 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6665 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6666 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6667 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6668
6669 fib_walk_process_queues(vm, 1);
6670
6671 FOR_EACH_TEST_CHILD(tc)
6672 {
6673 FIB_TEST(1 == vec_len(tc->ctxs),
6674 "%d child visitsed %d times during merge walk",
6675 ii, vec_len(tc->ctxs));
6676 vec_free(tc->ctxs);
6677 }
6678 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6679 "Queue is empty post merge walk");
6680 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6681 "Parent has %d children post merge walk",
6682 fib_node_list_get_size(PARENT()->fn_children));
6683
6684 /*
6685 * schedule 2 walks of the same priority that cannot be megred.
6686 * expect that each child is thus visited twice and in the order
6687 * in which the walks were scheduled.
6688 */
6689 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6690 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6691
6692 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6693 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6694 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6695 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6696
6697 fib_walk_process_queues(vm, 1);
6698
6699 FOR_EACH_TEST_CHILD(tc)
6700 {
6701 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6702 "%d child visitsed by high prio walk", ii);
6703 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6704 "%d child visitsed by low prio walk", ii);
6705 vec_free(tc->ctxs);
6706 }
6707 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6708 "Queue is empty post no-merge walk");
6709 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6710 "Parent has %d children post no-merge walk",
6711 fib_node_list_get_size(PARENT()->fn_children));
6712
6713 /*
6714 * schedule a walk that makes one one child progress.
6715 * we do this by giving the queue draining process zero
6716 * time quanta. it's a do..while loop, so it does something.
6717 */
Neale Ranns450cd302016-11-09 17:49:42 +00006718 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006719
6720 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6721 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6722 fib_walk_process_queues(vm, 0);
6723
6724 FOR_EACH_TEST_CHILD(tc)
6725 {
6726 if (ii == N_TEST_CHILDREN)
6727 {
6728 FIB_TEST(1 == vec_len(tc->ctxs),
6729 "%d child visitsed %d times in zero quanta walk",
6730 ii, vec_len(tc->ctxs));
6731 }
6732 else
6733 {
6734 FIB_TEST(0 == vec_len(tc->ctxs),
6735 "%d child visitsed %d times in 0 quanta walk",
6736 ii, vec_len(tc->ctxs));
6737 }
6738 }
6739 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6740 "Queue is not empty post zero quanta walk");
6741 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6742 "Parent has %d children post zero qunta walk",
6743 fib_node_list_get_size(PARENT()->fn_children));
6744
6745 /*
6746 * another one step
6747 */
6748 fib_walk_process_queues(vm, 0);
6749
6750 FOR_EACH_TEST_CHILD(tc)
6751 {
6752 if (ii >= N_TEST_CHILDREN-1)
6753 {
6754 FIB_TEST(1 == vec_len(tc->ctxs),
6755 "%d child visitsed %d times in 2nd zero quanta walk",
6756 ii, vec_len(tc->ctxs));
6757 }
6758 else
6759 {
6760 FIB_TEST(0 == vec_len(tc->ctxs),
6761 "%d child visitsed %d times in 2nd 0 quanta walk",
6762 ii, vec_len(tc->ctxs));
6763 }
6764 }
6765 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6766 "Queue is not empty post zero quanta walk");
6767 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6768 "Parent has %d children post zero qunta walk",
6769 fib_node_list_get_size(PARENT()->fn_children));
6770
6771 /*
6772 * schedule another walk that will catch-up and merge.
6773 */
6774 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6775 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6776 fib_walk_process_queues(vm, 1);
6777
6778 FOR_EACH_TEST_CHILD(tc)
6779 {
6780 if (ii >= N_TEST_CHILDREN-1)
6781 {
6782 FIB_TEST(2 == vec_len(tc->ctxs),
6783 "%d child visitsed %d times in 2nd zero quanta merge walk",
6784 ii, vec_len(tc->ctxs));
6785 vec_free(tc->ctxs);
6786 }
6787 else
6788 {
6789 FIB_TEST(1 == vec_len(tc->ctxs),
6790 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6791 ii, vec_len(tc->ctxs));
6792 vec_free(tc->ctxs);
6793 }
6794 }
6795 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6796 "Queue is not empty post 2nd zero quanta merge walk");
6797 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6798 "Parent has %d children post 2nd zero qunta merge walk",
6799 fib_node_list_get_size(PARENT()->fn_children));
6800
6801 /*
6802 * park a async walk in the middle of the list, then have an sync walk catch
6803 * it. same expectations as async catches async.
6804 */
Neale Ranns450cd302016-11-09 17:49:42 +00006805 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006806
6807 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6808 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6809
6810 fib_walk_process_queues(vm, 0);
6811 fib_walk_process_queues(vm, 0);
6812
6813 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6814
6815 FOR_EACH_TEST_CHILD(tc)
6816 {
6817 if (ii >= N_TEST_CHILDREN-1)
6818 {
6819 FIB_TEST(2 == vec_len(tc->ctxs),
6820 "%d child visitsed %d times in sync catches async walk",
6821 ii, vec_len(tc->ctxs));
6822 vec_free(tc->ctxs);
6823 }
6824 else
6825 {
6826 FIB_TEST(1 == vec_len(tc->ctxs),
6827 "%d child visitsed %d times in sync catches async walk",
6828 ii, vec_len(tc->ctxs));
6829 vec_free(tc->ctxs);
6830 }
6831 }
6832 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6833 "Queue is not empty post 2nd zero quanta merge walk");
6834 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6835 "Parent has %d children post 2nd zero qunta merge walk",
6836 fib_node_list_get_size(PARENT()->fn_children));
6837
6838 /*
6839 * make the parent a child of one of its children, thus inducing a routing loop.
6840 */
6841 fib_test_nodes[PARENT_INDEX].sibling =
6842 fib_node_child_add(FIB_NODE_TYPE_TEST,
6843 1, // the first child
6844 FIB_NODE_TYPE_TEST,
6845 PARENT_INDEX);
6846
6847 /*
6848 * execute a sync walk from the parent. each child visited spawns more sync
6849 * walks. we expect the walk to terminate.
6850 */
6851 fib_test_walk_spawns_walks = 1;
6852
6853 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6854
6855 FOR_EACH_TEST_CHILD(tc)
6856 {
6857 /*
6858 * child 1 - which is last in the list - has the loop.
6859 * the other children a re thus visitsed first. the we meet
6860 * child 1. we go round the loop again, visting the other children.
6861 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6862 * again.
6863 */
6864 if (1 == ii)
6865 {
6866 FIB_TEST(1 == vec_len(tc->ctxs),
6867 "child %d visitsed %d times during looped sync walk",
6868 ii, vec_len(tc->ctxs));
6869 }
6870 else
6871 {
6872 FIB_TEST(2 == vec_len(tc->ctxs),
6873 "child %d visitsed %d times during looped sync walk",
6874 ii, vec_len(tc->ctxs));
6875 }
6876 vec_free(tc->ctxs);
6877 }
6878 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6879 "Parent has %d children post sync loop walk",
6880 fib_node_list_get_size(PARENT()->fn_children));
6881
6882 /*
6883 * the walk doesn't reach the max depth because the infra knows that sync
6884 * meets sync implies a loop and bails early.
6885 */
6886 FIB_TEST(high_ctx.fnbw_depth == 9,
6887 "Walk context depth %d post sync loop walk",
6888 high_ctx.fnbw_depth);
6889
6890 /*
6891 * execute an async walk of the graph loop, with each child spawns sync walks
6892 */
6893 high_ctx.fnbw_depth = 0;
6894 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6895 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6896
6897 fib_walk_process_queues(vm, 1);
6898
6899 FOR_EACH_TEST_CHILD(tc)
6900 {
6901 /*
6902 * we don't really care how many times the children are visisted, as long as
6903 * it is more than once.
6904 */
6905 FIB_TEST(1 <= vec_len(tc->ctxs),
6906 "child %d visitsed %d times during looped aync spawns sync walk",
6907 ii, vec_len(tc->ctxs));
6908 vec_free(tc->ctxs);
6909 }
6910
6911 /*
6912 * execute an async walk of the graph loop, with each child spawns async walks
6913 */
6914 fib_test_walk_spawns_walks = 2;
6915 high_ctx.fnbw_depth = 0;
6916 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6917 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6918
6919 fib_walk_process_queues(vm, 1);
6920
6921 FOR_EACH_TEST_CHILD(tc)
6922 {
6923 /*
6924 * we don't really care how many times the children are visisted, as long as
6925 * it is more than once.
6926 */
6927 FIB_TEST(1 <= vec_len(tc->ctxs),
6928 "child %d visitsed %d times during looped async spawns async walk",
6929 ii, vec_len(tc->ctxs));
6930 vec_free(tc->ctxs);
6931 }
6932
6933
6934 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6935 1, // the first child
6936 fib_test_nodes[PARENT_INDEX].sibling);
6937
6938 /*
6939 * cleanup
6940 */
6941 FOR_EACH_TEST_CHILD(tc)
6942 {
6943 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6944 tc->sibling);
6945 fib_node_deinit(&tc->node);
6946 fib_node_unlock(&tc->node);
6947 }
6948 fib_node_deinit(PARENT());
6949
6950 /*
6951 * The parent will be destroyed when the last lock on it goes.
6952 * this test ensures all the walk objects are unlocking it.
6953 */
6954 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
6955 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006956
6957 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006958}
6959
Neale Ranns88fc83e2017-04-05 08:11:14 -07006960/*
6961 * declaration of the otherwise static callback functions
6962 */
6963void fib_bfd_notify (bfd_listen_event_e event,
6964 const bfd_session_t *session);
6965void adj_bfd_notify (bfd_listen_event_e event,
6966 const bfd_session_t *session);
6967
6968/**
6969 * Test BFD session interaction with FIB
6970 */
6971static int
6972fib_test_bfd (void)
6973{
6974 fib_node_index_t fei;
6975 test_main_t *tm;
6976 int n_feis;
6977
6978 /* via 10.10.10.1 */
6979 ip46_address_t nh_10_10_10_1 = {
6980 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6981 };
6982 /* via 10.10.10.2 */
6983 ip46_address_t nh_10_10_10_2 = {
6984 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
6985 };
6986 /* via 10.10.10.10 */
6987 ip46_address_t nh_10_10_10_10 = {
6988 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6989 };
6990 n_feis = fib_entry_pool_size();
6991
6992 tm = &test_main;
6993
6994 /*
6995 * add interface routes. we'll assume this works. it's tested elsewhere
6996 */
6997 fib_prefix_t pfx_10_10_10_10_s_24 = {
6998 .fp_len = 24,
6999 .fp_proto = FIB_PROTOCOL_IP4,
7000 .fp_addr = nh_10_10_10_10,
7001 };
7002
7003 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7004 FIB_SOURCE_INTERFACE,
7005 (FIB_ENTRY_FLAG_CONNECTED |
7006 FIB_ENTRY_FLAG_ATTACHED),
7007 FIB_PROTOCOL_IP4,
7008 NULL,
7009 tm->hw[0]->sw_if_index,
7010 ~0, // invalid fib index
7011 1, // weight
7012 NULL,
7013 FIB_ROUTE_PATH_FLAG_NONE);
7014
7015 fib_prefix_t pfx_10_10_10_10_s_32 = {
7016 .fp_len = 32,
7017 .fp_proto = FIB_PROTOCOL_IP4,
7018 .fp_addr = nh_10_10_10_10,
7019 };
7020 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7021 FIB_SOURCE_INTERFACE,
7022 (FIB_ENTRY_FLAG_CONNECTED |
7023 FIB_ENTRY_FLAG_LOCAL),
7024 FIB_PROTOCOL_IP4,
7025 NULL,
7026 tm->hw[0]->sw_if_index,
7027 ~0, // invalid fib index
7028 1, // weight
7029 NULL,
7030 FIB_ROUTE_PATH_FLAG_NONE);
7031
7032 /*
7033 * A BFD session via a neighbour we do not yet know
7034 */
7035 bfd_session_t bfd_10_10_10_1 = {
7036 .udp = {
7037 .key = {
7038 .fib_index = 0,
7039 .peer_addr = nh_10_10_10_1,
7040 },
7041 },
7042 .hop_type = BFD_HOP_TYPE_MULTI,
7043 .local_state = BFD_STATE_init,
7044 };
7045
7046 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7047
7048 /*
7049 * A new entry will be created that forwards via the adj
7050 */
7051 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7052 VNET_LINK_IP4,
7053 &nh_10_10_10_1,
7054 tm->hw[0]->sw_if_index);
7055 fib_prefix_t pfx_10_10_10_1_s_32 = {
7056 .fp_addr = nh_10_10_10_1,
7057 .fp_len = 32,
7058 .fp_proto = FIB_PROTOCOL_IP4,
7059 };
7060 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7061 .type = FT_LB_ADJ,
7062 .adj = {
7063 .adj = ai_10_10_10_1,
7064 },
7065 };
7066
7067 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7068 FIB_TEST(fib_test_validate_entry(fei,
7069 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7070 1,
7071 &adj_o_10_10_10_1),
7072 "BFD sourced %U via %U",
7073 format_fib_prefix, &pfx_10_10_10_1_s_32,
7074 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7075
7076 /*
7077 * Delete the BFD session. Expect the fib_entry to be removed
7078 */
7079 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7080
7081 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7082 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7083 "BFD sourced %U removed",
7084 format_fib_prefix, &pfx_10_10_10_1_s_32);
7085
7086 /*
7087 * Add the BFD source back
7088 */
7089 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7090
7091 /*
7092 * source the entry via the ADJ fib
7093 */
7094 fei = fib_table_entry_update_one_path(0,
7095 &pfx_10_10_10_1_s_32,
7096 FIB_SOURCE_ADJ,
7097 FIB_ENTRY_FLAG_ATTACHED,
7098 FIB_PROTOCOL_IP4,
7099 &nh_10_10_10_1,
7100 tm->hw[0]->sw_if_index,
7101 ~0, // invalid fib index
7102 1,
7103 NULL,
7104 FIB_ROUTE_PATH_FLAG_NONE);
7105
7106 /*
7107 * Delete the BFD session. Expect the fib_entry to remain
7108 */
7109 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7110
7111 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7112 FIB_TEST(fib_test_validate_entry(fei,
7113 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7114 1,
7115 &adj_o_10_10_10_1),
7116 "BFD sourced %U remains via %U",
7117 format_fib_prefix, &pfx_10_10_10_1_s_32,
7118 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7119
7120 /*
7121 * Add the BFD source back
7122 */
7123 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7124
7125 /*
7126 * Create another ADJ FIB
7127 */
7128 fib_prefix_t pfx_10_10_10_2_s_32 = {
7129 .fp_addr = nh_10_10_10_2,
7130 .fp_len = 32,
7131 .fp_proto = FIB_PROTOCOL_IP4,
7132 };
7133 fib_table_entry_update_one_path(0,
7134 &pfx_10_10_10_2_s_32,
7135 FIB_SOURCE_ADJ,
7136 FIB_ENTRY_FLAG_ATTACHED,
7137 FIB_PROTOCOL_IP4,
7138 &nh_10_10_10_2,
7139 tm->hw[0]->sw_if_index,
7140 ~0, // invalid fib index
7141 1,
7142 NULL,
7143 FIB_ROUTE_PATH_FLAG_NONE);
7144 /*
7145 * A BFD session for the new ADJ FIB
7146 */
7147 bfd_session_t bfd_10_10_10_2 = {
7148 .udp = {
7149 .key = {
7150 .fib_index = 0,
7151 .peer_addr = nh_10_10_10_2,
7152 },
7153 },
7154 .hop_type = BFD_HOP_TYPE_MULTI,
7155 .local_state = BFD_STATE_init,
7156 };
7157
7158 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7159
7160 /*
7161 * remove the adj-fib source whilst the session is present
7162 * then add it back
7163 */
7164 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7165 fib_table_entry_update_one_path(0,
7166 &pfx_10_10_10_2_s_32,
7167 FIB_SOURCE_ADJ,
7168 FIB_ENTRY_FLAG_ATTACHED,
7169 FIB_PROTOCOL_IP4,
7170 &nh_10_10_10_2,
7171 tm->hw[0]->sw_if_index,
7172 ~0, // invalid fib index
7173 1,
7174 NULL,
7175 FIB_ROUTE_PATH_FLAG_NONE);
7176
7177 /*
7178 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7179 * bring one of the sessions UP, leave the other down
7180 */
7181 bfd_10_10_10_1.local_state = BFD_STATE_up;
7182 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7183 bfd_10_10_10_2.local_state = BFD_STATE_down;
7184 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7185
7186 /*
7187 * A recursive prefix via both of the ADJ FIBs
7188 */
7189 fib_prefix_t pfx_200_0_0_0_s_24 = {
7190 .fp_proto = FIB_PROTOCOL_IP4,
7191 .fp_len = 32,
7192 .fp_addr = {
7193 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7194 },
7195 };
7196 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7197
7198 dpo_10_10_10_1 =
7199 fib_entry_contribute_ip_forwarding(
7200 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7201 dpo_10_10_10_2 =
7202 fib_entry_contribute_ip_forwarding(
7203 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7204
7205 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7206 .type = FT_LB_O_LB,
7207 .lb = {
7208 .lb = dpo_10_10_10_1->dpoi_index,
7209 },
7210 };
7211 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7212 .type = FT_LB_O_LB,
7213 .lb = {
7214 .lb = dpo_10_10_10_2->dpoi_index,
7215 },
7216 };
7217
7218 /*
7219 * A prefix via the adj-fib that is BFD down => DROP
7220 */
7221 fei = fib_table_entry_path_add(0,
7222 &pfx_200_0_0_0_s_24,
7223 FIB_SOURCE_API,
7224 FIB_ENTRY_FLAG_NONE,
7225 FIB_PROTOCOL_IP4,
7226 &nh_10_10_10_2,
7227 ~0, // recursive
7228 0, // default fib index
7229 1,
7230 NULL,
7231 FIB_ROUTE_PATH_FLAG_NONE);
7232 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7233 "%U resolves via drop",
7234 format_fib_prefix, &pfx_200_0_0_0_s_24);
7235
7236 /*
7237 * add a path via the UP BFD adj-fib.
7238 * we expect that the DOWN BFD ADJ FIB is not used.
7239 */
7240 fei = fib_table_entry_path_add(0,
7241 &pfx_200_0_0_0_s_24,
7242 FIB_SOURCE_API,
7243 FIB_ENTRY_FLAG_NONE,
7244 FIB_PROTOCOL_IP4,
7245 &nh_10_10_10_1,
7246 ~0, // recursive
7247 0, // default fib index
7248 1,
7249 NULL,
7250 FIB_ROUTE_PATH_FLAG_NONE);
7251
7252 FIB_TEST(fib_test_validate_entry(fei,
7253 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7254 1,
7255 &lb_o_10_10_10_1),
7256 "Recursive %U only UP BFD adj-fibs",
7257 format_fib_prefix, &pfx_200_0_0_0_s_24);
7258
7259 /*
7260 * Send a BFD state change to UP - both sessions are now up
7261 * the recursive prefix should LB over both
7262 */
7263 bfd_10_10_10_2.local_state = BFD_STATE_up;
7264 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7265
7266
7267 FIB_TEST(fib_test_validate_entry(fei,
7268 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7269 2,
7270 &lb_o_10_10_10_1,
7271 &lb_o_10_10_10_2),
7272 "Recursive %U via both UP BFD adj-fibs",
7273 format_fib_prefix, &pfx_200_0_0_0_s_24);
7274
7275 /*
7276 * Send a BFD state change to DOWN
7277 * the recursive prefix should exclude the down
7278 */
7279 bfd_10_10_10_2.local_state = BFD_STATE_down;
7280 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7281
7282
7283 FIB_TEST(fib_test_validate_entry(fei,
7284 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7285 1,
7286 &lb_o_10_10_10_1),
7287 "Recursive %U via only UP",
7288 format_fib_prefix, &pfx_200_0_0_0_s_24);
7289
7290 /*
7291 * Delete the BFD session while it is in the DOWN state.
7292 * FIB should consider the entry's state as back up
7293 */
7294 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
7295
7296 FIB_TEST(fib_test_validate_entry(fei,
7297 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7298 2,
7299 &lb_o_10_10_10_1,
7300 &lb_o_10_10_10_2),
7301 "Recursive %U via both UP BFD adj-fibs post down session delete",
7302 format_fib_prefix, &pfx_200_0_0_0_s_24);
7303
7304 /*
7305 * Delete the BFD other session while it is in the UP state.
7306 */
7307 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7308
7309 FIB_TEST(fib_test_validate_entry(fei,
7310 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7311 2,
7312 &lb_o_10_10_10_1,
7313 &lb_o_10_10_10_2),
7314 "Recursive %U via both UP BFD adj-fibs post up session delete",
7315 format_fib_prefix, &pfx_200_0_0_0_s_24);
7316
7317 /*
7318 * cleaup
7319 */
7320 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
7321 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
7322 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7323
7324 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
7325 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
7326
7327 adj_unlock(ai_10_10_10_1);
7328 /*
7329 * test no-one left behind
7330 */
7331 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7332 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7333
7334 /*
7335 * Single-hop BFD tests
7336 */
7337 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
7338 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
7339
7340 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7341
7342 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7343 VNET_LINK_IP4,
7344 &nh_10_10_10_1,
7345 tm->hw[0]->sw_if_index);
7346 /*
7347 * whilst the BFD session is not signalled, the adj is up
7348 */
7349 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
7350
7351 /*
7352 * bring the BFD session up
7353 */
7354 bfd_10_10_10_1.local_state = BFD_STATE_up;
7355 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7356 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
7357
7358 /*
7359 * bring the BFD session down
7360 */
7361 bfd_10_10_10_1.local_state = BFD_STATE_down;
7362 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7363 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
7364
7365
7366 /*
7367 * add an attached next hop FIB entry via the down adj
7368 */
7369 fib_prefix_t pfx_5_5_5_5_s_32 = {
7370 .fp_addr = {
7371 .ip4 = {
7372 .as_u32 = clib_host_to_net_u32(0x05050505),
7373 },
7374 },
7375 .fp_len = 32,
7376 .fp_proto = FIB_PROTOCOL_IP4,
7377 };
7378
7379 fei = fib_table_entry_path_add(0,
7380 &pfx_5_5_5_5_s_32,
7381 FIB_SOURCE_CLI,
7382 FIB_ENTRY_FLAG_NONE,
7383 FIB_PROTOCOL_IP4,
7384 &nh_10_10_10_1,
7385 tm->hw[0]->sw_if_index,
7386 ~0, // invalid fib index
7387 1,
7388 NULL,
7389 FIB_ROUTE_PATH_FLAG_NONE);
7390 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7391 "%U resolves via drop",
7392 format_fib_prefix, &pfx_5_5_5_5_s_32);
7393
7394 /*
7395 * Add a path via an ADJ that is up
7396 */
7397 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7398 VNET_LINK_IP4,
7399 &nh_10_10_10_2,
7400 tm->hw[0]->sw_if_index);
7401
7402 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
7403 .type = FT_LB_ADJ,
7404 .adj = {
7405 .adj = ai_10_10_10_2,
7406 },
7407 };
7408 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
7409
7410 fei = fib_table_entry_path_add(0,
7411 &pfx_5_5_5_5_s_32,
7412 FIB_SOURCE_CLI,
7413 FIB_ENTRY_FLAG_NONE,
7414 FIB_PROTOCOL_IP4,
7415 &nh_10_10_10_2,
7416 tm->hw[0]->sw_if_index,
7417 ~0, // invalid fib index
7418 1,
7419 NULL,
7420 FIB_ROUTE_PATH_FLAG_NONE);
7421
7422 FIB_TEST(fib_test_validate_entry(fei,
7423 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7424 1,
7425 &adj_o_10_10_10_2),
7426 "BFD sourced %U via %U",
7427 format_fib_prefix, &pfx_5_5_5_5_s_32,
7428 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
7429
7430 /*
7431 * Bring up the down session - should now LB
7432 */
7433 bfd_10_10_10_1.local_state = BFD_STATE_up;
7434 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7435 FIB_TEST(fib_test_validate_entry(fei,
7436 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7437 2,
7438 &adj_o_10_10_10_1,
7439 &adj_o_10_10_10_2),
7440 "BFD sourced %U via noth adjs",
7441 format_fib_prefix, &pfx_5_5_5_5_s_32);
7442
7443 /*
7444 * remove the BFD session state from the adj
7445 */
7446 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7447
7448 /*
7449 * clean-up
7450 */
7451 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
7452 adj_unlock(ai_10_10_10_1);
7453 adj_unlock(ai_10_10_10_2);
7454
7455 /*
7456 * test no-one left behind
7457 */
7458 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7459 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7460 return (0);
7461}
7462
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007463static int
7464lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007465{
7466 const mpls_label_t deag_label = 50;
7467 const u32 lfib_index = 0;
7468 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01007469 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007470 const dpo_id_t *dpo1;
7471 fib_node_index_t lfe;
7472 lookup_dpo_t *lkd;
7473 test_main_t *tm;
7474 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00007475 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007476
7477 tm = &test_main;
7478 lb_count = pool_elts(load_balance_pool);
7479
7480 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7481 adj_nbr_db_size());
7482
7483 /*
7484 * MPLS enable an interface so we get the MPLS table created
7485 */
7486 mpls_sw_interface_enable_disable(&mpls_main,
7487 tm->hw[0]->sw_if_index,
7488 1);
7489
Neale Rannsad422ed2016-11-02 14:20:04 +00007490 ip46_address_t nh_10_10_10_1 = {
7491 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7492 };
7493 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7494 VNET_LINK_MPLS,
7495 &nh_10_10_10_1,
7496 tm->hw[0]->sw_if_index);
7497
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007498 /*
7499 * Test the specials stack properly.
7500 */
7501 fib_prefix_t exp_null_v6_pfx = {
7502 .fp_proto = FIB_PROTOCOL_MPLS,
7503 .fp_eos = MPLS_EOS,
7504 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7505 .fp_payload_proto = DPO_PROTO_IP6,
7506 };
7507 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
7508 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
7509 "%U/%U present",
7510 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7511 format_mpls_eos_bit, MPLS_EOS);
7512 fib_entry_contribute_forwarding(lfe,
7513 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7514 &dpo);
7515 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7516 lkd = lookup_dpo_get(dpo1->dpoi_index);
7517
7518 FIB_TEST((fib_index == lkd->lkd_fib_index),
7519 "%U/%U is deag in %d %U",
7520 format_mpls_unicast_label, deag_label,
7521 format_mpls_eos_bit, MPLS_EOS,
7522 lkd->lkd_fib_index,
7523 format_dpo_id, &dpo, 0);
7524 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7525 "%U/%U is dst deag",
7526 format_mpls_unicast_label, deag_label,
7527 format_mpls_eos_bit, MPLS_EOS);
7528 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
7529 "%U/%U is lookup in interface's table",
7530 format_mpls_unicast_label, deag_label,
7531 format_mpls_eos_bit, MPLS_EOS);
7532 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
7533 "%U/%U is %U dst deag",
7534 format_mpls_unicast_label, deag_label,
7535 format_mpls_eos_bit, MPLS_EOS,
7536 format_dpo_proto, lkd->lkd_proto);
7537
7538
7539 /*
7540 * A route deag route for EOS
7541 */
7542 fib_prefix_t pfx = {
7543 .fp_proto = FIB_PROTOCOL_MPLS,
7544 .fp_eos = MPLS_EOS,
7545 .fp_label = deag_label,
7546 .fp_payload_proto = DPO_PROTO_IP4,
7547 };
7548 lfe = fib_table_entry_path_add(lfib_index,
7549 &pfx,
7550 FIB_SOURCE_CLI,
7551 FIB_ENTRY_FLAG_NONE,
7552 FIB_PROTOCOL_IP4,
7553 &zero_addr,
7554 ~0,
7555 fib_index,
7556 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007557 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007558 FIB_ROUTE_PATH_FLAG_NONE);
7559
7560 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7561 "%U/%U present",
7562 format_mpls_unicast_label, deag_label,
7563 format_mpls_eos_bit, MPLS_EOS);
7564
7565 fib_entry_contribute_forwarding(lfe,
7566 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7567 &dpo);
7568 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7569 lkd = lookup_dpo_get(dpo1->dpoi_index);
7570
7571 FIB_TEST((fib_index == lkd->lkd_fib_index),
7572 "%U/%U is deag in %d %U",
7573 format_mpls_unicast_label, deag_label,
7574 format_mpls_eos_bit, MPLS_EOS,
7575 lkd->lkd_fib_index,
7576 format_dpo_id, &dpo, 0);
7577 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7578 "%U/%U is dst deag",
7579 format_mpls_unicast_label, deag_label,
7580 format_mpls_eos_bit, MPLS_EOS);
7581 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
7582 "%U/%U is %U dst deag",
7583 format_mpls_unicast_label, deag_label,
7584 format_mpls_eos_bit, MPLS_EOS,
7585 format_dpo_proto, lkd->lkd_proto);
7586
7587 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7588
7589 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7590 &pfx)),
7591 "%U/%U not present",
7592 format_mpls_unicast_label, deag_label,
7593 format_mpls_eos_bit, MPLS_EOS);
7594
7595 /*
7596 * A route deag route for non-EOS
7597 */
7598 pfx.fp_eos = MPLS_NON_EOS;
7599 lfe = fib_table_entry_path_add(lfib_index,
7600 &pfx,
7601 FIB_SOURCE_CLI,
7602 FIB_ENTRY_FLAG_NONE,
7603 FIB_PROTOCOL_IP4,
7604 &zero_addr,
7605 ~0,
7606 lfib_index,
7607 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007608 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007609 FIB_ROUTE_PATH_FLAG_NONE);
7610
7611 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7612 "%U/%U present",
7613 format_mpls_unicast_label, deag_label,
7614 format_mpls_eos_bit, MPLS_NON_EOS);
7615
7616 fib_entry_contribute_forwarding(lfe,
7617 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7618 &dpo);
7619 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7620 lkd = lookup_dpo_get(dpo1->dpoi_index);
7621
7622 FIB_TEST((fib_index == lkd->lkd_fib_index),
7623 "%U/%U is deag in %d %U",
7624 format_mpls_unicast_label, deag_label,
7625 format_mpls_eos_bit, MPLS_NON_EOS,
7626 lkd->lkd_fib_index,
7627 format_dpo_id, &dpo, 0);
7628 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7629 "%U/%U is dst deag",
7630 format_mpls_unicast_label, deag_label,
7631 format_mpls_eos_bit, MPLS_NON_EOS);
7632
7633 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
7634 "%U/%U is %U dst deag",
7635 format_mpls_unicast_label, deag_label,
7636 format_mpls_eos_bit, MPLS_NON_EOS,
7637 format_dpo_proto, lkd->lkd_proto);
7638
7639 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7640
7641 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7642 &pfx)),
7643 "%U/%U not present",
7644 format_mpls_unicast_label, deag_label,
7645 format_mpls_eos_bit, MPLS_EOS);
7646
Neale Rannsad422ed2016-11-02 14:20:04 +00007647 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007648
Neale Rannsad422ed2016-11-02 14:20:04 +00007649 /*
7650 * An MPLS x-connect
7651 */
7652 fib_prefix_t pfx_1200 = {
7653 .fp_len = 21,
7654 .fp_proto = FIB_PROTOCOL_MPLS,
7655 .fp_label = 1200,
7656 .fp_eos = MPLS_NON_EOS,
7657 };
7658 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
7659 .type = FT_LB_LABEL_STACK_O_ADJ,
7660 .label_stack_o_adj = {
7661 .adj = ai_mpls_10_10_10_1,
7662 .label_stack_size = 4,
7663 .label_stack = {
7664 200, 300, 400, 500,
7665 },
7666 .eos = MPLS_NON_EOS,
7667 },
7668 };
7669 dpo_id_t neos_1200 = DPO_INVALID;
7670 dpo_id_t ip_1200 = DPO_INVALID;
7671 mpls_label_t *l200 = NULL;
7672 vec_add1(l200, 200);
7673 vec_add1(l200, 300);
7674 vec_add1(l200, 400);
7675 vec_add1(l200, 500);
7676
7677 lfe = fib_table_entry_update_one_path(fib_index,
7678 &pfx_1200,
7679 FIB_SOURCE_API,
7680 FIB_ENTRY_FLAG_NONE,
7681 FIB_PROTOCOL_IP4,
7682 &nh_10_10_10_1,
7683 tm->hw[0]->sw_if_index,
7684 ~0, // invalid fib index
7685 1,
7686 l200,
7687 FIB_ROUTE_PATH_FLAG_NONE);
7688
7689 FIB_TEST(fib_test_validate_entry(lfe,
7690 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7691 1,
7692 &neos_o_10_10_10_1),
7693 "1200/0 LB 1 buckets via: "
7694 "adj 10.10.11.1");
7695
7696 /*
7697 * A recursive route via the MPLS x-connect
7698 */
7699 fib_prefix_t pfx_2_2_2_3_s_32 = {
7700 .fp_len = 32,
7701 .fp_proto = FIB_PROTOCOL_IP4,
7702 .fp_addr = {
7703 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7704 },
7705 };
7706 fib_route_path_t *rpaths = NULL, rpath = {
7707 .frp_proto = FIB_PROTOCOL_MPLS,
7708 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007709 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00007710 .frp_sw_if_index = ~0, // recurive
7711 .frp_fib_index = 0, // Default MPLS fib
7712 .frp_weight = 1,
7713 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
7714 .frp_label_stack = NULL,
7715 };
7716 vec_add1(rpaths, rpath);
7717
7718 fib_table_entry_path_add2(fib_index,
7719 &pfx_2_2_2_3_s_32,
7720 FIB_SOURCE_API,
7721 FIB_ENTRY_FLAG_NONE,
7722 rpaths);
7723
7724 /*
7725 * A labelled recursive route via the MPLS x-connect
7726 */
7727 fib_prefix_t pfx_2_2_2_4_s_32 = {
7728 .fp_len = 32,
7729 .fp_proto = FIB_PROTOCOL_IP4,
7730 .fp_addr = {
7731 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7732 },
7733 };
7734 mpls_label_t *l999 = NULL;
7735 vec_add1(l999, 999);
7736 rpaths[0].frp_label_stack = l999,
7737
7738 fib_table_entry_path_add2(fib_index,
7739 &pfx_2_2_2_4_s_32,
7740 FIB_SOURCE_API,
7741 FIB_ENTRY_FLAG_NONE,
7742 rpaths);
7743
7744 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7745 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7746 &ip_1200);
7747 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7748 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7749 &neos_1200);
7750
7751 fib_test_lb_bucket_t ip_o_1200 = {
7752 .type = FT_LB_O_LB,
7753 .lb = {
7754 .lb = ip_1200.dpoi_index,
7755 },
7756 };
7757 fib_test_lb_bucket_t mpls_o_1200 = {
7758 .type = FT_LB_LABEL_O_LB,
7759 .label_o_lb = {
7760 .lb = neos_1200.dpoi_index,
7761 .label = 999,
7762 .eos = MPLS_EOS,
7763 },
7764 };
7765
7766 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7767 FIB_TEST(fib_test_validate_entry(lfe,
7768 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7769 1,
7770 &ip_o_1200),
7771 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
7772 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7773 FIB_TEST(fib_test_validate_entry(lfe,
7774 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7775 1,
7776 &mpls_o_1200),
7777 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
7778
7779 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
7780 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
7781 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7782
7783 dpo_reset(&neos_1200);
7784 dpo_reset(&ip_1200);
7785
7786 /*
7787 * A recursive via a label that does not exist
7788 */
7789 fib_test_lb_bucket_t bucket_drop = {
7790 .type = FT_LB_SPECIAL,
7791 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07007792 .adj = DPO_PROTO_IP4,
7793 },
7794 };
7795 fib_test_lb_bucket_t mpls_bucket_drop = {
7796 .type = FT_LB_SPECIAL,
7797 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00007798 .adj = DPO_PROTO_MPLS,
7799 },
7800 };
7801
7802 rpaths[0].frp_label_stack = NULL;
7803 lfe = fib_table_entry_path_add2(fib_index,
7804 &pfx_2_2_2_4_s_32,
7805 FIB_SOURCE_API,
7806 FIB_ENTRY_FLAG_NONE,
7807 rpaths);
7808
7809 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7810 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7811 &ip_1200);
7812 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7813
7814 FIB_TEST(fib_test_validate_entry(lfe,
7815 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7816 1,
7817 &ip_o_1200),
7818 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
7819 lfe = fib_table_lookup(fib_index, &pfx_1200);
7820 FIB_TEST(fib_test_validate_entry(lfe,
7821 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7822 1,
7823 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07007824 "1200/neos LB 1 buckets via: ip4-DROP");
7825 FIB_TEST(fib_test_validate_entry(lfe,
7826 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7827 1,
7828 &mpls_bucket_drop),
7829 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00007830
7831 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7832
7833 dpo_reset(&ip_1200);
7834
7835 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007836 * An rx-interface route.
7837 * like the tail of an mcast LSP
7838 */
7839 dpo_id_t idpo = DPO_INVALID;
7840
7841 interface_dpo_add_or_lock(DPO_PROTO_IP4,
7842 tm->hw[0]->sw_if_index,
7843 &idpo);
7844
7845 fib_prefix_t pfx_2500 = {
7846 .fp_len = 21,
7847 .fp_proto = FIB_PROTOCOL_MPLS,
7848 .fp_label = 2500,
7849 .fp_eos = MPLS_EOS,
7850 .fp_payload_proto = DPO_PROTO_IP4,
7851 };
7852 fib_test_lb_bucket_t rx_intf_0 = {
7853 .type = FT_LB_INTF,
7854 .adj = {
7855 .adj = idpo.dpoi_index,
7856 },
7857 };
7858
7859 lfe = fib_table_entry_update_one_path(fib_index,
7860 &pfx_2500,
7861 FIB_SOURCE_API,
7862 FIB_ENTRY_FLAG_NONE,
7863 FIB_PROTOCOL_IP4,
7864 NULL,
7865 tm->hw[0]->sw_if_index,
7866 ~0, // invalid fib index
7867 0,
7868 NULL,
7869 FIB_ROUTE_PATH_INTF_RX);
7870 FIB_TEST(fib_test_validate_entry(lfe,
7871 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7872 1,
7873 &rx_intf_0),
7874 "2500 rx-interface 0");
7875 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
7876
7877 /*
7878 * An MPLS mulicast entry
7879 */
7880 fib_prefix_t pfx_3500 = {
7881 .fp_len = 21,
7882 .fp_proto = FIB_PROTOCOL_MPLS,
7883 .fp_label = 3500,
7884 .fp_eos = MPLS_EOS,
7885 .fp_payload_proto = DPO_PROTO_IP4,
7886 };
7887 fib_test_rep_bucket_t mc_0 = {
7888 .type = FT_REP_LABEL_O_ADJ,
7889 .label_o_adj = {
7890 .adj = ai_mpls_10_10_10_1,
7891 .label = 3300,
7892 .eos = MPLS_EOS,
7893 },
7894 };
7895 fib_test_rep_bucket_t mc_intf_0 = {
7896 .type = FT_REP_INTF,
7897 .adj = {
7898 .adj = idpo.dpoi_index,
7899 },
7900 };
7901 mpls_label_t *l3300 = NULL;
7902 vec_add1(l3300, 3300);
7903
7904 lfe = fib_table_entry_update_one_path(lfib_index,
7905 &pfx_3500,
7906 FIB_SOURCE_API,
7907 FIB_ENTRY_FLAG_MULTICAST,
7908 FIB_PROTOCOL_IP4,
7909 &nh_10_10_10_1,
7910 tm->hw[0]->sw_if_index,
7911 ~0, // invalid fib index
7912 1,
7913 l3300,
7914 FIB_ROUTE_PATH_FLAG_NONE);
7915 FIB_TEST(fib_test_validate_entry(lfe,
7916 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7917 1,
7918 &mc_0),
7919 "3500 via replicate over 10.10.10.1");
7920
7921 /*
7922 * MPLS Bud-node. Add a replication via an interface-receieve path
7923 */
7924 lfe = fib_table_entry_path_add(lfib_index,
7925 &pfx_3500,
7926 FIB_SOURCE_API,
7927 FIB_ENTRY_FLAG_MULTICAST,
7928 FIB_PROTOCOL_IP4,
7929 NULL,
7930 tm->hw[0]->sw_if_index,
7931 ~0, // invalid fib index
7932 0,
7933 NULL,
7934 FIB_ROUTE_PATH_INTF_RX);
7935 FIB_TEST(fib_test_validate_entry(lfe,
7936 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7937 2,
7938 &mc_0,
7939 &mc_intf_0),
7940 "3500 via replicate over 10.10.10.1 and interface-rx");
7941
7942 /*
7943 * Add a replication via an interface-free for-us path
7944 */
7945 fib_test_rep_bucket_t mc_disp = {
7946 .type = FT_REP_DISP_MFIB_LOOKUP,
7947 .adj = {
7948 .adj = idpo.dpoi_index,
7949 },
7950 };
7951 lfe = fib_table_entry_path_add(lfib_index,
7952 &pfx_3500,
7953 FIB_SOURCE_API,
7954 FIB_ENTRY_FLAG_MULTICAST,
7955 FIB_PROTOCOL_IP4,
7956 NULL,
7957 5, // rpf-id
7958 0, // default table
7959 0,
7960 NULL,
7961 FIB_ROUTE_PATH_RPF_ID);
7962 FIB_TEST(fib_test_validate_entry(lfe,
7963 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7964 3,
7965 &mc_0,
7966 &mc_disp,
7967 &mc_intf_0),
7968 "3500 via replicate over 10.10.10.1 and interface-rx");
7969
7970
7971
7972 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
7973 dpo_reset(&idpo);
7974
7975 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00007976 * cleanup
7977 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007978 mpls_sw_interface_enable_disable(&mpls_main,
7979 tm->hw[0]->sw_if_index,
7980 0);
7981
Neale Rannsad422ed2016-11-02 14:20:04 +00007982 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007983 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00007984 lb_count, pool_elts(load_balance_pool));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007985 FIB_TEST(0 == pool_elts(interface_dpo_pool),
7986 "interface_dpo resources freed %d of %d",
7987 0, pool_elts(interface_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007988
7989 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007990}
7991
7992static clib_error_t *
7993fib_test (vlib_main_t * vm,
7994 unformat_input_t * input,
7995 vlib_cli_command_t * cmd_arg)
7996{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007997 int res;
7998
7999 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008000 fib_test_mk_intf(4);
8001
Neale Ranns88fc83e2017-04-05 08:11:14 -07008002 if (unformat (input, "debug"))
8003 {
8004 fib_test_do_debug = 1;
8005 }
8006
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008007 if (unformat (input, "ip"))
8008 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008009 res += fib_test_v4();
8010 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008011 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008012 else if (unformat (input, "label"))
8013 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008014 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008015 }
8016 else if (unformat (input, "ae"))
8017 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008018 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008019 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008020 else if (unformat (input, "lfib"))
8021 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008022 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008023 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008024 else if (unformat (input, "walk"))
8025 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008026 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008027 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008028 else if (unformat (input, "bfd"))
8029 {
8030 res += fib_test_bfd();
8031 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008032 else
8033 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008034 res += fib_test_v4();
8035 res += fib_test_v6();
8036 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008037 res += fib_test_bfd();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008038 res += fib_test_label();
8039 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008040
8041 /*
8042 * fib-walk process must be disabled in order for the walk tests to work
8043 */
8044 fib_walk_process_disable();
8045 res += fib_test_walk();
8046 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008047 }
8048
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008049 if (res)
8050 {
8051 return clib_error_return(0, "FIB Unit Test Failed");
8052 }
8053 else
8054 {
8055 return (NULL);
8056 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008057}
8058
8059VLIB_CLI_COMMAND (test_fib_command, static) = {
8060 .path = "test fib",
8061 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8062 .function = fib_test,
8063};
8064
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008065clib_error_t *
8066fib_test_init (vlib_main_t *vm)
8067{
8068 return 0;
8069}
8070
8071VLIB_INIT_FUNCTION (fib_test_init);