blob: 486e561679847f2c8e062da7c7ac066f8f1b4589 [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 /*
Neale Ranns08b16482017-05-13 05:52:58 -07002980 * Make the default route recursive via a unknown next-hop. Thus the
2981 * next hop's cover would be the default route
2982 */
2983 fei = fib_table_entry_path_add(fib_index,
2984 &pfx_0_0_0_0_s_0,
2985 FIB_SOURCE_API,
2986 FIB_ENTRY_FLAG_NONE,
2987 FIB_PROTOCOL_IP4,
2988 &pfx_23_23_23_23_s_32.fp_addr,
2989 ~0, // recursive
2990 fib_index,
2991 1,
2992 NULL,
2993 FIB_ROUTE_PATH_FLAG_NONE);
2994 dpo = fib_entry_contribute_ip_forwarding(fei);
2995 FIB_TEST(load_balance_is_drop(dpo),
2996 "0.0.0.0.0/0 via is DROP");
2997 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
2998 "no resolving interface for looped 0.0.0.0/0");
2999
3000 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3001 dpo = fib_entry_contribute_ip_forwarding(fei);
3002 FIB_TEST(load_balance_is_drop(dpo),
3003 "23.23.23.23/32 via is DROP");
3004 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3005 "no resolving interface for looped 23.23.23.23/32");
3006
3007 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3008
3009 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003010 * A recursive route with recursion constraints.
3011 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3012 */
3013 fib_table_entry_path_add(fib_index,
3014 &bgp_200_pfx,
3015 FIB_SOURCE_API,
3016 FIB_ENTRY_FLAG_NONE,
3017 FIB_PROTOCOL_IP4,
3018 &nh_1_1_1_1,
3019 ~0,
3020 fib_index,
3021 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003022 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003023 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3024
3025 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3026 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3027
3028 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3029 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3030
3031 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3032 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3033
3034 /*
3035 * save the load-balance. we expect it to be inplace modified
3036 */
3037 lb = load_balance_get(dpo1->dpoi_index);
3038
3039 /*
3040 * add a covering prefix for the via fib that would otherwise serve
3041 * as the resolving route when the host is removed
3042 */
3043 fib_table_entry_path_add(fib_index,
3044 &pfx_1_1_1_0_s_28,
3045 FIB_SOURCE_API,
3046 FIB_ENTRY_FLAG_NONE,
3047 FIB_PROTOCOL_IP4,
3048 &nh_10_10_10_1,
3049 tm->hw[0]->sw_if_index,
3050 ~0, // invalid fib index
3051 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003052 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003053 FIB_ROUTE_PATH_FLAG_NONE);
3054 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3055 ai = fib_entry_get_adj(fei);
3056 FIB_TEST((ai == ai_01),
3057 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3058
3059 /*
3060 * remove the host via FIB - expect the BGP prefix to be drop
3061 */
3062 fib_table_entry_path_remove(fib_index,
3063 &pfx_1_1_1_1_s_32,
3064 FIB_SOURCE_API,
3065 FIB_PROTOCOL_IP4,
3066 &nh_10_10_10_1,
3067 tm->hw[0]->sw_if_index,
3068 ~0, // invalid fib index
3069 1,
3070 FIB_ROUTE_PATH_FLAG_NONE);
3071
3072 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3073 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3074
3075 /*
3076 * add the via-entry host reoute back. expect to resolve again
3077 */
3078 fib_table_entry_path_add(fib_index,
3079 &pfx_1_1_1_1_s_32,
3080 FIB_SOURCE_API,
3081 FIB_ENTRY_FLAG_NONE,
3082 FIB_PROTOCOL_IP4,
3083 &nh_10_10_10_1,
3084 tm->hw[0]->sw_if_index,
3085 ~0, // invalid fib index
3086 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003087 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003088 FIB_ROUTE_PATH_FLAG_NONE);
3089 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3090 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3091
3092 /*
3093 * add another path for the recursive. it will then have 2.
3094 */
3095 fib_prefix_t pfx_1_1_1_3_s_32 = {
3096 .fp_len = 32,
3097 .fp_proto = FIB_PROTOCOL_IP4,
3098 .fp_addr = {
3099 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3100 },
3101 };
3102 fib_table_entry_path_add(fib_index,
3103 &pfx_1_1_1_3_s_32,
3104 FIB_SOURCE_API,
3105 FIB_ENTRY_FLAG_NONE,
3106 FIB_PROTOCOL_IP4,
3107 &nh_10_10_10_2,
3108 tm->hw[0]->sw_if_index,
3109 ~0, // invalid fib index
3110 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003111 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003112 FIB_ROUTE_PATH_FLAG_NONE);
3113
3114 fib_table_entry_path_add(fib_index,
3115 &bgp_200_pfx,
3116 FIB_SOURCE_API,
3117 FIB_ENTRY_FLAG_NONE,
3118 FIB_PROTOCOL_IP4,
3119 &pfx_1_1_1_3_s_32.fp_addr,
3120 ~0,
3121 fib_index,
3122 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003123 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003124 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3125
Neale Rannsf12a83f2017-04-18 09:09:40 -07003126 /*
3127 * add a bunch load more entries using this path combo so that we get
3128 * an LB-map created.
3129 */
3130#define N_P 128
3131 fib_prefix_t bgp_78s[N_P];
3132 for (ii = 0; ii < N_P; ii++)
3133 {
3134 bgp_78s[ii].fp_len = 32;
3135 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3136 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3137
3138
3139 fib_table_entry_path_add(fib_index,
3140 &bgp_78s[ii],
3141 FIB_SOURCE_API,
3142 FIB_ENTRY_FLAG_NONE,
3143 FIB_PROTOCOL_IP4,
3144 &pfx_1_1_1_3_s_32.fp_addr,
3145 ~0,
3146 fib_index,
3147 1,
3148 NULL,
3149 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3150 fib_table_entry_path_add(fib_index,
3151 &bgp_78s[ii],
3152 FIB_SOURCE_API,
3153 FIB_ENTRY_FLAG_NONE,
3154 FIB_PROTOCOL_IP4,
3155 &nh_1_1_1_1,
3156 ~0,
3157 fib_index,
3158 1,
3159 NULL,
3160 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3161 }
3162
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003163 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3164 dpo = fib_entry_contribute_ip_forwarding(fei);
3165
3166 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3167 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3168 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3169 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3170 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3171 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3172 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3173 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3174
3175 /*
3176 * expect the lb-map used by the recursive's load-balance is using both buckets
3177 */
3178 load_balance_map_t *lbm;
3179 index_t lbmi;
3180
3181 lb = load_balance_get(dpo->dpoi_index);
3182 lbmi = lb->lb_map;
3183 load_balance_map_lock(lbmi);
3184 lbm = load_balance_map_get(lbmi);
3185
3186 FIB_TEST(lbm->lbm_buckets[0] == 0,
3187 "LB maps's bucket 0 is %d",
3188 lbm->lbm_buckets[0]);
3189 FIB_TEST(lbm->lbm_buckets[1] == 1,
3190 "LB maps's bucket 1 is %d",
3191 lbm->lbm_buckets[1]);
3192
3193 /*
3194 * withdraw one of the /32 via-entrys.
3195 * that ECMP path will be unresolved and forwarding should continue on the
3196 * other available path. this is an iBGP PIC edge failover.
3197 * Test the forwarding changes without re-fetching the adj from the
3198 * recursive entry. this ensures its the same one that is updated; i.e. an
3199 * inplace-modify.
3200 */
3201 fib_table_entry_path_remove(fib_index,
3202 &pfx_1_1_1_1_s_32,
3203 FIB_SOURCE_API,
3204 FIB_PROTOCOL_IP4,
3205 &nh_10_10_10_1,
3206 tm->hw[0]->sw_if_index,
3207 ~0, // invalid fib index
3208 1,
3209 FIB_ROUTE_PATH_FLAG_NONE);
3210
Neale Rannsf12a83f2017-04-18 09:09:40 -07003211 /* suspend so the update walk kicks int */
3212 vlib_process_suspend(vlib_get_main(), 1e-5);
3213
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003214 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3215 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3216 "post PIC 200.200.200.200/32 was inplace modified");
3217
3218 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3219 "post PIC adj for 200.200.200.200/32 is recursive"
3220 " via adj for 1.1.1.3");
3221
3222 /*
3223 * the LB maps that was locked above should have been modified to remove
3224 * the path that was down, and thus its bucket points to a path that is
3225 * still up.
3226 */
3227 FIB_TEST(lbm->lbm_buckets[0] == 1,
3228 "LB maps's bucket 0 is %d",
3229 lbm->lbm_buckets[0]);
3230 FIB_TEST(lbm->lbm_buckets[1] == 1,
3231 "LB maps's bucket 1 is %d",
3232 lbm->lbm_buckets[1]);
3233
Neale Ranns994dab42017-04-18 12:56:45 -07003234 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003235
3236 /*
3237 * add it back. again
3238 */
3239 fib_table_entry_path_add(fib_index,
3240 &pfx_1_1_1_1_s_32,
3241 FIB_SOURCE_API,
3242 FIB_ENTRY_FLAG_NONE,
3243 FIB_PROTOCOL_IP4,
3244 &nh_10_10_10_1,
3245 tm->hw[0]->sw_if_index,
3246 ~0, // invalid fib index
3247 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003248 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003249 FIB_ROUTE_PATH_FLAG_NONE);
3250
Neale Rannsf12a83f2017-04-18 09:09:40 -07003251 /* suspend so the update walk kicks in */
3252 vlib_process_suspend(vlib_get_main(), 1e-5);
3253
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003254 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3255 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3256 "via adj for 1.1.1.1");
3257 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3258 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3259 "via adj for 1.1.1.3");
3260
3261 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3262 dpo = fib_entry_contribute_ip_forwarding(fei);
3263 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3264 "post PIC 200.200.200.200/32 was inplace modified");
3265
3266 /*
3267 * add a 3rd path. this makes the LB 16 buckets.
3268 */
3269 fib_table_entry_path_add(fib_index,
3270 &bgp_200_pfx,
3271 FIB_SOURCE_API,
3272 FIB_ENTRY_FLAG_NONE,
3273 FIB_PROTOCOL_IP4,
3274 &pfx_1_1_1_2_s_32.fp_addr,
3275 ~0,
3276 fib_index,
3277 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003278 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003279 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003280 for (ii = 0; ii < N_P; ii++)
3281 {
3282 fib_table_entry_path_add(fib_index,
3283 &bgp_78s[ii],
3284 FIB_SOURCE_API,
3285 FIB_ENTRY_FLAG_NONE,
3286 FIB_PROTOCOL_IP4,
3287 &pfx_1_1_1_2_s_32.fp_addr,
3288 ~0,
3289 fib_index,
3290 1,
3291 NULL,
3292 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3293 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003294
3295 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3296 dpo = fib_entry_contribute_ip_forwarding(fei);
3297 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3298 "200.200.200.200/32 was inplace modified for 3rd path");
3299 FIB_TEST(16 == lb->lb_n_buckets,
3300 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3301
3302 lbmi = lb->lb_map;
3303 load_balance_map_lock(lbmi);
3304 lbm = load_balance_map_get(lbmi);
3305
3306 for (ii = 0; ii < 16; ii++)
3307 {
3308 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3309 "LB Map for 200.200.200.200/32 at %d is %d",
3310 ii, lbm->lbm_buckets[ii]);
3311 }
3312
3313 /*
3314 * trigger PIC by removing the first via-entry
3315 * the first 6 buckets of the map should map to the next 6
3316 */
3317 fib_table_entry_path_remove(fib_index,
3318 &pfx_1_1_1_1_s_32,
3319 FIB_SOURCE_API,
3320 FIB_PROTOCOL_IP4,
3321 &nh_10_10_10_1,
3322 tm->hw[0]->sw_if_index,
3323 ~0,
3324 1,
3325 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003326 /* suspend so the update walk kicks int */
3327 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003328
3329 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3330 dpo = fib_entry_contribute_ip_forwarding(fei);
3331 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3332 "200.200.200.200/32 was inplace modified for 3rd path");
3333 FIB_TEST(2 == lb->lb_n_buckets,
3334 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3335
3336 for (ii = 0; ii < 6; ii++)
3337 {
3338 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3339 "LB Map for 200.200.200.200/32 at %d is %d",
3340 ii, lbm->lbm_buckets[ii]);
3341 }
3342 for (ii = 6; ii < 16; ii++)
3343 {
3344 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3345 "LB Map for 200.200.200.200/32 at %d is %d",
3346 ii, lbm->lbm_buckets[ii]);
3347 }
Neale Ranns994dab42017-04-18 12:56:45 -07003348 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003349
3350 /*
3351 * tidy up
3352 */
3353 fib_table_entry_path_add(fib_index,
3354 &pfx_1_1_1_1_s_32,
3355 FIB_SOURCE_API,
3356 FIB_ENTRY_FLAG_NONE,
3357 FIB_PROTOCOL_IP4,
3358 &nh_10_10_10_1,
3359 tm->hw[0]->sw_if_index,
3360 ~0,
3361 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003362 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003363 FIB_ROUTE_PATH_FLAG_NONE);
3364
Neale Rannsf12a83f2017-04-18 09:09:40 -07003365 for (ii = 0; ii < N_P; ii++)
3366 {
3367 fib_table_entry_delete(fib_index,
3368 &bgp_78s[ii],
3369 FIB_SOURCE_API);
3370 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3371 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3372 "%U removed",
3373 format_fib_prefix, &bgp_78s[ii]);
3374 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003375 fib_table_entry_path_remove(fib_index,
3376 &bgp_200_pfx,
3377 FIB_SOURCE_API,
3378 FIB_PROTOCOL_IP4,
3379 &pfx_1_1_1_2_s_32.fp_addr,
3380 ~0,
3381 fib_index,
3382 1,
3383 MPLS_LABEL_INVALID);
3384 fib_table_entry_path_remove(fib_index,
3385 &bgp_200_pfx,
3386 FIB_SOURCE_API,
3387 FIB_PROTOCOL_IP4,
3388 &nh_1_1_1_1,
3389 ~0,
3390 fib_index,
3391 1,
3392 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3393 fib_table_entry_path_remove(fib_index,
3394 &bgp_200_pfx,
3395 FIB_SOURCE_API,
3396 FIB_PROTOCOL_IP4,
3397 &pfx_1_1_1_3_s_32.fp_addr,
3398 ~0,
3399 fib_index,
3400 1,
3401 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3402 fib_table_entry_delete(fib_index,
3403 &pfx_1_1_1_3_s_32,
3404 FIB_SOURCE_API);
3405 fib_table_entry_delete(fib_index,
3406 &pfx_1_1_1_0_s_28,
3407 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003408 /* suspend so the update walk kicks int */
3409 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003410 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3411 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3412 "1.1.1.1/28 removed");
3413 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3414 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3415 "1.1.1.3/32 removed");
3416 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3417 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3418 "200.200.200.200/32 removed");
3419
3420 /*
3421 * add-remove test. no change.
3422 */
3423 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3424 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003425 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003426 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003427 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003428 fib_entry_pool_size());
3429
3430 /*
3431 * A route whose paths are built up iteratively and then removed
3432 * all at once
3433 */
3434 fib_prefix_t pfx_4_4_4_4_s_32 = {
3435 .fp_len = 32,
3436 .fp_proto = FIB_PROTOCOL_IP4,
3437 .fp_addr = {
3438 /* 4.4.4.4/32 */
3439 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3440 },
3441 };
3442
3443 fib_table_entry_path_add(fib_index,
3444 &pfx_4_4_4_4_s_32,
3445 FIB_SOURCE_API,
3446 FIB_ENTRY_FLAG_NONE,
3447 FIB_PROTOCOL_IP4,
3448 &nh_10_10_10_1,
3449 tm->hw[0]->sw_if_index,
3450 ~0,
3451 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003452 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003453 FIB_ROUTE_PATH_FLAG_NONE);
3454 fib_table_entry_path_add(fib_index,
3455 &pfx_4_4_4_4_s_32,
3456 FIB_SOURCE_API,
3457 FIB_ENTRY_FLAG_NONE,
3458 FIB_PROTOCOL_IP4,
3459 &nh_10_10_10_2,
3460 tm->hw[0]->sw_if_index,
3461 ~0,
3462 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003463 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003464 FIB_ROUTE_PATH_FLAG_NONE);
3465 fib_table_entry_path_add(fib_index,
3466 &pfx_4_4_4_4_s_32,
3467 FIB_SOURCE_API,
3468 FIB_ENTRY_FLAG_NONE,
3469 FIB_PROTOCOL_IP4,
3470 &nh_10_10_10_3,
3471 tm->hw[0]->sw_if_index,
3472 ~0,
3473 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003474 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003475 FIB_ROUTE_PATH_FLAG_NONE);
3476 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3477 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3478 "4.4.4.4/32 present");
3479
3480 fib_table_entry_delete(fib_index,
3481 &pfx_4_4_4_4_s_32,
3482 FIB_SOURCE_API);
3483 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3484 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3485 "4.4.4.4/32 removed");
3486
3487 /*
3488 * add-remove test. no change.
3489 */
3490 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3491 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003492 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003493 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003494 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003495 fib_entry_pool_size());
3496
3497 /*
3498 * A route with multiple paths at once
3499 */
3500 fib_route_path_t *r_paths = NULL;
3501
3502 for (ii = 0; ii < 4; ii++)
3503 {
3504 fib_route_path_t r_path = {
3505 .frp_proto = FIB_PROTOCOL_IP4,
3506 .frp_addr = {
3507 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3508 },
3509 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3510 .frp_weight = 1,
3511 .frp_fib_index = ~0,
3512 };
3513 vec_add1(r_paths, r_path);
3514 }
3515
3516 fib_table_entry_update(fib_index,
3517 &pfx_4_4_4_4_s_32,
3518 FIB_SOURCE_API,
3519 FIB_ENTRY_FLAG_NONE,
3520 r_paths);
3521
3522 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3523 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3524 dpo = fib_entry_contribute_ip_forwarding(fei);
3525
3526 lb = load_balance_get(dpo->dpoi_index);
3527 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3528
3529 fib_table_entry_delete(fib_index,
3530 &pfx_4_4_4_4_s_32,
3531 FIB_SOURCE_API);
3532 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3533 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3534 "4.4.4.4/32 removed");
3535 vec_free(r_paths);
3536
3537 /*
3538 * add-remove test. no change.
3539 */
3540 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3541 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003542 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003543 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003544 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003545 fib_entry_pool_size());
3546
3547 /*
3548 * A route deag route
3549 */
3550 fib_table_entry_path_add(fib_index,
3551 &pfx_4_4_4_4_s_32,
3552 FIB_SOURCE_API,
3553 FIB_ENTRY_FLAG_NONE,
3554 FIB_PROTOCOL_IP4,
3555 &zero_addr,
3556 ~0,
3557 fib_index,
3558 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003559 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003560 FIB_ROUTE_PATH_FLAG_NONE);
3561
3562 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3563 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3564
3565 dpo = fib_entry_contribute_ip_forwarding(fei);
3566 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3567 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3568
3569 FIB_TEST((fib_index == lkd->lkd_fib_index),
3570 "4.4.4.4/32 is deag in %d %U",
3571 lkd->lkd_fib_index,
3572 format_dpo_id, dpo, 0);
3573
3574 fib_table_entry_delete(fib_index,
3575 &pfx_4_4_4_4_s_32,
3576 FIB_SOURCE_API);
3577 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3578 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3579 "4.4.4.4/32 removed");
3580 vec_free(r_paths);
3581
3582 /*
3583 * add-remove test. no change.
3584 */
3585 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3586 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003587 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003588 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003589 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003590 fib_entry_pool_size());
3591
3592 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003593 * Duplicate paths:
3594 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3595 */
3596 fib_prefix_t pfx_34_1_1_1_s_32 = {
3597 .fp_len = 32,
3598 .fp_proto = FIB_PROTOCOL_IP4,
3599 .fp_addr = {
3600 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3601 },
3602 };
3603 fib_prefix_t pfx_34_34_1_1_s_32 = {
3604 .fp_len = 32,
3605 .fp_proto = FIB_PROTOCOL_IP4,
3606 .fp_addr = {
3607 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3608 },
3609 };
3610 fei = fib_table_entry_path_add(fib_index,
3611 &pfx_34_1_1_1_s_32,
3612 FIB_SOURCE_API,
3613 FIB_ENTRY_FLAG_NONE,
3614 FIB_PROTOCOL_IP4,
3615 &pfx_34_34_1_1_s_32.fp_addr,
3616 ~0,
3617 fib_index,
3618 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003619 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003620 FIB_ROUTE_PATH_FLAG_NONE);
3621 fei = fib_table_entry_path_add(fib_index,
3622 &pfx_34_1_1_1_s_32,
3623 FIB_SOURCE_API,
3624 FIB_ENTRY_FLAG_NONE,
3625 FIB_PROTOCOL_IP4,
3626 &pfx_34_34_1_1_s_32.fp_addr,
3627 ~0,
3628 fib_index,
3629 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003630 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003631 FIB_ROUTE_PATH_FLAG_NONE);
3632 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3633 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3634
3635 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003636 * CLEANUP
3637 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3638 * all of which are via 10.10.10.1, Itf1
3639 */
3640 fib_table_entry_path_remove(fib_index,
3641 &pfx_1_1_1_2_s_32,
3642 FIB_SOURCE_API,
3643 FIB_PROTOCOL_IP4,
3644 &nh_10_10_10_1,
3645 tm->hw[0]->sw_if_index,
3646 ~0,
3647 1,
3648 FIB_ROUTE_PATH_FLAG_NONE);
3649 fib_table_entry_path_remove(fib_index,
3650 &pfx_1_1_1_1_s_32,
3651 FIB_SOURCE_API,
3652 FIB_PROTOCOL_IP4,
3653 &nh_10_10_10_1,
3654 tm->hw[0]->sw_if_index,
3655 ~0,
3656 1,
3657 FIB_ROUTE_PATH_FLAG_NONE);
3658 fib_table_entry_path_remove(fib_index,
3659 &pfx_1_1_2_0_s_24,
3660 FIB_SOURCE_API,
3661 FIB_PROTOCOL_IP4,
3662 &nh_10_10_10_1,
3663 tm->hw[0]->sw_if_index,
3664 ~0,
3665 1,
3666 FIB_ROUTE_PATH_FLAG_NONE);
3667
3668 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3669 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3670 "1.1.1.1/32 removed");
3671 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3672 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3673 "1.1.1.2/32 removed");
3674 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3675 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3676 "1.1.2.0/24 removed");
3677
3678 /*
3679 * -3 entries and -1 shared path-list
3680 */
3681 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3682 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003683 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003684 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003685 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003686 fib_entry_pool_size());
3687
3688 /*
3689 * An attached-host route. Expect to link to the incomplete adj
3690 */
3691 fib_prefix_t pfx_4_1_1_1_s_32 = {
3692 .fp_len = 32,
3693 .fp_proto = FIB_PROTOCOL_IP4,
3694 .fp_addr = {
3695 /* 4.1.1.1/32 */
3696 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3697 },
3698 };
3699 fib_table_entry_path_add(fib_index,
3700 &pfx_4_1_1_1_s_32,
3701 FIB_SOURCE_API,
3702 FIB_ENTRY_FLAG_NONE,
3703 FIB_PROTOCOL_IP4,
3704 &zero_addr,
3705 tm->hw[0]->sw_if_index,
3706 fib_index,
3707 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003708 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003709 FIB_ROUTE_PATH_FLAG_NONE);
3710
3711 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3712 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3713 ai = fib_entry_get_adj(fei);
3714
3715 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003716 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003717 &pfx_4_1_1_1_s_32.fp_addr,
3718 tm->hw[0]->sw_if_index);
3719 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3720 adj_unlock(ai2);
3721
3722 /*
3723 * +1 entry and +1 shared path-list
3724 */
3725 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3726 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003727 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003728 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003729 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003730 fib_entry_pool_size());
3731
3732 fib_table_entry_delete(fib_index,
3733 &pfx_4_1_1_1_s_32,
3734 FIB_SOURCE_API);
3735
3736 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3737 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003738 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003739 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003740 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003741 fib_entry_pool_size());
3742
3743 /*
3744 * add a v6 prefix via v4 next-hops
3745 */
3746 fib_prefix_t pfx_2001_s_64 = {
3747 .fp_len = 64,
3748 .fp_proto = FIB_PROTOCOL_IP6,
3749 .fp_addr = {
3750 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3751 },
3752 };
3753 fei = fib_table_entry_path_add(0, //default v6 table
3754 &pfx_2001_s_64,
3755 FIB_SOURCE_API,
3756 FIB_ENTRY_FLAG_NONE,
3757 FIB_PROTOCOL_IP4,
3758 &nh_10_10_10_1,
3759 tm->hw[0]->sw_if_index,
3760 fib_index,
3761 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003762 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003763 FIB_ROUTE_PATH_FLAG_NONE);
3764
3765 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3766 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3767 ai = fib_entry_get_adj(fei);
3768 adj = adj_get(ai);
3769 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3770 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003771 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003772 "2001::/64 is link type v6");
3773 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3774 "2001::/64 ADJ-adj is NH proto v4");
3775 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3776
Neale Ranns3ee44042016-10-03 13:05:48 +01003777 /*
3778 * add a uRPF exempt prefix:
3779 * test:
3780 * - it's forwarding is drop
3781 * - it's uRPF list is not empty
3782 * - the uRPF list for the default route (it's cover) is empty
3783 */
3784 fei = fib_table_entry_special_add(fib_index,
3785 &pfx_4_1_1_1_s_32,
3786 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003787 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003788 dpo = fib_entry_contribute_ip_forwarding(fei);
3789 FIB_TEST(load_balance_is_drop(dpo),
3790 "uRPF exempt 4.1.1.1/32 DROP");
3791 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3792 "uRPF list for exempt prefix has itf index 0");
3793 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3794 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3795 "uRPF list for 0.0.0.0/0 empty");
3796
3797 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003798
3799 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003800 * An adj-fib that fails the refinement criteria - no connected cover
3801 */
3802 fib_prefix_t pfx_12_10_10_2_s_32 = {
3803 .fp_len = 32,
3804 .fp_proto = FIB_PROTOCOL_IP4,
3805 .fp_addr = {
3806 /* 12.10.10.2 */
3807 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3808 },
3809 };
3810
3811 fib_table_entry_update_one_path(fib_index,
3812 &pfx_12_10_10_2_s_32,
3813 FIB_SOURCE_ADJ,
3814 FIB_ENTRY_FLAG_ATTACHED,
3815 FIB_PROTOCOL_IP4,
3816 &pfx_12_10_10_2_s_32.fp_addr,
3817 tm->hw[0]->sw_if_index,
3818 ~0, // invalid fib index
3819 1,
3820 NULL,
3821 FIB_ROUTE_PATH_FLAG_NONE);
3822
3823 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3824 dpo = fib_entry_contribute_ip_forwarding(fei);
3825 FIB_TEST(!dpo_id_is_valid(dpo),
3826 "no connected cover adj-fib fails refinement");
3827
3828 fib_table_entry_delete(fib_index,
3829 &pfx_12_10_10_2_s_32,
3830 FIB_SOURCE_ADJ);
3831
3832 /*
3833 * An adj-fib that fails the refinement criteria - cover is connected
3834 * but on a different interface
3835 */
3836 fib_prefix_t pfx_10_10_10_127_s_32 = {
3837 .fp_len = 32,
3838 .fp_proto = FIB_PROTOCOL_IP4,
3839 .fp_addr = {
3840 /* 10.10.10.127 */
3841 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3842 },
3843 };
3844
3845 fib_table_entry_update_one_path(fib_index,
3846 &pfx_10_10_10_127_s_32,
3847 FIB_SOURCE_ADJ,
3848 FIB_ENTRY_FLAG_ATTACHED,
3849 FIB_PROTOCOL_IP4,
3850 &pfx_10_10_10_127_s_32.fp_addr,
3851 tm->hw[1]->sw_if_index,
3852 ~0, // invalid fib index
3853 1,
3854 NULL,
3855 FIB_ROUTE_PATH_FLAG_NONE);
3856
3857 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3858 dpo = fib_entry_contribute_ip_forwarding(fei);
3859 FIB_TEST(!dpo_id_is_valid(dpo),
3860 "wrong interface adj-fib fails refinement");
3861
3862 fib_table_entry_delete(fib_index,
3863 &pfx_10_10_10_127_s_32,
3864 FIB_SOURCE_ADJ);
Neale Ranns227038a2017-04-21 01:07:59 -07003865 /*
3866 * change the table's flow-hash config - expect the update to propagete to
3867 * the entries' load-balance objects
3868 */
3869 flow_hash_config_t old_hash_config, new_hash_config;
3870
3871 old_hash_config = fib_table_get_flow_hash_config(fib_index,
3872 FIB_PROTOCOL_IP4);
3873 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
3874 IP_FLOW_HASH_DST_ADDR);
3875
3876 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
3877 dpo = fib_entry_contribute_ip_forwarding(fei);
3878 lb = load_balance_get(dpo->dpoi_index);
3879 FIB_TEST((lb->lb_hash_config == old_hash_config),
3880 "Table and LB hash config match: %U",
3881 format_ip_flow_hash_config, lb->lb_hash_config);
3882
3883 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
3884
3885 FIB_TEST((lb->lb_hash_config == new_hash_config),
3886 "Table and LB newhash config match: %U",
3887 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08003888
3889 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003890 * CLEANUP
3891 * remove adj-fibs:
3892 */
3893 fib_table_entry_delete(fib_index,
3894 &pfx_10_10_10_1_s_32,
3895 FIB_SOURCE_ADJ);
3896 fib_table_entry_delete(fib_index,
3897 &pfx_10_10_10_2_s_32,
3898 FIB_SOURCE_ADJ);
3899 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3900 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3901 "10.10.10.1/32 adj-fib removed");
3902 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3903 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3904 "10.10.10.2/32 adj-fib removed");
3905
3906 /*
3907 * -2 entries and -2 non-shared path-list
3908 */
3909 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3910 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003911 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003912 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003913 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003914 fib_entry_pool_size());
3915
3916 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01003917 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003918 * These are the last locks on these adjs. they should thus go away.
3919 */
3920 adj_unlock(ai_02);
3921 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01003922 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003923
3924 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3925 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003926
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003927 /*
3928 * CLEANUP
3929 * remove the interface prefixes
3930 */
3931 local_pfx.fp_len = 32;
3932 fib_table_entry_special_remove(fib_index, &local_pfx,
3933 FIB_SOURCE_INTERFACE);
3934 fei = fib_table_lookup(fib_index, &local_pfx);
3935
3936 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3937 fib_table_lookup_exact_match(fib_index, &local_pfx),
3938 "10.10.10.10/32 adj-fib removed");
3939
3940 local_pfx.fp_len = 24;
3941 fib_table_entry_delete(fib_index, &local_pfx,
3942 FIB_SOURCE_INTERFACE);
3943
3944 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3945 fib_table_lookup_exact_match(fib_index, &local_pfx),
3946 "10.10.10.10/24 adj-fib removed");
3947
3948 /*
3949 * -2 entries and -2 non-shared path-list
3950 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07003951 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003952 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003953 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003954 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003955 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003956 fib_entry_pool_size());
3957
3958 /*
3959 * Last but not least, remove the VRF
3960 */
3961 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3962 FIB_PROTOCOL_IP4,
3963 FIB_SOURCE_API)),
3964 "NO API Source'd prefixes");
3965 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3966 FIB_PROTOCOL_IP4,
3967 FIB_SOURCE_RR)),
3968 "NO RR Source'd prefixes");
3969 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3970 FIB_PROTOCOL_IP4,
3971 FIB_SOURCE_INTERFACE)),
3972 "NO INterface Source'd prefixes");
3973
3974 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3975
3976 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3977 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003978 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003979 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003980 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003981 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003982 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01003983 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07003984 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07003985 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07003986 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
3987 pool_elts(load_balance_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003988
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003989 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003990}
3991
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003992static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003993fib_test_v6 (void)
3994{
3995 /*
3996 * In the default table check for the presence and correct forwarding
3997 * of the special entries
3998 */
3999 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4000 const dpo_id_t *dpo, *dpo_drop;
4001 const ip_adjacency_t *adj;
4002 const receive_dpo_t *rd;
4003 test_main_t *tm;
4004 u32 fib_index;
4005 int ii;
4006
4007 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4008 adj_nbr_db_size());
4009
4010 /* via 2001:0:0:1::2 */
4011 ip46_address_t nh_2001_2 = {
4012 .ip6 = {
4013 .as_u64 = {
4014 [0] = clib_host_to_net_u64(0x2001000000000001),
4015 [1] = clib_host_to_net_u64(0x0000000000000002),
4016 },
4017 },
4018 };
4019
4020 tm = &test_main;
4021
4022 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4023
4024 /* Find or create FIB table 11 */
4025 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
4026
4027 for (ii = 0; ii < 4; ii++)
4028 {
4029 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4030 }
4031
4032 fib_prefix_t pfx_0_0 = {
4033 .fp_len = 0,
4034 .fp_proto = FIB_PROTOCOL_IP6,
4035 .fp_addr = {
4036 .ip6 = {
4037 {0, 0},
4038 },
4039 },
4040 };
4041
4042 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4043 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4044 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4045 "Default route is DROP");
4046
4047 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4048 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4049 &ip6_main,
4050 1,
4051 &pfx_0_0.fp_addr.ip6)),
4052 "default-route; fwd and non-fwd tables match");
4053
4054 // FIXME - check specials.
4055
4056 /*
4057 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004058 * each with 2 entries and a v6 mfib with 4 path-lists.
4059 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004060 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004061#define ENPS (5+4)
4062#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004063 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004064 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004065 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004066 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004067 fib_entry_pool_size());
4068
4069 /*
4070 * add interface routes.
4071 * validate presence of /64 attached and /128 recieve.
4072 * test for the presence of the receive address in the glean and local adj
4073 *
4074 * receive on 2001:0:0:1::1/128
4075 */
4076 fib_prefix_t local_pfx = {
4077 .fp_len = 64,
4078 .fp_proto = FIB_PROTOCOL_IP6,
4079 .fp_addr = {
4080 .ip6 = {
4081 .as_u64 = {
4082 [0] = clib_host_to_net_u64(0x2001000000000001),
4083 [1] = clib_host_to_net_u64(0x0000000000000001),
4084 },
4085 },
4086 }
4087 };
4088
4089 fib_table_entry_update_one_path(fib_index, &local_pfx,
4090 FIB_SOURCE_INTERFACE,
4091 (FIB_ENTRY_FLAG_CONNECTED |
4092 FIB_ENTRY_FLAG_ATTACHED),
4093 FIB_PROTOCOL_IP6,
4094 NULL,
4095 tm->hw[0]->sw_if_index,
4096 ~0,
4097 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004098 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004099 FIB_ROUTE_PATH_FLAG_NONE);
4100 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4101
4102 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4103
4104 ai = fib_entry_get_adj(fei);
4105 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4106 adj = adj_get(ai);
4107 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4108 "attached interface adj is glean");
4109 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4110 &adj->sub_type.glean.receive_addr)),
4111 "attached interface adj is receive ok");
4112 dpo = fib_entry_contribute_ip_forwarding(fei);
4113 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4114 &ip6_main,
4115 1,
4116 &local_pfx.fp_addr.ip6)),
4117 "attached-route; fwd and non-fwd tables match");
4118
4119 local_pfx.fp_len = 128;
4120 fib_table_entry_update_one_path(fib_index, &local_pfx,
4121 FIB_SOURCE_INTERFACE,
4122 (FIB_ENTRY_FLAG_CONNECTED |
4123 FIB_ENTRY_FLAG_LOCAL),
4124 FIB_PROTOCOL_IP6,
4125 NULL,
4126 tm->hw[0]->sw_if_index,
4127 ~0, // invalid fib index
4128 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004129 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004130 FIB_ROUTE_PATH_FLAG_NONE);
4131 fei = fib_table_lookup(fib_index, &local_pfx);
4132
4133 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4134
4135 dpo = fib_entry_contribute_ip_forwarding(fei);
4136 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4137 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4138 "local interface adj is local");
4139 rd = receive_dpo_get(dpo->dpoi_index);
4140
4141 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4142 &rd->rd_addr)),
4143 "local interface adj is receive ok");
4144
4145 dpo = fib_entry_contribute_ip_forwarding(fei);
4146 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4147 &ip6_main,
4148 1,
4149 &local_pfx.fp_addr.ip6)),
4150 "local-route; fwd and non-fwd tables match");
4151
4152 /*
4153 * +2 entries. +2 unshared path-lists
4154 */
4155 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004156 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004157 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004158 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004159 fib_entry_pool_size());
4160
4161 /*
4162 * Modify the default route to be via an adj not yet known.
4163 * this sources the defalut route with the API source, which is
4164 * a higher preference to the DEFAULT_ROUTE source
4165 */
4166 fib_table_entry_path_add(fib_index, &pfx_0_0,
4167 FIB_SOURCE_API,
4168 FIB_ENTRY_FLAG_NONE,
4169 FIB_PROTOCOL_IP6,
4170 &nh_2001_2,
4171 tm->hw[0]->sw_if_index,
4172 ~0,
4173 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004174 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004175 FIB_ROUTE_PATH_FLAG_NONE);
4176 fei = fib_table_lookup(fib_index, &pfx_0_0);
4177
4178 FIB_TEST((fei == dfrt), "default route same index");
4179 ai = fib_entry_get_adj(fei);
4180 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4181 adj = adj_get(ai);
4182 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4183 "adj is incomplete");
4184 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4185 "adj nbr next-hop ok");
4186
4187 /*
4188 * find the adj in the shared db
4189 */
4190 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004191 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004192 &nh_2001_2,
4193 tm->hw[0]->sw_if_index);
4194 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4195 adj_unlock(locked_ai);
4196
4197 /*
4198 * no more entires. +1 shared path-list
4199 */
4200 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4201 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004202 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004203 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004204 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004205 fib_entry_pool_size());
4206
4207 /*
4208 * remove the API source from the default route. We expected
4209 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4210 */
4211 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4212 FIB_SOURCE_API,
4213 FIB_PROTOCOL_IP6,
4214 &nh_2001_2,
4215 tm->hw[0]->sw_if_index,
4216 ~0,
4217 1,
4218 FIB_ROUTE_PATH_FLAG_NONE);
4219 fei = fib_table_lookup(fib_index, &pfx_0_0);
4220
4221 FIB_TEST((fei == dfrt), "default route same index");
4222 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4223 "Default route is DROP");
4224
4225 /*
4226 * no more entires. -1 shared path-list
4227 */
4228 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4229 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004230 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004231 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004232 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004233 fib_entry_pool_size());
4234
4235 /*
4236 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4237 */
4238 fib_prefix_t pfx_2001_1_2_s_128 = {
4239 .fp_len = 128,
4240 .fp_proto = FIB_PROTOCOL_IP6,
4241 .fp_addr = {
4242 .ip6 = {
4243 .as_u64 = {
4244 [0] = clib_host_to_net_u64(0x2001000000000001),
4245 [1] = clib_host_to_net_u64(0x0000000000000002),
4246 },
4247 },
4248 }
4249 };
4250 fib_prefix_t pfx_2001_1_3_s_128 = {
4251 .fp_len = 128,
4252 .fp_proto = FIB_PROTOCOL_IP6,
4253 .fp_addr = {
4254 .ip6 = {
4255 .as_u64 = {
4256 [0] = clib_host_to_net_u64(0x2001000000000001),
4257 [1] = clib_host_to_net_u64(0x0000000000000003),
4258 },
4259 },
4260 }
4261 };
4262 u8 eth_addr[] = {
4263 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4264 };
4265
4266 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004267 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004268 &pfx_2001_1_2_s_128.fp_addr,
4269 tm->hw[0]->sw_if_index);
4270 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4271 adj = adj_get(ai_01);
4272 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4273 "adj is incomplete");
4274 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4275 &adj->sub_type.nbr.next_hop)),
4276 "adj nbr next-hop ok");
4277
Neale Rannsb80c5362016-10-08 13:03:40 +01004278 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4279 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004280 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4281 "adj is complete");
4282 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4283 &adj->sub_type.nbr.next_hop)),
4284 "adj nbr next-hop ok");
4285
4286 fib_table_entry_update_one_path(fib_index,
4287 &pfx_2001_1_2_s_128,
4288 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004289 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004290 FIB_PROTOCOL_IP6,
4291 &pfx_2001_1_2_s_128.fp_addr,
4292 tm->hw[0]->sw_if_index,
4293 ~0,
4294 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004295 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004296 FIB_ROUTE_PATH_FLAG_NONE);
4297
4298 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4299 ai = fib_entry_get_adj(fei);
4300 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4301
4302 eth_addr[5] = 0xb2;
4303
4304 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004305 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004306 &pfx_2001_1_3_s_128.fp_addr,
4307 tm->hw[0]->sw_if_index);
4308 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4309 adj = adj_get(ai_02);
4310 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4311 "adj is incomplete");
4312 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4313 &adj->sub_type.nbr.next_hop)),
4314 "adj nbr next-hop ok");
4315
Neale Rannsb80c5362016-10-08 13:03:40 +01004316 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4317 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004318 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4319 "adj is complete");
4320 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4321 &adj->sub_type.nbr.next_hop)),
4322 "adj nbr next-hop ok");
4323 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4324
4325 fib_table_entry_update_one_path(fib_index,
4326 &pfx_2001_1_3_s_128,
4327 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004328 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004329 FIB_PROTOCOL_IP6,
4330 &pfx_2001_1_3_s_128.fp_addr,
4331 tm->hw[0]->sw_if_index,
4332 ~0,
4333 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004334 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004335 FIB_ROUTE_PATH_FLAG_NONE);
4336
4337 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4338 ai = fib_entry_get_adj(fei);
4339 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4340
4341 /*
4342 * +2 entries, +2 unshread path-lists.
4343 */
4344 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4345 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004346 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004347 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004348 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004349 fib_entry_pool_size());
4350
4351 /*
4352 * Add a 2 routes via the first ADJ. ensure path-list sharing
4353 */
4354 fib_prefix_t pfx_2001_a_s_64 = {
4355 .fp_len = 64,
4356 .fp_proto = FIB_PROTOCOL_IP6,
4357 .fp_addr = {
4358 .ip6 = {
4359 .as_u64 = {
4360 [0] = clib_host_to_net_u64(0x200100000000000a),
4361 [1] = clib_host_to_net_u64(0x0000000000000000),
4362 },
4363 },
4364 }
4365 };
4366 fib_prefix_t pfx_2001_b_s_64 = {
4367 .fp_len = 64,
4368 .fp_proto = FIB_PROTOCOL_IP6,
4369 .fp_addr = {
4370 .ip6 = {
4371 .as_u64 = {
4372 [0] = clib_host_to_net_u64(0x200100000000000b),
4373 [1] = clib_host_to_net_u64(0x0000000000000000),
4374 },
4375 },
4376 }
4377 };
4378
4379 fib_table_entry_path_add(fib_index,
4380 &pfx_2001_a_s_64,
4381 FIB_SOURCE_API,
4382 FIB_ENTRY_FLAG_NONE,
4383 FIB_PROTOCOL_IP6,
4384 &nh_2001_2,
4385 tm->hw[0]->sw_if_index,
4386 ~0,
4387 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004388 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004389 FIB_ROUTE_PATH_FLAG_NONE);
4390 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4391 ai = fib_entry_get_adj(fei);
4392 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4393 fib_table_entry_path_add(fib_index,
4394 &pfx_2001_b_s_64,
4395 FIB_SOURCE_API,
4396 FIB_ENTRY_FLAG_NONE,
4397 FIB_PROTOCOL_IP6,
4398 &nh_2001_2,
4399 tm->hw[0]->sw_if_index,
4400 ~0,
4401 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004402 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004403 FIB_ROUTE_PATH_FLAG_NONE);
4404 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4405 ai = fib_entry_get_adj(fei);
4406 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4407
4408 /*
4409 * +2 entries, +1 shared path-list.
4410 */
4411 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4412 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004413 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004414 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004415 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004416 fib_entry_pool_size());
4417
4418 /*
4419 * add a v4 prefix via a v6 next-hop
4420 */
4421 fib_prefix_t pfx_1_1_1_1_s_32 = {
4422 .fp_len = 32,
4423 .fp_proto = FIB_PROTOCOL_IP4,
4424 .fp_addr = {
4425 .ip4.as_u32 = 0x01010101,
4426 },
4427 };
4428 fei = fib_table_entry_path_add(0, // default table
4429 &pfx_1_1_1_1_s_32,
4430 FIB_SOURCE_API,
4431 FIB_ENTRY_FLAG_NONE,
4432 FIB_PROTOCOL_IP6,
4433 &nh_2001_2,
4434 tm->hw[0]->sw_if_index,
4435 ~0,
4436 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004437 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004438 FIB_ROUTE_PATH_FLAG_NONE);
4439 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4440 "1.1.1.1/32 o v6 route present");
4441 ai = fib_entry_get_adj(fei);
4442 adj = adj_get(ai);
4443 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4444 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004445 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004446 "1.1.1.1/32 ADJ-adj is link type v4");
4447 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4448 "1.1.1.1/32 ADJ-adj is NH proto v6");
4449 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4450
4451 /*
4452 * An attached route
4453 */
4454 fib_prefix_t pfx_2001_c_s_64 = {
4455 .fp_len = 64,
4456 .fp_proto = FIB_PROTOCOL_IP6,
4457 .fp_addr = {
4458 .ip6 = {
4459 .as_u64 = {
4460 [0] = clib_host_to_net_u64(0x200100000000000c),
4461 [1] = clib_host_to_net_u64(0x0000000000000000),
4462 },
4463 },
4464 }
4465 };
4466 fib_table_entry_path_add(fib_index,
4467 &pfx_2001_c_s_64,
4468 FIB_SOURCE_CLI,
4469 FIB_ENTRY_FLAG_ATTACHED,
4470 FIB_PROTOCOL_IP6,
4471 NULL,
4472 tm->hw[0]->sw_if_index,
4473 ~0,
4474 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004475 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004476 FIB_ROUTE_PATH_FLAG_NONE);
4477 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4478 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4479 ai = fib_entry_get_adj(fei);
4480 adj = adj_get(ai);
4481 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4482 "2001:0:0:c/64 attached resolves via glean");
4483
4484 fib_table_entry_path_remove(fib_index,
4485 &pfx_2001_c_s_64,
4486 FIB_SOURCE_CLI,
4487 FIB_PROTOCOL_IP6,
4488 NULL,
4489 tm->hw[0]->sw_if_index,
4490 ~0,
4491 1,
4492 FIB_ROUTE_PATH_FLAG_NONE);
4493 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4494 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4495
4496 /*
4497 * Shutdown the interface on which we have a connected and through
4498 * which the routes are reachable.
4499 * This will result in the connected, adj-fibs, and routes linking to drop
4500 * The local/for-us prefix continues to receive.
4501 */
4502 clib_error_t * error;
4503
4504 error = vnet_sw_interface_set_flags(vnet_get_main(),
4505 tm->hw[0]->sw_if_index,
4506 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4507 FIB_TEST((NULL == error), "Interface shutdown OK");
4508
4509 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4510 dpo = fib_entry_contribute_ip_forwarding(fei);
4511 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4512 "2001::b/64 resolves via drop");
4513
4514 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4515 dpo = fib_entry_contribute_ip_forwarding(fei);
4516 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4517 "2001::a/64 resolves via drop");
4518 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4519 dpo = fib_entry_contribute_ip_forwarding(fei);
4520 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4521 "2001:0:0:1::3/64 resolves via drop");
4522 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4523 dpo = fib_entry_contribute_ip_forwarding(fei);
4524 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4525 "2001:0:0:1::2/64 resolves via drop");
4526 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4527 dpo = fib_entry_contribute_ip_forwarding(fei);
4528 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4529 "2001:0:0:1::1/128 not drop");
4530 local_pfx.fp_len = 64;
4531 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4532 dpo = fib_entry_contribute_ip_forwarding(fei);
4533 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4534 "2001:0:0:1/64 resolves via drop");
4535
4536 /*
4537 * no change
4538 */
4539 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4540 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004541 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004542 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004543 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004544 fib_entry_pool_size());
4545
4546 /*
4547 * shutdown one of the other interfaces, then add a connected.
4548 * and swap one of the routes to it.
4549 */
4550 error = vnet_sw_interface_set_flags(vnet_get_main(),
4551 tm->hw[1]->sw_if_index,
4552 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4553 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4554
4555 fib_prefix_t connected_pfx = {
4556 .fp_len = 64,
4557 .fp_proto = FIB_PROTOCOL_IP6,
4558 .fp_addr = {
4559 .ip6 = {
4560 /* 2001:0:0:2::1/64 */
4561 .as_u64 = {
4562 [0] = clib_host_to_net_u64(0x2001000000000002),
4563 [1] = clib_host_to_net_u64(0x0000000000000001),
4564 },
4565 },
4566 }
4567 };
4568 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4569 FIB_SOURCE_INTERFACE,
4570 (FIB_ENTRY_FLAG_CONNECTED |
4571 FIB_ENTRY_FLAG_ATTACHED),
4572 FIB_PROTOCOL_IP6,
4573 NULL,
4574 tm->hw[1]->sw_if_index,
4575 ~0,
4576 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004577 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004578 FIB_ROUTE_PATH_FLAG_NONE);
4579 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4580 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4581 dpo = fib_entry_contribute_ip_forwarding(fei);
4582 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4583 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4584 "2001:0:0:2/64 not resolves via drop");
4585
4586 connected_pfx.fp_len = 128;
4587 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4588 FIB_SOURCE_INTERFACE,
4589 (FIB_ENTRY_FLAG_CONNECTED |
4590 FIB_ENTRY_FLAG_LOCAL),
4591 FIB_PROTOCOL_IP6,
4592 NULL,
4593 tm->hw[0]->sw_if_index,
4594 ~0, // invalid fib index
4595 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004596 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004597 FIB_ROUTE_PATH_FLAG_NONE);
4598 fei = fib_table_lookup(fib_index, &connected_pfx);
4599
4600 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4601 dpo = fib_entry_contribute_ip_forwarding(fei);
4602 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4603 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4604 "local interface adj is local");
4605 rd = receive_dpo_get(dpo->dpoi_index);
4606 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4607 &rd->rd_addr)),
4608 "local interface adj is receive ok");
4609
4610 /*
4611 * +2 entries, +2 unshared path-lists
4612 */
4613 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4614 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004615 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004616 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004617 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004618 fib_entry_pool_size());
4619
4620
4621 /*
4622 * bring the interface back up. we expected the routes to return
4623 * to normal forwarding.
4624 */
4625 error = vnet_sw_interface_set_flags(vnet_get_main(),
4626 tm->hw[0]->sw_if_index,
4627 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4628 FIB_TEST((NULL == error), "Interface bring-up OK");
4629 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4630 ai = fib_entry_get_adj(fei);
4631 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4632 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4633 ai = fib_entry_get_adj(fei);
4634 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4635 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4636 ai = fib_entry_get_adj(fei);
4637 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4638 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4639 ai = fib_entry_get_adj(fei);
4640 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4641 local_pfx.fp_len = 64;
4642 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4643 ai = fib_entry_get_adj(fei);
4644 adj = adj_get(ai);
4645 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4646 "attached interface adj is glean");
4647
4648 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004649 * Same test as above, but this time the HW interface goes down
4650 */
4651 error = vnet_hw_interface_set_flags(vnet_get_main(),
4652 tm->hw_if_indicies[0],
4653 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4654 FIB_TEST((NULL == error), "Interface shutdown OK");
4655
4656 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4657 dpo = fib_entry_contribute_ip_forwarding(fei);
4658 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4659 "2001::b/64 resolves via drop");
4660 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4661 dpo = fib_entry_contribute_ip_forwarding(fei);
4662 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4663 "2001::a/64 resolves via drop");
4664 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4665 dpo = fib_entry_contribute_ip_forwarding(fei);
4666 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4667 "2001:0:0:1::3/128 resolves via drop");
4668 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4669 dpo = fib_entry_contribute_ip_forwarding(fei);
4670 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4671 "2001:0:0:1::2/128 resolves via drop");
4672 local_pfx.fp_len = 128;
4673 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4674 dpo = fib_entry_contribute_ip_forwarding(fei);
4675 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4676 "2001:0:0:1::1/128 not drop");
4677 local_pfx.fp_len = 64;
4678 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4679 dpo = fib_entry_contribute_ip_forwarding(fei);
4680 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4681 "2001:0:0:1/64 resolves via drop");
4682
4683 error = vnet_hw_interface_set_flags(vnet_get_main(),
4684 tm->hw_if_indicies[0],
4685 VNET_HW_INTERFACE_FLAG_LINK_UP);
4686 FIB_TEST((NULL == error), "Interface bring-up OK");
4687 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4688 ai = fib_entry_get_adj(fei);
4689 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4690 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4691 ai = fib_entry_get_adj(fei);
4692 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4693 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4694 ai = fib_entry_get_adj(fei);
4695 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4696 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4697 ai = fib_entry_get_adj(fei);
4698 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4699 local_pfx.fp_len = 64;
4700 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4701 ai = fib_entry_get_adj(fei);
4702 adj = adj_get(ai);
4703 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4704 "attached interface adj is glean");
4705
4706 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004707 * Delete the interface that the routes reolve through.
4708 * Again no routes are removed. They all point to drop.
4709 *
4710 * This is considered an error case. The control plane should
4711 * not remove interfaces through which routes resolve, but
4712 * such things can happen. ALL affected routes will drop.
4713 */
4714 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4715
4716 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4717 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4718 "2001::b/64 resolves via drop");
4719 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4720 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4721 "2001::b/64 resolves via drop");
4722 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4723 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4724 "2001:0:0:1::3/64 resolves via drop");
4725 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4726 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4727 "2001:0:0:1::2/64 resolves via drop");
4728 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4729 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4730 "2001:0:0:1::1/128 is drop");
4731 local_pfx.fp_len = 64;
4732 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4733 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4734 "2001:0:0:1/64 resolves via drop");
4735
4736 /*
4737 * no change
4738 */
4739 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4740 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004741 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004742 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004743 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004744 fib_entry_pool_size());
4745
4746 /*
4747 * Add the interface back. routes stay unresolved.
4748 */
4749 error = ethernet_register_interface(vnet_get_main(),
4750 test_interface_device_class.index,
4751 0 /* instance */,
4752 hw_address,
4753 &tm->hw_if_indicies[0],
4754 /* flag change */ 0);
4755
4756 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4757 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4758 "2001::b/64 resolves via drop");
4759 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4760 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4761 "2001::b/64 resolves via drop");
4762 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4763 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4764 "2001:0:0:1::3/64 resolves via drop");
4765 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4766 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4767 "2001:0:0:1::2/64 resolves via drop");
4768 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4769 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4770 "2001:0:0:1::1/128 is drop");
4771 local_pfx.fp_len = 64;
4772 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4773 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4774 "2001:0:0:1/64 resolves via drop");
4775
4776 /*
4777 * CLEANUP ALL the routes
4778 */
4779 fib_table_entry_delete(fib_index,
4780 &pfx_2001_c_s_64,
4781 FIB_SOURCE_API);
4782 fib_table_entry_delete(fib_index,
4783 &pfx_2001_a_s_64,
4784 FIB_SOURCE_API);
4785 fib_table_entry_delete(fib_index,
4786 &pfx_2001_b_s_64,
4787 FIB_SOURCE_API);
4788 fib_table_entry_delete(fib_index,
4789 &pfx_2001_1_3_s_128,
4790 FIB_SOURCE_ADJ);
4791 fib_table_entry_delete(fib_index,
4792 &pfx_2001_1_2_s_128,
4793 FIB_SOURCE_ADJ);
4794 local_pfx.fp_len = 64;
4795 fib_table_entry_delete(fib_index, &local_pfx,
4796 FIB_SOURCE_INTERFACE);
4797 local_pfx.fp_len = 128;
4798 fib_table_entry_special_remove(fib_index, &local_pfx,
4799 FIB_SOURCE_INTERFACE);
4800 connected_pfx.fp_len = 64;
4801 fib_table_entry_delete(fib_index, &connected_pfx,
4802 FIB_SOURCE_INTERFACE);
4803 connected_pfx.fp_len = 128;
4804 fib_table_entry_special_remove(fib_index, &connected_pfx,
4805 FIB_SOURCE_INTERFACE);
4806
4807 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4808 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4809 "2001::a/64 removed");
4810 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4811 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4812 "2001::b/64 removed");
4813 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4814 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4815 "2001:0:0:1::3/128 removed");
4816 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4817 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4818 "2001:0:0:1::3/128 removed");
4819 local_pfx.fp_len = 64;
4820 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4821 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4822 "2001:0:0:1/64 removed");
4823 local_pfx.fp_len = 128;
4824 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4825 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4826 "2001:0:0:1::1/128 removed");
4827 connected_pfx.fp_len = 64;
4828 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4829 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4830 "2001:0:0:2/64 removed");
4831 connected_pfx.fp_len = 128;
4832 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4833 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4834 "2001:0:0:2::1/128 removed");
4835
4836 /*
4837 * -8 entries. -7 path-lists (1 was shared).
4838 */
4839 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4840 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004841 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004842 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004843 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004844 fib_entry_pool_size());
4845
4846 /*
4847 * now remove the VRF
4848 */
4849 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4850
4851 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4852 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004853 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004854 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004855 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004856 fib_entry_pool_size());
4857
4858 adj_unlock(ai_02);
4859 adj_unlock(ai_01);
4860
4861 /*
4862 * return the interfaces to up state
4863 */
4864 error = vnet_sw_interface_set_flags(vnet_get_main(),
4865 tm->hw[0]->sw_if_index,
4866 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4867 error = vnet_sw_interface_set_flags(vnet_get_main(),
4868 tm->hw[1]->sw_if_index,
4869 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4870
4871 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4872 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004873
4874 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004875}
4876
4877/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004878 * Test Attached Exports
4879 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004880static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004881fib_test_ae (void)
4882{
4883 const dpo_id_t *dpo, *dpo_drop;
4884 const u32 fib_index = 0;
4885 fib_node_index_t fei;
4886 test_main_t *tm;
4887 ip4_main_t *im;
4888
4889 tm = &test_main;
4890 im = &ip4_main;
4891
4892 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4893 adj_nbr_db_size());
4894
4895 /*
4896 * add interface routes. We'll assume this works. It's more rigorously
4897 * tested elsewhere.
4898 */
4899 fib_prefix_t local_pfx = {
4900 .fp_len = 24,
4901 .fp_proto = FIB_PROTOCOL_IP4,
4902 .fp_addr = {
4903 .ip4 = {
4904 /* 10.10.10.10 */
4905 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4906 },
4907 },
4908 };
4909
4910 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4911 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4912
4913 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4914
4915 fib_table_entry_update_one_path(fib_index, &local_pfx,
4916 FIB_SOURCE_INTERFACE,
4917 (FIB_ENTRY_FLAG_CONNECTED |
4918 FIB_ENTRY_FLAG_ATTACHED),
4919 FIB_PROTOCOL_IP4,
4920 NULL,
4921 tm->hw[0]->sw_if_index,
4922 ~0,
4923 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004924 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004925 FIB_ROUTE_PATH_FLAG_NONE);
4926 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4927 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4928 "attached interface route present");
4929
4930 local_pfx.fp_len = 32;
4931 fib_table_entry_update_one_path(fib_index, &local_pfx,
4932 FIB_SOURCE_INTERFACE,
4933 (FIB_ENTRY_FLAG_CONNECTED |
4934 FIB_ENTRY_FLAG_LOCAL),
4935 FIB_PROTOCOL_IP4,
4936 NULL,
4937 tm->hw[0]->sw_if_index,
4938 ~0, // invalid fib index
4939 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004940 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004941 FIB_ROUTE_PATH_FLAG_NONE);
4942 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4943
4944 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4945 "local interface route present");
4946
4947 /*
4948 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4949 */
4950 fib_prefix_t pfx_10_10_10_1_s_32 = {
4951 .fp_len = 32,
4952 .fp_proto = FIB_PROTOCOL_IP4,
4953 .fp_addr = {
4954 /* 10.10.10.1 */
4955 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4956 },
4957 };
4958 fib_node_index_t ai;
4959
4960 fib_table_entry_update_one_path(fib_index,
4961 &pfx_10_10_10_1_s_32,
4962 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004963 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004964 FIB_PROTOCOL_IP4,
4965 &pfx_10_10_10_1_s_32.fp_addr,
4966 tm->hw[0]->sw_if_index,
4967 ~0, // invalid fib index
4968 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004969 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004970 FIB_ROUTE_PATH_FLAG_NONE);
4971
4972 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4973 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4974 ai = fib_entry_get_adj(fei);
4975
4976 /*
4977 * create another FIB table into which routes will be imported
4978 */
4979 u32 import_fib_index1;
4980
4981 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4982
4983 /*
4984 * Add an attached route in the import FIB
4985 */
4986 local_pfx.fp_len = 24;
4987 fib_table_entry_update_one_path(import_fib_index1,
4988 &local_pfx,
4989 FIB_SOURCE_API,
4990 FIB_ENTRY_FLAG_NONE,
4991 FIB_PROTOCOL_IP4,
4992 NULL,
4993 tm->hw[0]->sw_if_index,
4994 ~0, // invalid fib index
4995 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004996 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004997 FIB_ROUTE_PATH_FLAG_NONE);
4998 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4999 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5000
5001 /*
5002 * check for the presence of the adj-fibs in the import table
5003 */
5004 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5005 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5006 FIB_TEST((ai == fib_entry_get_adj(fei)),
5007 "adj-fib1 Import uses same adj as export");
5008
5009 /*
5010 * check for the presence of the local in the import table
5011 */
5012 local_pfx.fp_len = 32;
5013 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5014 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5015
5016 /*
5017 * Add another adj-fin in the export table. Expect this
5018 * to get magically exported;
5019 */
5020 fib_prefix_t pfx_10_10_10_2_s_32 = {
5021 .fp_len = 32,
5022 .fp_proto = FIB_PROTOCOL_IP4,
5023 .fp_addr = {
5024 /* 10.10.10.2 */
5025 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5026 },
5027 };
5028
5029 fib_table_entry_update_one_path(fib_index,
5030 &pfx_10_10_10_2_s_32,
5031 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00005032 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005033 FIB_PROTOCOL_IP4,
5034 &pfx_10_10_10_2_s_32.fp_addr,
5035 tm->hw[0]->sw_if_index,
5036 ~0, // invalid fib index
5037 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005038 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005039 FIB_ROUTE_PATH_FLAG_NONE);
5040 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5041 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5042 ai = fib_entry_get_adj(fei);
5043
5044 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5045 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5046 FIB_TEST((ai == fib_entry_get_adj(fei)),
5047 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005048 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5049 "ADJ-fib2 imported flags %d",
5050 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005051
5052 /*
5053 * create a 2nd FIB table into which routes will be imported
5054 */
5055 u32 import_fib_index2;
5056
5057 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
5058
5059 /*
5060 * Add an attached route in the import FIB
5061 */
5062 local_pfx.fp_len = 24;
5063 fib_table_entry_update_one_path(import_fib_index2,
5064 &local_pfx,
5065 FIB_SOURCE_API,
5066 FIB_ENTRY_FLAG_NONE,
5067 FIB_PROTOCOL_IP4,
5068 NULL,
5069 tm->hw[0]->sw_if_index,
5070 ~0, // invalid fib index
5071 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005072 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005073 FIB_ROUTE_PATH_FLAG_NONE);
5074 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5075 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5076
5077 /*
5078 * check for the presence of all the adj-fibs and local in the import table
5079 */
5080 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5081 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5082 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5083 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5084 local_pfx.fp_len = 32;
5085 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5086 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5087
5088 /*
5089 * add a 3rd adj-fib. expect it to be exported to both tables.
5090 */
5091 fib_prefix_t pfx_10_10_10_3_s_32 = {
5092 .fp_len = 32,
5093 .fp_proto = FIB_PROTOCOL_IP4,
5094 .fp_addr = {
5095 /* 10.10.10.3 */
5096 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5097 },
5098 };
5099
5100 fib_table_entry_update_one_path(fib_index,
5101 &pfx_10_10_10_3_s_32,
5102 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00005103 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005104 FIB_PROTOCOL_IP4,
5105 &pfx_10_10_10_3_s_32.fp_addr,
5106 tm->hw[0]->sw_if_index,
5107 ~0, // invalid fib index
5108 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005109 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005110 FIB_ROUTE_PATH_FLAG_NONE);
5111 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5112 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5113 ai = fib_entry_get_adj(fei);
5114
5115 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5116 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5117 FIB_TEST((ai == fib_entry_get_adj(fei)),
5118 "Import uses same adj as export");
5119 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5120 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5121 FIB_TEST((ai == fib_entry_get_adj(fei)),
5122 "Import uses same adj as export");
5123
5124 /*
5125 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5126 */
5127 fib_table_entry_delete(fib_index,
5128 &pfx_10_10_10_3_s_32,
5129 FIB_SOURCE_ADJ);
5130
5131 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5132 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5133
5134 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5135 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5136
5137 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5138 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5139
5140 /*
5141 * remove the attached route from the 2nd FIB. expect the imported
5142 * entires to be removed
5143 */
5144 local_pfx.fp_len = 24;
5145 fib_table_entry_delete(import_fib_index2,
5146 &local_pfx,
5147 FIB_SOURCE_API);
5148 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5149 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5150
5151 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5152 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5153 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5154 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5155 local_pfx.fp_len = 32;
5156 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5157 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5158
5159 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5160 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5161 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5162 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5163 local_pfx.fp_len = 32;
5164 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5165 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5166
5167 /*
5168 * modify the route in FIB1 so it is no longer attached. expect the imported
5169 * entires to be removed
5170 */
5171 local_pfx.fp_len = 24;
5172 fib_table_entry_update_one_path(import_fib_index1,
5173 &local_pfx,
5174 FIB_SOURCE_API,
5175 FIB_ENTRY_FLAG_NONE,
5176 FIB_PROTOCOL_IP4,
5177 &pfx_10_10_10_2_s_32.fp_addr,
5178 tm->hw[0]->sw_if_index,
5179 ~0, // invalid fib index
5180 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005181 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005182 FIB_ROUTE_PATH_FLAG_NONE);
5183 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5184 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5185 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5186 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5187 local_pfx.fp_len = 32;
5188 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5189 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5190
5191 /*
5192 * modify it back to attached. expect the adj-fibs back
5193 */
5194 local_pfx.fp_len = 24;
5195 fib_table_entry_update_one_path(import_fib_index1,
5196 &local_pfx,
5197 FIB_SOURCE_API,
5198 FIB_ENTRY_FLAG_NONE,
5199 FIB_PROTOCOL_IP4,
5200 NULL,
5201 tm->hw[0]->sw_if_index,
5202 ~0, // invalid fib index
5203 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005204 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005205 FIB_ROUTE_PATH_FLAG_NONE);
5206 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5207 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5208 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5209 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5210 local_pfx.fp_len = 32;
5211 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5212 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5213
5214 /*
5215 * add a covering attached next-hop for the interface address, so we have
5216 * a valid adj to find when we check the forwarding tables
5217 */
5218 fib_prefix_t pfx_10_0_0_0_s_8 = {
5219 .fp_len = 8,
5220 .fp_proto = FIB_PROTOCOL_IP4,
5221 .fp_addr = {
5222 /* 10.0.0.0 */
5223 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5224 },
5225 };
5226
5227 fei = fib_table_entry_update_one_path(fib_index,
5228 &pfx_10_0_0_0_s_8,
5229 FIB_SOURCE_API,
5230 FIB_ENTRY_FLAG_NONE,
5231 FIB_PROTOCOL_IP4,
5232 &pfx_10_10_10_3_s_32.fp_addr,
5233 tm->hw[0]->sw_if_index,
5234 ~0, // invalid fib index
5235 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005236 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005237 FIB_ROUTE_PATH_FLAG_NONE);
5238 dpo = fib_entry_contribute_ip_forwarding(fei);
5239
5240 /*
5241 * remove the route in the export fib. expect the adj-fibs to be removed
5242 */
5243 local_pfx.fp_len = 24;
5244 fib_table_entry_delete(fib_index,
5245 &local_pfx,
5246 FIB_SOURCE_INTERFACE);
5247
5248 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5249 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5250 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5251 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5252 local_pfx.fp_len = 32;
5253 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5254 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5255
5256 /*
5257 * the adj-fibs in the export VRF are present in the FIB table,
5258 * but not installed in forwarding, since they have no attached cover.
5259 * Consequently a lookup in the MTRIE gives the adj for the covering
5260 * route 10.0.0.0/8.
5261 */
5262 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5263 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5264
5265 index_t lbi;
5266 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5267 FIB_TEST(lbi == dpo->dpoi_index,
5268 "10.10.10.1 forwards on \n%U not \n%U",
5269 format_load_balance, lbi, 0,
5270 format_dpo_id, dpo, 0);
5271 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5272 FIB_TEST(lbi == dpo->dpoi_index,
5273 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5274 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5275 FIB_TEST(lbi == dpo->dpoi_index,
5276 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5277
5278 /*
5279 * add the export prefix back, but not as attached.
5280 * No adj-fibs in export nor import tables
5281 */
5282 local_pfx.fp_len = 24;
5283 fei = fib_table_entry_update_one_path(fib_index,
5284 &local_pfx,
5285 FIB_SOURCE_API,
5286 FIB_ENTRY_FLAG_NONE,
5287 FIB_PROTOCOL_IP4,
5288 &pfx_10_10_10_1_s_32.fp_addr,
5289 tm->hw[0]->sw_if_index,
5290 ~0, // invalid fib index
5291 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005292 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005293 FIB_ROUTE_PATH_FLAG_NONE);
5294 dpo = fib_entry_contribute_ip_forwarding(fei);
5295
5296 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5297 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5298 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5299 FIB_TEST(lbi == dpo->dpoi_index,
5300 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5301 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5302 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5303 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5304 FIB_TEST(lbi == dpo->dpoi_index,
5305 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5306
5307 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5308 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5309 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5310 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5311 local_pfx.fp_len = 32;
5312 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5313 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5314
5315 /*
5316 * modify the export prefix so it is attached. expect all covereds to return
5317 */
5318 local_pfx.fp_len = 24;
5319 fib_table_entry_update_one_path(fib_index,
5320 &local_pfx,
5321 FIB_SOURCE_API,
5322 FIB_ENTRY_FLAG_NONE,
5323 FIB_PROTOCOL_IP4,
5324 NULL,
5325 tm->hw[0]->sw_if_index,
5326 ~0, // invalid fib index
5327 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005328 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005329 FIB_ROUTE_PATH_FLAG_NONE);
5330
5331 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5332 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5333 dpo = fib_entry_contribute_ip_forwarding(fei);
5334 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5335 "Adj-fib1 is not drop in export");
5336 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5337 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5338 local_pfx.fp_len = 32;
5339 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5340 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5341 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5342 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5343 dpo = fib_entry_contribute_ip_forwarding(fei);
5344 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5345 "Adj-fib1 is not drop in export");
5346 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5347 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5348 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5349 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5350 local_pfx.fp_len = 32;
5351 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5352 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5353
5354 /*
5355 * modify the export prefix so connected. no change.
5356 */
5357 local_pfx.fp_len = 24;
5358 fib_table_entry_update_one_path(fib_index, &local_pfx,
5359 FIB_SOURCE_INTERFACE,
5360 (FIB_ENTRY_FLAG_CONNECTED |
5361 FIB_ENTRY_FLAG_ATTACHED),
5362 FIB_PROTOCOL_IP4,
5363 NULL,
5364 tm->hw[0]->sw_if_index,
5365 ~0,
5366 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005367 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005368 FIB_ROUTE_PATH_FLAG_NONE);
5369
5370 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5371 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5372 dpo = fib_entry_contribute_ip_forwarding(fei);
5373 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5374 "Adj-fib1 is not drop in export");
5375 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5376 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5377 local_pfx.fp_len = 32;
5378 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5379 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5380 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5381 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5382 dpo = fib_entry_contribute_ip_forwarding(fei);
5383 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5384 "Adj-fib1 is not drop in export");
5385 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5386 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5387 local_pfx.fp_len = 32;
5388 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5389 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5390
5391 /*
5392 * CLEANUP
5393 */
5394 fib_table_entry_delete(fib_index,
5395 &pfx_10_0_0_0_s_8,
5396 FIB_SOURCE_API);
5397 fib_table_entry_delete(fib_index,
5398 &pfx_10_10_10_1_s_32,
5399 FIB_SOURCE_ADJ);
5400 fib_table_entry_delete(fib_index,
5401 &pfx_10_10_10_2_s_32,
5402 FIB_SOURCE_ADJ);
5403 local_pfx.fp_len = 32;
5404 fib_table_entry_delete(fib_index,
5405 &local_pfx,
5406 FIB_SOURCE_INTERFACE);
5407 local_pfx.fp_len = 24;
5408 fib_table_entry_delete(fib_index,
5409 &local_pfx,
5410 FIB_SOURCE_API);
5411 fib_table_entry_delete(fib_index,
5412 &local_pfx,
5413 FIB_SOURCE_INTERFACE);
5414 local_pfx.fp_len = 24;
5415 fib_table_entry_delete(import_fib_index1,
5416 &local_pfx,
5417 FIB_SOURCE_API);
5418
5419 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5420 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5421
5422 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5423 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005424
5425 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005426}
5427
Neale Rannsad422ed2016-11-02 14:20:04 +00005428
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005429/*
5430 * Test the recursive route route handling for GRE tunnels
5431 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005432static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005433fib_test_label (void)
5434{
5435 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;
5436 const u32 fib_index = 0;
5437 test_main_t *tm;
5438 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005439 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005440
5441 lb_count = pool_elts(load_balance_pool);
5442 tm = &test_main;
5443 im = &ip4_main;
5444
5445 /*
5446 * add interface routes. We'll assume this works. It's more rigorously
5447 * tested elsewhere.
5448 */
5449 fib_prefix_t local0_pfx = {
5450 .fp_len = 24,
5451 .fp_proto = FIB_PROTOCOL_IP4,
5452 .fp_addr = {
5453 .ip4 = {
5454 /* 10.10.10.10 */
5455 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5456 },
5457 },
5458 };
5459
5460 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5461 adj_nbr_db_size());
5462
5463 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5464 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5465
5466 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5467 FIB_SOURCE_INTERFACE,
5468 (FIB_ENTRY_FLAG_CONNECTED |
5469 FIB_ENTRY_FLAG_ATTACHED),
5470 FIB_PROTOCOL_IP4,
5471 NULL,
5472 tm->hw[0]->sw_if_index,
5473 ~0,
5474 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005475 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005476 FIB_ROUTE_PATH_FLAG_NONE);
5477 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5478 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5479 "attached interface route present");
5480
5481 local0_pfx.fp_len = 32;
5482 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5483 FIB_SOURCE_INTERFACE,
5484 (FIB_ENTRY_FLAG_CONNECTED |
5485 FIB_ENTRY_FLAG_LOCAL),
5486 FIB_PROTOCOL_IP4,
5487 NULL,
5488 tm->hw[0]->sw_if_index,
5489 ~0, // invalid fib index
5490 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005491 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005492 FIB_ROUTE_PATH_FLAG_NONE);
5493 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5494
5495 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5496 "local interface route present");
5497
5498 fib_prefix_t local1_pfx = {
5499 .fp_len = 24,
5500 .fp_proto = FIB_PROTOCOL_IP4,
5501 .fp_addr = {
5502 .ip4 = {
5503 /* 10.10.11.10 */
5504 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5505 },
5506 },
5507 };
5508
5509 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5510 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5511
5512 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5513 FIB_SOURCE_INTERFACE,
5514 (FIB_ENTRY_FLAG_CONNECTED |
5515 FIB_ENTRY_FLAG_ATTACHED),
5516 FIB_PROTOCOL_IP4,
5517 NULL,
5518 tm->hw[1]->sw_if_index,
5519 ~0,
5520 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005521 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005522 FIB_ROUTE_PATH_FLAG_NONE);
5523 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5524 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5525 "attached interface route present");
5526
5527 local1_pfx.fp_len = 32;
5528 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5529 FIB_SOURCE_INTERFACE,
5530 (FIB_ENTRY_FLAG_CONNECTED |
5531 FIB_ENTRY_FLAG_LOCAL),
5532 FIB_PROTOCOL_IP4,
5533 NULL,
5534 tm->hw[1]->sw_if_index,
5535 ~0, // invalid fib index
5536 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005537 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005538 FIB_ROUTE_PATH_FLAG_NONE);
5539 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5540
5541 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5542 "local interface route present");
5543
5544 ip46_address_t nh_10_10_10_1 = {
5545 .ip4 = {
5546 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5547 },
5548 };
5549 ip46_address_t nh_10_10_11_1 = {
5550 .ip4 = {
5551 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5552 },
5553 };
5554 ip46_address_t nh_10_10_11_2 = {
5555 .ip4 = {
5556 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5557 },
5558 };
5559
5560 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005561 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005562 &nh_10_10_11_1,
5563 tm->hw[1]->sw_if_index);
5564 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005565 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005566 &nh_10_10_11_2,
5567 tm->hw[1]->sw_if_index);
5568 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005569 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005570 &nh_10_10_10_1,
5571 tm->hw[0]->sw_if_index);
5572 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005573 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005574 &nh_10_10_11_2,
5575 tm->hw[1]->sw_if_index);
5576 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005577 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005578 &nh_10_10_11_1,
5579 tm->hw[1]->sw_if_index);
5580
5581 /*
5582 * Add an etry with one path with a real out-going label
5583 */
5584 fib_prefix_t pfx_1_1_1_1_s_32 = {
5585 .fp_len = 32,
5586 .fp_proto = FIB_PROTOCOL_IP4,
5587 .fp_addr = {
5588 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5589 },
5590 };
5591 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5592 .type = FT_LB_LABEL_O_ADJ,
5593 .label_o_adj = {
5594 .adj = ai_mpls_10_10_10_1,
5595 .label = 99,
5596 .eos = MPLS_EOS,
5597 },
5598 };
5599 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5600 .type = FT_LB_LABEL_O_ADJ,
5601 .label_o_adj = {
5602 .adj = ai_mpls_10_10_10_1,
5603 .label = 99,
5604 .eos = MPLS_NON_EOS,
5605 },
5606 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005607 mpls_label_t *l99 = NULL;
5608 vec_add1(l99, 99);
5609
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005610 fib_table_entry_update_one_path(fib_index,
5611 &pfx_1_1_1_1_s_32,
5612 FIB_SOURCE_API,
5613 FIB_ENTRY_FLAG_NONE,
5614 FIB_PROTOCOL_IP4,
5615 &nh_10_10_10_1,
5616 tm->hw[0]->sw_if_index,
5617 ~0, // invalid fib index
5618 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005619 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005620 FIB_ROUTE_PATH_FLAG_NONE);
5621
5622 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5623 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5624
5625 FIB_TEST(fib_test_validate_entry(fei,
5626 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5627 1,
5628 &l99_eos_o_10_10_10_1),
5629 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5630
5631 /*
5632 * add a path with an implicit NULL label
5633 */
5634 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5635 .type = FT_LB_ADJ,
5636 .adj = {
5637 .adj = ai_v4_10_10_11_1,
5638 },
5639 };
5640 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5641 .type = FT_LB_ADJ,
5642 .adj = {
5643 .adj = ai_mpls_10_10_11_1,
5644 },
5645 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005646 mpls_label_t *l_imp_null = NULL;
5647 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005648
5649 fei = fib_table_entry_path_add(fib_index,
5650 &pfx_1_1_1_1_s_32,
5651 FIB_SOURCE_API,
5652 FIB_ENTRY_FLAG_NONE,
5653 FIB_PROTOCOL_IP4,
5654 &nh_10_10_11_1,
5655 tm->hw[1]->sw_if_index,
5656 ~0, // invalid fib index
5657 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005658 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005659 FIB_ROUTE_PATH_FLAG_NONE);
5660
5661 FIB_TEST(fib_test_validate_entry(fei,
5662 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5663 2,
5664 &l99_eos_o_10_10_10_1,
5665 &a_o_10_10_11_1),
5666 "1.1.1.1/32 LB 2 buckets via: "
5667 "label 99 over 10.10.10.1, "
5668 "adj over 10.10.11.1");
5669
5670 /*
5671 * assign the route a local label
5672 */
5673 fib_table_entry_local_label_add(fib_index,
5674 &pfx_1_1_1_1_s_32,
5675 24001);
5676
5677 fib_prefix_t pfx_24001_eos = {
5678 .fp_proto = FIB_PROTOCOL_MPLS,
5679 .fp_label = 24001,
5680 .fp_eos = MPLS_EOS,
5681 };
5682 fib_prefix_t pfx_24001_neos = {
5683 .fp_proto = FIB_PROTOCOL_MPLS,
5684 .fp_label = 24001,
5685 .fp_eos = MPLS_NON_EOS,
5686 };
5687
5688 /*
5689 * The EOS entry should link to both the paths,
5690 * and use an ip adj for the imp-null
5691 * The NON-EOS entry should link to both the paths,
5692 * and use an mpls adj for the imp-null
5693 */
5694 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5695 &pfx_24001_eos);
5696 FIB_TEST(fib_test_validate_entry(fei,
5697 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5698 2,
5699 &l99_eos_o_10_10_10_1,
5700 &a_o_10_10_11_1),
5701 "24001/eos LB 2 buckets via: "
5702 "label 99 over 10.10.10.1, "
5703 "adj over 10.10.11.1");
5704
5705
5706 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5707 &pfx_24001_neos);
5708 FIB_TEST(fib_test_validate_entry(fei,
5709 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5710 2,
5711 &l99_neos_o_10_10_10_1,
5712 &a_mpls_o_10_10_11_1),
5713 "24001/neos LB 1 bucket via: "
5714 "label 99 over 10.10.10.1 ",
5715 "mpls-adj via 10.10.11.1");
5716
5717 /*
5718 * add an unlabelled path, this is excluded from the neos chains,
5719 */
5720 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5721 .type = FT_LB_ADJ,
5722 .adj = {
5723 .adj = ai_v4_10_10_11_2,
5724 },
5725 };
5726
5727 fei = fib_table_entry_path_add(fib_index,
5728 &pfx_1_1_1_1_s_32,
5729 FIB_SOURCE_API,
5730 FIB_ENTRY_FLAG_NONE,
5731 FIB_PROTOCOL_IP4,
5732 &nh_10_10_11_2,
5733 tm->hw[1]->sw_if_index,
5734 ~0, // invalid fib index
5735 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005736 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005737 FIB_ROUTE_PATH_FLAG_NONE);
5738
5739 FIB_TEST(fib_test_validate_entry(fei,
5740 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5741 16, // 3 choices spread over 16 buckets
5742 &l99_eos_o_10_10_10_1,
5743 &l99_eos_o_10_10_10_1,
5744 &l99_eos_o_10_10_10_1,
5745 &l99_eos_o_10_10_10_1,
5746 &l99_eos_o_10_10_10_1,
5747 &l99_eos_o_10_10_10_1,
5748 &a_o_10_10_11_1,
5749 &a_o_10_10_11_1,
5750 &a_o_10_10_11_1,
5751 &a_o_10_10_11_1,
5752 &a_o_10_10_11_1,
5753 &adj_o_10_10_11_2,
5754 &adj_o_10_10_11_2,
5755 &adj_o_10_10_11_2,
5756 &adj_o_10_10_11_2,
5757 &adj_o_10_10_11_2),
5758 "1.1.1.1/32 LB 16 buckets via: "
5759 "label 99 over 10.10.10.1, "
5760 "adj over 10.10.11.1",
5761 "adj over 10.10.11.2");
5762
5763 /*
5764 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5765 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005766 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005767 fib_entry_contribute_forwarding(fei,
5768 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5769 &non_eos_1_1_1_1);
5770
5771 /*
5772 * n-eos has only the 2 labelled paths
5773 */
5774 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5775 &pfx_24001_neos);
5776
5777 FIB_TEST(fib_test_validate_entry(fei,
5778 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5779 2,
5780 &l99_neos_o_10_10_10_1,
5781 &a_mpls_o_10_10_11_1),
5782 "24001/neos LB 2 buckets via: "
5783 "label 99 over 10.10.10.1, "
5784 "adj-mpls over 10.10.11.2");
5785
5786 /*
5787 * A labelled recursive
5788 */
5789 fib_prefix_t pfx_2_2_2_2_s_32 = {
5790 .fp_len = 32,
5791 .fp_proto = FIB_PROTOCOL_IP4,
5792 .fp_addr = {
5793 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5794 },
5795 };
5796 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5797 .type = FT_LB_LABEL_O_LB,
5798 .label_o_lb = {
5799 .lb = non_eos_1_1_1_1.dpoi_index,
5800 .label = 1600,
5801 .eos = MPLS_EOS,
5802 },
5803 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005804 mpls_label_t *l1600 = NULL;
5805 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005806
5807 fib_table_entry_update_one_path(fib_index,
5808 &pfx_2_2_2_2_s_32,
5809 FIB_SOURCE_API,
5810 FIB_ENTRY_FLAG_NONE,
5811 FIB_PROTOCOL_IP4,
5812 &pfx_1_1_1_1_s_32.fp_addr,
5813 ~0,
5814 fib_index,
5815 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005816 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005817 FIB_ROUTE_PATH_FLAG_NONE);
5818
5819 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5820 FIB_TEST(fib_test_validate_entry(fei,
5821 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5822 1,
5823 &l1600_eos_o_1_1_1_1),
5824 "2.2.2.2.2/32 LB 1 buckets via: "
5825 "label 1600 over 1.1.1.1");
5826
Neale Ranns948e00f2016-10-20 13:39:34 +01005827 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005828 index_t urpfi;
5829
5830 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5831 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5832
5833 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5834 "uRPF check for 2.2.2.2/32 on %d OK",
5835 tm->hw[0]->sw_if_index);
5836 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5837 "uRPF check for 2.2.2.2/32 on %d OK",
5838 tm->hw[1]->sw_if_index);
5839 FIB_TEST(!fib_urpf_check(urpfi, 99),
5840 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5841 99);
5842
5843 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5844 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5845 "Shared uRPF on IP and non-EOS chain");
5846
5847 dpo_reset(&dpo_44);
5848
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005849 /*
5850 * we are holding a lock on the non-eos LB of the via-entry.
5851 * do a PIC-core failover by shutting the link of the via-entry.
5852 *
5853 * shut down the link with the valid label
5854 */
5855 vnet_sw_interface_set_flags(vnet_get_main(),
5856 tm->hw[0]->sw_if_index,
5857 0);
5858
5859 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5860 FIB_TEST(fib_test_validate_entry(fei,
5861 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5862 2,
5863 &a_o_10_10_11_1,
5864 &adj_o_10_10_11_2),
5865 "1.1.1.1/32 LB 2 buckets via: "
5866 "adj over 10.10.11.1, ",
5867 "adj-v4 over 10.10.11.2");
5868
5869 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5870 &pfx_24001_eos);
5871 FIB_TEST(fib_test_validate_entry(fei,
5872 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5873 2,
5874 &a_o_10_10_11_1,
5875 &adj_o_10_10_11_2),
5876 "24001/eos LB 2 buckets via: "
5877 "adj over 10.10.11.1, ",
5878 "adj-v4 over 10.10.11.2");
5879
5880 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5881 &pfx_24001_neos);
5882 FIB_TEST(fib_test_validate_entry(fei,
5883 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5884 1,
5885 &a_mpls_o_10_10_11_1),
5886 "24001/neos LB 1 buckets via: "
5887 "adj-mpls over 10.10.11.2");
5888
5889 /*
5890 * test that the pre-failover load-balance has been in-place
5891 * modified
5892 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005893 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005894 fib_entry_contribute_forwarding(fei,
5895 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5896 &current);
5897
5898 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5899 &current),
5900 "PIC-core LB inplace modified %U %U",
5901 format_dpo_id, &non_eos_1_1_1_1, 0,
5902 format_dpo_id, &current, 0);
5903
5904 dpo_reset(&non_eos_1_1_1_1);
5905 dpo_reset(&current);
5906
5907 /*
5908 * no-shut the link with the valid label
5909 */
5910 vnet_sw_interface_set_flags(vnet_get_main(),
5911 tm->hw[0]->sw_if_index,
5912 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5913
5914 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5915 FIB_TEST(fib_test_validate_entry(fei,
5916 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5917 16, // 3 choices spread over 16 buckets
5918 &l99_eos_o_10_10_10_1,
5919 &l99_eos_o_10_10_10_1,
5920 &l99_eos_o_10_10_10_1,
5921 &l99_eos_o_10_10_10_1,
5922 &l99_eos_o_10_10_10_1,
5923 &l99_eos_o_10_10_10_1,
5924 &a_o_10_10_11_1,
5925 &a_o_10_10_11_1,
5926 &a_o_10_10_11_1,
5927 &a_o_10_10_11_1,
5928 &a_o_10_10_11_1,
5929 &adj_o_10_10_11_2,
5930 &adj_o_10_10_11_2,
5931 &adj_o_10_10_11_2,
5932 &adj_o_10_10_11_2,
5933 &adj_o_10_10_11_2),
5934 "1.1.1.1/32 LB 16 buckets via: "
5935 "label 99 over 10.10.10.1, "
5936 "adj over 10.10.11.1",
5937 "adj-v4 over 10.10.11.2");
5938
5939
5940 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5941 &pfx_24001_eos);
5942 FIB_TEST(fib_test_validate_entry(fei,
5943 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5944 16, // 3 choices spread over 16 buckets
5945 &l99_eos_o_10_10_10_1,
5946 &l99_eos_o_10_10_10_1,
5947 &l99_eos_o_10_10_10_1,
5948 &l99_eos_o_10_10_10_1,
5949 &l99_eos_o_10_10_10_1,
5950 &l99_eos_o_10_10_10_1,
5951 &a_o_10_10_11_1,
5952 &a_o_10_10_11_1,
5953 &a_o_10_10_11_1,
5954 &a_o_10_10_11_1,
5955 &a_o_10_10_11_1,
5956 &adj_o_10_10_11_2,
5957 &adj_o_10_10_11_2,
5958 &adj_o_10_10_11_2,
5959 &adj_o_10_10_11_2,
5960 &adj_o_10_10_11_2),
5961 "24001/eos LB 16 buckets via: "
5962 "label 99 over 10.10.10.1, "
5963 "adj over 10.10.11.1",
5964 "adj-v4 over 10.10.11.2");
5965
5966 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5967 &pfx_24001_neos);
5968 FIB_TEST(fib_test_validate_entry(fei,
5969 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5970 2,
5971 &l99_neos_o_10_10_10_1,
5972 &a_mpls_o_10_10_11_1),
5973 "24001/neos LB 2 buckets via: "
5974 "label 99 over 10.10.10.1, "
5975 "adj-mpls over 10.10.11.2");
5976
5977 /*
5978 * remove the first path with the valid label
5979 */
5980 fib_table_entry_path_remove(fib_index,
5981 &pfx_1_1_1_1_s_32,
5982 FIB_SOURCE_API,
5983 FIB_PROTOCOL_IP4,
5984 &nh_10_10_10_1,
5985 tm->hw[0]->sw_if_index,
5986 ~0, // invalid fib index
5987 1,
5988 FIB_ROUTE_PATH_FLAG_NONE);
5989
5990 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5991 FIB_TEST(fib_test_validate_entry(fei,
5992 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5993 2,
5994 &a_o_10_10_11_1,
5995 &adj_o_10_10_11_2),
5996 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07005997 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005998 "adj-v4 over 10.10.11.2");
5999
6000 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6001 &pfx_24001_eos);
6002 FIB_TEST(fib_test_validate_entry(fei,
6003 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6004 2,
6005 &a_o_10_10_11_1,
6006 &adj_o_10_10_11_2),
6007 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006008 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006009 "adj-v4 over 10.10.11.2");
6010
6011 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6012 &pfx_24001_neos);
6013
6014 FIB_TEST(fib_test_validate_entry(fei,
6015 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6016 1,
6017 &a_mpls_o_10_10_11_1),
6018 "24001/neos LB 1 buckets via: "
6019 "adj-mpls over 10.10.11.2");
6020
6021 /*
6022 * remove the other path with a valid label
6023 */
6024 fib_test_lb_bucket_t bucket_drop = {
6025 .type = FT_LB_SPECIAL,
6026 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00006027 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006028 },
6029 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006030 fib_test_lb_bucket_t mpls_bucket_drop = {
6031 .type = FT_LB_SPECIAL,
6032 .special = {
6033 .adj = DPO_PROTO_MPLS,
6034 },
6035 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006036
6037 fib_table_entry_path_remove(fib_index,
6038 &pfx_1_1_1_1_s_32,
6039 FIB_SOURCE_API,
6040 FIB_PROTOCOL_IP4,
6041 &nh_10_10_11_1,
6042 tm->hw[1]->sw_if_index,
6043 ~0, // invalid fib index
6044 1,
6045 FIB_ROUTE_PATH_FLAG_NONE);
6046
6047 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6048 FIB_TEST(fib_test_validate_entry(fei,
6049 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6050 1,
6051 &adj_o_10_10_11_2),
6052 "1.1.1.1/32 LB 1 buckets via: "
6053 "adj over 10.10.11.2");
6054
6055 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6056 &pfx_24001_eos);
6057 FIB_TEST(fib_test_validate_entry(fei,
6058 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6059 1,
6060 &adj_o_10_10_11_2),
6061 "24001/eos LB 1 buckets via: "
6062 "adj over 10.10.11.2");
6063
6064 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6065 &pfx_24001_neos);
6066 FIB_TEST(fib_test_validate_entry(fei,
6067 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006068 1,
6069 &mpls_bucket_drop),
6070 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006071
6072 /*
6073 * add back the path with the valid label
6074 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006075 l99 = NULL;
6076 vec_add1(l99, 99);
6077
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006078 fib_table_entry_path_add(fib_index,
6079 &pfx_1_1_1_1_s_32,
6080 FIB_SOURCE_API,
6081 FIB_ENTRY_FLAG_NONE,
6082 FIB_PROTOCOL_IP4,
6083 &nh_10_10_10_1,
6084 tm->hw[0]->sw_if_index,
6085 ~0, // invalid fib index
6086 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006087 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006088 FIB_ROUTE_PATH_FLAG_NONE);
6089
6090 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6091 FIB_TEST(fib_test_validate_entry(fei,
6092 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6093 2,
6094 &l99_eos_o_10_10_10_1,
6095 &adj_o_10_10_11_2),
6096 "1.1.1.1/32 LB 2 buckets via: "
6097 "label 99 over 10.10.10.1, "
6098 "adj over 10.10.11.2");
6099
6100 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6101 &pfx_24001_eos);
6102 FIB_TEST(fib_test_validate_entry(fei,
6103 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6104 2,
6105 &l99_eos_o_10_10_10_1,
6106 &adj_o_10_10_11_2),
6107 "24001/eos LB 2 buckets via: "
6108 "label 99 over 10.10.10.1, "
6109 "adj over 10.10.11.2");
6110
6111 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6112 &pfx_24001_neos);
6113 FIB_TEST(fib_test_validate_entry(fei,
6114 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6115 1,
6116 &l99_neos_o_10_10_10_1),
6117 "24001/neos LB 1 buckets via: "
6118 "label 99 over 10.10.10.1");
6119
6120 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006121 * change the local label
6122 */
6123 fib_table_entry_local_label_add(fib_index,
6124 &pfx_1_1_1_1_s_32,
6125 25005);
6126
6127 fib_prefix_t pfx_25005_eos = {
6128 .fp_proto = FIB_PROTOCOL_MPLS,
6129 .fp_label = 25005,
6130 .fp_eos = MPLS_EOS,
6131 };
6132 fib_prefix_t pfx_25005_neos = {
6133 .fp_proto = FIB_PROTOCOL_MPLS,
6134 .fp_label = 25005,
6135 .fp_eos = MPLS_NON_EOS,
6136 };
6137
6138 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6139 fib_table_lookup(fib_index, &pfx_24001_eos)),
6140 "24001/eos removed after label change");
6141 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6142 fib_table_lookup(fib_index, &pfx_24001_neos)),
6143 "24001/eos removed after label change");
6144
6145 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6146 &pfx_25005_eos);
6147 FIB_TEST(fib_test_validate_entry(fei,
6148 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6149 2,
6150 &l99_eos_o_10_10_10_1,
6151 &adj_o_10_10_11_2),
6152 "25005/eos LB 2 buckets via: "
6153 "label 99 over 10.10.10.1, "
6154 "adj over 10.10.11.2");
6155
6156 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6157 &pfx_25005_neos);
6158 FIB_TEST(fib_test_validate_entry(fei,
6159 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6160 1,
6161 &l99_neos_o_10_10_10_1),
6162 "25005/neos LB 1 buckets via: "
6163 "label 99 over 10.10.10.1");
6164
6165 /*
6166 * remove the local label.
6167 * the check that the MPLS entries are gone is done by the fact the
6168 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006169 */
6170 fib_table_entry_local_label_remove(fib_index,
6171 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006172 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006173
6174 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6175 FIB_TEST(fib_test_validate_entry(fei,
6176 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6177 2,
6178 &l99_eos_o_10_10_10_1,
6179 &adj_o_10_10_11_2),
6180 "24001/eos LB 2 buckets via: "
6181 "label 99 over 10.10.10.1, "
6182 "adj over 10.10.11.2");
6183
6184 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6185 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6186 "No more MPLS FIB entries => table removed");
6187
6188 /*
6189 * add another via-entry for the recursive
6190 */
6191 fib_prefix_t pfx_1_1_1_2_s_32 = {
6192 .fp_len = 32,
6193 .fp_proto = FIB_PROTOCOL_IP4,
6194 .fp_addr = {
6195 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6196 },
6197 };
6198 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6199 .type = FT_LB_LABEL_O_ADJ,
6200 .label_o_adj = {
6201 .adj = ai_mpls_10_10_10_1,
6202 .label = 101,
6203 .eos = MPLS_EOS,
6204 },
6205 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006206 mpls_label_t *l101 = NULL;
6207 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006208
6209 fei = fib_table_entry_update_one_path(fib_index,
6210 &pfx_1_1_1_2_s_32,
6211 FIB_SOURCE_API,
6212 FIB_ENTRY_FLAG_NONE,
6213 FIB_PROTOCOL_IP4,
6214 &nh_10_10_10_1,
6215 tm->hw[0]->sw_if_index,
6216 ~0, // invalid fib index
6217 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006218 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006219 FIB_ROUTE_PATH_FLAG_NONE);
6220
6221 FIB_TEST(fib_test_validate_entry(fei,
6222 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6223 1,
6224 &l101_eos_o_10_10_10_1),
6225 "1.1.1.2/32 LB 1 buckets via: "
6226 "label 101 over 10.10.10.1");
6227
Neale Ranns948e00f2016-10-20 13:39:34 +01006228 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006229 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6230 &pfx_1_1_1_1_s_32),
6231 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6232 &non_eos_1_1_1_1);
6233 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6234 &pfx_1_1_1_2_s_32),
6235 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6236 &non_eos_1_1_1_2);
6237
6238 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6239 .type = FT_LB_LABEL_O_LB,
6240 .label_o_lb = {
6241 .lb = non_eos_1_1_1_2.dpoi_index,
6242 .label = 1601,
6243 .eos = MPLS_EOS,
6244 },
6245 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006246 mpls_label_t *l1601 = NULL;
6247 vec_add1(l1601, 1601);
6248
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006249 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6250
6251 fei = fib_table_entry_path_add(fib_index,
6252 &pfx_2_2_2_2_s_32,
6253 FIB_SOURCE_API,
6254 FIB_ENTRY_FLAG_NONE,
6255 FIB_PROTOCOL_IP4,
6256 &pfx_1_1_1_2_s_32.fp_addr,
6257 ~0,
6258 fib_index,
6259 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006260 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006261 FIB_ROUTE_PATH_FLAG_NONE);
6262
6263 FIB_TEST(fib_test_validate_entry(fei,
6264 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6265 2,
6266 &l1600_eos_o_1_1_1_1,
6267 &l1601_eos_o_1_1_1_2),
6268 "2.2.2.2/32 LB 2 buckets via: "
6269 "label 1600 via 1.1,1.1, "
6270 "label 16001 via 1.1.1.2");
6271
6272 /*
6273 * update the via-entry so it no longer has an imp-null path.
6274 * the LB for the recursive can use an imp-null
6275 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006276 l_imp_null = NULL;
6277 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6278
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006279 fei = fib_table_entry_update_one_path(fib_index,
6280 &pfx_1_1_1_2_s_32,
6281 FIB_SOURCE_API,
6282 FIB_ENTRY_FLAG_NONE,
6283 FIB_PROTOCOL_IP4,
6284 &nh_10_10_11_1,
6285 tm->hw[1]->sw_if_index,
6286 ~0, // invalid fib index
6287 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006288 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006289 FIB_ROUTE_PATH_FLAG_NONE);
6290
6291 FIB_TEST(fib_test_validate_entry(fei,
6292 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6293 1,
6294 &a_o_10_10_11_1),
6295 "1.1.1.2/32 LB 1 buckets via: "
6296 "adj 10.10.11.1");
6297
6298 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6299 FIB_TEST(fib_test_validate_entry(fei,
6300 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6301 2,
6302 &l1600_eos_o_1_1_1_1,
6303 &l1601_eos_o_1_1_1_2),
6304 "2.2.2.2/32 LB 2 buckets via: "
6305 "label 1600 via 1.1,1.1, "
6306 "label 16001 via 1.1.1.2");
6307
6308 /*
6309 * update the via-entry so it no longer has labelled paths.
6310 * the LB for the recursive should exclue this via form its LB
6311 */
6312 fei = fib_table_entry_update_one_path(fib_index,
6313 &pfx_1_1_1_2_s_32,
6314 FIB_SOURCE_API,
6315 FIB_ENTRY_FLAG_NONE,
6316 FIB_PROTOCOL_IP4,
6317 &nh_10_10_11_1,
6318 tm->hw[1]->sw_if_index,
6319 ~0, // invalid fib index
6320 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006321 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006322 FIB_ROUTE_PATH_FLAG_NONE);
6323
6324 FIB_TEST(fib_test_validate_entry(fei,
6325 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6326 1,
6327 &a_o_10_10_11_1),
6328 "1.1.1.2/32 LB 1 buckets via: "
6329 "adj 10.10.11.1");
6330
6331 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6332 FIB_TEST(fib_test_validate_entry(fei,
6333 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6334 1,
6335 &l1600_eos_o_1_1_1_1),
6336 "2.2.2.2/32 LB 1 buckets via: "
6337 "label 1600 via 1.1,1.1");
6338
6339 dpo_reset(&non_eos_1_1_1_1);
6340 dpo_reset(&non_eos_1_1_1_2);
6341
6342 /*
6343 * Add a recursive with no out-labels. We expect to use the IP of the via
6344 */
6345 fib_prefix_t pfx_2_2_2_3_s_32 = {
6346 .fp_len = 32,
6347 .fp_proto = FIB_PROTOCOL_IP4,
6348 .fp_addr = {
6349 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6350 },
6351 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006352 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006353
6354 fib_table_entry_update_one_path(fib_index,
6355 &pfx_2_2_2_3_s_32,
6356 FIB_SOURCE_API,
6357 FIB_ENTRY_FLAG_NONE,
6358 FIB_PROTOCOL_IP4,
6359 &pfx_1_1_1_1_s_32.fp_addr,
6360 ~0,
6361 fib_index,
6362 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006363 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006364 FIB_ROUTE_PATH_FLAG_NONE);
6365
6366 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6367 &pfx_1_1_1_1_s_32),
6368 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6369 &ip_1_1_1_1);
6370
6371 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6372 .type = FT_LB_O_LB,
6373 .lb = {
6374 .lb = ip_1_1_1_1.dpoi_index,
6375 },
6376 };
6377
6378 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6379 FIB_TEST(fib_test_validate_entry(fei,
6380 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6381 1,
6382 &ip_o_1_1_1_1),
6383 "2.2.2.2.3/32 LB 1 buckets via: "
6384 "ip 1.1.1.1");
6385
6386 /*
6387 * Add a recursive with an imp-null out-label.
6388 * We expect to use the IP of the via
6389 */
6390 fib_prefix_t pfx_2_2_2_4_s_32 = {
6391 .fp_len = 32,
6392 .fp_proto = FIB_PROTOCOL_IP4,
6393 .fp_addr = {
6394 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6395 },
6396 };
6397
6398 fib_table_entry_update_one_path(fib_index,
6399 &pfx_2_2_2_4_s_32,
6400 FIB_SOURCE_API,
6401 FIB_ENTRY_FLAG_NONE,
6402 FIB_PROTOCOL_IP4,
6403 &pfx_1_1_1_1_s_32.fp_addr,
6404 ~0,
6405 fib_index,
6406 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006407 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006408 FIB_ROUTE_PATH_FLAG_NONE);
6409
6410 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6411 FIB_TEST(fib_test_validate_entry(fei,
6412 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6413 1,
6414 &ip_o_1_1_1_1),
6415 "2.2.2.2.4/32 LB 1 buckets via: "
6416 "ip 1.1.1.1");
6417
6418 dpo_reset(&ip_1_1_1_1);
6419
6420 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006421 * Create an entry with a deep label stack
6422 */
6423 fib_prefix_t pfx_2_2_5_5_s_32 = {
6424 .fp_len = 32,
6425 .fp_proto = FIB_PROTOCOL_IP4,
6426 .fp_addr = {
6427 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6428 },
6429 };
6430 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6431 .type = FT_LB_LABEL_STACK_O_ADJ,
6432 .label_stack_o_adj = {
6433 .adj = ai_mpls_10_10_11_1,
6434 .label_stack_size = 8,
6435 .label_stack = {
6436 200, 201, 202, 203, 204, 205, 206, 207
6437 },
6438 .eos = MPLS_EOS,
6439 },
6440 };
6441 mpls_label_t *label_stack = NULL;
6442 vec_validate(label_stack, 7);
6443 for (ii = 0; ii < 8; ii++)
6444 {
6445 label_stack[ii] = ii + 200;
6446 }
6447
6448 fei = fib_table_entry_update_one_path(fib_index,
6449 &pfx_2_2_5_5_s_32,
6450 FIB_SOURCE_API,
6451 FIB_ENTRY_FLAG_NONE,
6452 FIB_PROTOCOL_IP4,
6453 &nh_10_10_11_1,
6454 tm->hw[1]->sw_if_index,
6455 ~0, // invalid fib index
6456 1,
6457 label_stack,
6458 FIB_ROUTE_PATH_FLAG_NONE);
6459
6460 FIB_TEST(fib_test_validate_entry(fei,
6461 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6462 1,
6463 &ls_eos_o_10_10_10_1),
6464 "2.2.5.5/32 LB 1 buckets via: "
6465 "adj 10.10.11.1");
6466 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6467
6468 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006469 * cleanup
6470 */
6471 fib_table_entry_delete(fib_index,
6472 &pfx_1_1_1_2_s_32,
6473 FIB_SOURCE_API);
6474
6475 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6476 FIB_TEST(fib_test_validate_entry(fei,
6477 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6478 1,
6479 &l1600_eos_o_1_1_1_1),
6480 "2.2.2.2/32 LB 1 buckets via: "
6481 "label 1600 via 1.1,1.1");
6482
6483 fib_table_entry_delete(fib_index,
6484 &pfx_1_1_1_1_s_32,
6485 FIB_SOURCE_API);
6486
6487 FIB_TEST(fib_test_validate_entry(fei,
6488 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6489 1,
6490 &bucket_drop),
6491 "2.2.2.2/32 LB 1 buckets via: DROP");
6492
6493 fib_table_entry_delete(fib_index,
6494 &pfx_2_2_2_2_s_32,
6495 FIB_SOURCE_API);
6496 fib_table_entry_delete(fib_index,
6497 &pfx_2_2_2_3_s_32,
6498 FIB_SOURCE_API);
6499 fib_table_entry_delete(fib_index,
6500 &pfx_2_2_2_4_s_32,
6501 FIB_SOURCE_API);
6502
6503 adj_unlock(ai_mpls_10_10_10_1);
6504 adj_unlock(ai_mpls_10_10_11_2);
6505 adj_unlock(ai_v4_10_10_11_1);
6506 adj_unlock(ai_v4_10_10_11_2);
6507 adj_unlock(ai_mpls_10_10_11_1);
6508
6509 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6510 adj_nbr_db_size());
6511
6512 local0_pfx.fp_len = 32;
6513 fib_table_entry_delete(fib_index,
6514 &local0_pfx,
6515 FIB_SOURCE_INTERFACE);
6516 local0_pfx.fp_len = 24;
6517 fib_table_entry_delete(fib_index,
6518 &local0_pfx,
6519 FIB_SOURCE_INTERFACE);
6520 local1_pfx.fp_len = 32;
6521 fib_table_entry_delete(fib_index,
6522 &local1_pfx,
6523 FIB_SOURCE_INTERFACE);
6524 local1_pfx.fp_len = 24;
6525 fib_table_entry_delete(fib_index,
6526 &local1_pfx,
6527 FIB_SOURCE_INTERFACE);
6528
6529 /*
6530 * +1 for the drop LB in the MPLS tables.
6531 */
6532 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6533 "Load-balance resources freed %d of %d",
6534 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006535
6536 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006537}
6538
6539#define N_TEST_CHILDREN 4
6540#define PARENT_INDEX 0
6541
6542typedef struct fib_node_test_t_
6543{
6544 fib_node_t node;
6545 u32 sibling;
6546 u32 index;
6547 fib_node_back_walk_ctx_t *ctxs;
6548 u32 destroyed;
6549} fib_node_test_t;
6550
6551static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6552
6553#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6554
6555#define FOR_EACH_TEST_CHILD(_tc) \
6556 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6557 ii < N_TEST_CHILDREN+1; \
6558 ii++, (_tc) = &fib_test_nodes[ii])
6559
6560static fib_node_t *
6561fib_test_child_get_node (fib_node_index_t index)
6562{
6563 return (&fib_test_nodes[index].node);
6564}
6565
6566static int fib_test_walk_spawns_walks;
6567
6568static fib_node_back_walk_rc_t
6569fib_test_child_back_walk_notify (fib_node_t *node,
6570 fib_node_back_walk_ctx_t *ctx)
6571{
6572 fib_node_test_t *tc = (fib_node_test_t*) node;
6573
6574 vec_add1(tc->ctxs, *ctx);
6575
6576 if (1 == fib_test_walk_spawns_walks)
6577 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6578 if (2 == fib_test_walk_spawns_walks)
6579 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6580 FIB_WALK_PRIORITY_HIGH, ctx);
6581
6582 return (FIB_NODE_BACK_WALK_CONTINUE);
6583}
6584
6585static void
6586fib_test_child_last_lock_gone (fib_node_t *node)
6587{
6588 fib_node_test_t *tc = (fib_node_test_t *)node;
6589
6590 tc->destroyed = 1;
6591}
6592
6593/**
6594 * The FIB walk's graph node virtual function table
6595 */
6596static const fib_node_vft_t fib_test_child_vft = {
6597 .fnv_get = fib_test_child_get_node,
6598 .fnv_last_lock = fib_test_child_last_lock_gone,
6599 .fnv_back_walk = fib_test_child_back_walk_notify,
6600};
6601
6602/*
6603 * the function (that should have been static but isn't so I can do this)
6604 * that processes the walk from the async queue,
6605 */
6606f64 fib_walk_process_queues(vlib_main_t * vm,
6607 const f64 quota);
6608u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6609
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006610static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006611fib_test_walk (void)
6612{
6613 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6614 fib_node_test_t *tc;
6615 vlib_main_t *vm;
6616 u32 ii;
6617
6618 vm = vlib_get_main();
6619 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6620
6621 /*
6622 * init a fake node on which we will add children
6623 */
6624 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6625 FIB_NODE_TYPE_TEST);
6626
6627 FOR_EACH_TEST_CHILD(tc)
6628 {
6629 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6630 fib_node_lock(&tc->node);
6631 tc->ctxs = NULL;
6632 tc->index = ii;
6633 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6634 PARENT_INDEX,
6635 FIB_NODE_TYPE_TEST, ii);
6636 }
6637
6638 /*
6639 * enqueue a walk across the parents children.
6640 */
Neale Ranns450cd302016-11-09 17:49:42 +00006641 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006642
6643 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6644 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6645 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6646 "Parent has %d children pre-walk",
6647 fib_node_list_get_size(PARENT()->fn_children));
6648
6649 /*
6650 * give the walk a large amount of time so it gets to the end
6651 */
6652 fib_walk_process_queues(vm, 1);
6653
6654 FOR_EACH_TEST_CHILD(tc)
6655 {
6656 FIB_TEST(1 == vec_len(tc->ctxs),
6657 "%d child visitsed %d times",
6658 ii, vec_len(tc->ctxs));
6659 vec_free(tc->ctxs);
6660 }
6661 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6662 "Queue is empty post walk");
6663 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6664 "Parent has %d children post walk",
6665 fib_node_list_get_size(PARENT()->fn_children));
6666
6667 /*
6668 * walk again. should be no increase in the number of visits, since
6669 * the walk will have terminated.
6670 */
6671 fib_walk_process_queues(vm, 1);
6672
6673 FOR_EACH_TEST_CHILD(tc)
6674 {
6675 FIB_TEST(0 == vec_len(tc->ctxs),
6676 "%d child visitsed %d times",
6677 ii, vec_len(tc->ctxs));
6678 }
6679
6680 /*
6681 * schedule a low and hig priority walk. expect the high to be performed
6682 * before the low.
6683 * schedule the high prio walk first so that it is further from the head
6684 * of the dependency list. that way it won't merge with the low one.
6685 */
6686 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6687 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6688
6689 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6690 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6691 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6692 FIB_WALK_PRIORITY_LOW, &low_ctx);
6693
6694 fib_walk_process_queues(vm, 1);
6695
6696 FOR_EACH_TEST_CHILD(tc)
6697 {
6698 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6699 "%d child visitsed by high prio walk", ii);
6700 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6701 "%d child visitsed by low prio walk", ii);
6702 vec_free(tc->ctxs);
6703 }
6704 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6705 "Queue is empty post prio walk");
6706 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6707 "Parent has %d children post prio walk",
6708 fib_node_list_get_size(PARENT()->fn_children));
6709
6710 /*
6711 * schedule 2 walks of the same priority that can be megred.
6712 * expect that each child is thus visited only once.
6713 */
6714 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6715 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6716
6717 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6718 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6719 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6720 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6721
6722 fib_walk_process_queues(vm, 1);
6723
6724 FOR_EACH_TEST_CHILD(tc)
6725 {
6726 FIB_TEST(1 == vec_len(tc->ctxs),
6727 "%d child visitsed %d times during merge walk",
6728 ii, vec_len(tc->ctxs));
6729 vec_free(tc->ctxs);
6730 }
6731 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6732 "Queue is empty post merge walk");
6733 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6734 "Parent has %d children post merge walk",
6735 fib_node_list_get_size(PARENT()->fn_children));
6736
6737 /*
6738 * schedule 2 walks of the same priority that cannot be megred.
6739 * expect that each child is thus visited twice and in the order
6740 * in which the walks were scheduled.
6741 */
6742 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6743 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6744
6745 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6746 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6747 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6748 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6749
6750 fib_walk_process_queues(vm, 1);
6751
6752 FOR_EACH_TEST_CHILD(tc)
6753 {
6754 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6755 "%d child visitsed by high prio walk", ii);
6756 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6757 "%d child visitsed by low prio walk", ii);
6758 vec_free(tc->ctxs);
6759 }
6760 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6761 "Queue is empty post no-merge walk");
6762 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6763 "Parent has %d children post no-merge walk",
6764 fib_node_list_get_size(PARENT()->fn_children));
6765
6766 /*
6767 * schedule a walk that makes one one child progress.
6768 * we do this by giving the queue draining process zero
6769 * time quanta. it's a do..while loop, so it does something.
6770 */
Neale Ranns450cd302016-11-09 17:49:42 +00006771 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006772
6773 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6774 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6775 fib_walk_process_queues(vm, 0);
6776
6777 FOR_EACH_TEST_CHILD(tc)
6778 {
6779 if (ii == N_TEST_CHILDREN)
6780 {
6781 FIB_TEST(1 == vec_len(tc->ctxs),
6782 "%d child visitsed %d times in zero quanta walk",
6783 ii, vec_len(tc->ctxs));
6784 }
6785 else
6786 {
6787 FIB_TEST(0 == vec_len(tc->ctxs),
6788 "%d child visitsed %d times in 0 quanta walk",
6789 ii, vec_len(tc->ctxs));
6790 }
6791 }
6792 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6793 "Queue is not empty post zero quanta walk");
6794 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6795 "Parent has %d children post zero qunta walk",
6796 fib_node_list_get_size(PARENT()->fn_children));
6797
6798 /*
6799 * another one step
6800 */
6801 fib_walk_process_queues(vm, 0);
6802
6803 FOR_EACH_TEST_CHILD(tc)
6804 {
6805 if (ii >= N_TEST_CHILDREN-1)
6806 {
6807 FIB_TEST(1 == vec_len(tc->ctxs),
6808 "%d child visitsed %d times in 2nd zero quanta walk",
6809 ii, vec_len(tc->ctxs));
6810 }
6811 else
6812 {
6813 FIB_TEST(0 == vec_len(tc->ctxs),
6814 "%d child visitsed %d times in 2nd 0 quanta walk",
6815 ii, vec_len(tc->ctxs));
6816 }
6817 }
6818 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6819 "Queue is not empty post zero quanta walk");
6820 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6821 "Parent has %d children post zero qunta walk",
6822 fib_node_list_get_size(PARENT()->fn_children));
6823
6824 /*
6825 * schedule another walk that will catch-up and merge.
6826 */
6827 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6828 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6829 fib_walk_process_queues(vm, 1);
6830
6831 FOR_EACH_TEST_CHILD(tc)
6832 {
6833 if (ii >= N_TEST_CHILDREN-1)
6834 {
6835 FIB_TEST(2 == vec_len(tc->ctxs),
6836 "%d child visitsed %d times in 2nd zero quanta merge walk",
6837 ii, vec_len(tc->ctxs));
6838 vec_free(tc->ctxs);
6839 }
6840 else
6841 {
6842 FIB_TEST(1 == vec_len(tc->ctxs),
6843 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6844 ii, vec_len(tc->ctxs));
6845 vec_free(tc->ctxs);
6846 }
6847 }
6848 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6849 "Queue is not empty post 2nd zero quanta merge walk");
6850 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6851 "Parent has %d children post 2nd zero qunta merge walk",
6852 fib_node_list_get_size(PARENT()->fn_children));
6853
6854 /*
6855 * park a async walk in the middle of the list, then have an sync walk catch
6856 * it. same expectations as async catches async.
6857 */
Neale Ranns450cd302016-11-09 17:49:42 +00006858 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006859
6860 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6861 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6862
6863 fib_walk_process_queues(vm, 0);
6864 fib_walk_process_queues(vm, 0);
6865
6866 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6867
6868 FOR_EACH_TEST_CHILD(tc)
6869 {
6870 if (ii >= N_TEST_CHILDREN-1)
6871 {
6872 FIB_TEST(2 == vec_len(tc->ctxs),
6873 "%d child visitsed %d times in sync catches async walk",
6874 ii, vec_len(tc->ctxs));
6875 vec_free(tc->ctxs);
6876 }
6877 else
6878 {
6879 FIB_TEST(1 == vec_len(tc->ctxs),
6880 "%d child visitsed %d times in sync catches async walk",
6881 ii, vec_len(tc->ctxs));
6882 vec_free(tc->ctxs);
6883 }
6884 }
6885 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6886 "Queue is not empty post 2nd zero quanta merge walk");
6887 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6888 "Parent has %d children post 2nd zero qunta merge walk",
6889 fib_node_list_get_size(PARENT()->fn_children));
6890
6891 /*
6892 * make the parent a child of one of its children, thus inducing a routing loop.
6893 */
6894 fib_test_nodes[PARENT_INDEX].sibling =
6895 fib_node_child_add(FIB_NODE_TYPE_TEST,
6896 1, // the first child
6897 FIB_NODE_TYPE_TEST,
6898 PARENT_INDEX);
6899
6900 /*
6901 * execute a sync walk from the parent. each child visited spawns more sync
6902 * walks. we expect the walk to terminate.
6903 */
6904 fib_test_walk_spawns_walks = 1;
6905
6906 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6907
6908 FOR_EACH_TEST_CHILD(tc)
6909 {
6910 /*
6911 * child 1 - which is last in the list - has the loop.
6912 * the other children a re thus visitsed first. the we meet
6913 * child 1. we go round the loop again, visting the other children.
6914 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6915 * again.
6916 */
6917 if (1 == ii)
6918 {
6919 FIB_TEST(1 == vec_len(tc->ctxs),
6920 "child %d visitsed %d times during looped sync walk",
6921 ii, vec_len(tc->ctxs));
6922 }
6923 else
6924 {
6925 FIB_TEST(2 == vec_len(tc->ctxs),
6926 "child %d visitsed %d times during looped sync walk",
6927 ii, vec_len(tc->ctxs));
6928 }
6929 vec_free(tc->ctxs);
6930 }
6931 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6932 "Parent has %d children post sync loop walk",
6933 fib_node_list_get_size(PARENT()->fn_children));
6934
6935 /*
6936 * the walk doesn't reach the max depth because the infra knows that sync
6937 * meets sync implies a loop and bails early.
6938 */
6939 FIB_TEST(high_ctx.fnbw_depth == 9,
6940 "Walk context depth %d post sync loop walk",
6941 high_ctx.fnbw_depth);
6942
6943 /*
6944 * execute an async walk of the graph loop, with each child spawns sync walks
6945 */
6946 high_ctx.fnbw_depth = 0;
6947 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6948 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6949
6950 fib_walk_process_queues(vm, 1);
6951
6952 FOR_EACH_TEST_CHILD(tc)
6953 {
6954 /*
6955 * we don't really care how many times the children are visisted, as long as
6956 * it is more than once.
6957 */
6958 FIB_TEST(1 <= vec_len(tc->ctxs),
6959 "child %d visitsed %d times during looped aync spawns sync walk",
6960 ii, vec_len(tc->ctxs));
6961 vec_free(tc->ctxs);
6962 }
6963
6964 /*
6965 * execute an async walk of the graph loop, with each child spawns async walks
6966 */
6967 fib_test_walk_spawns_walks = 2;
6968 high_ctx.fnbw_depth = 0;
6969 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6970 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6971
6972 fib_walk_process_queues(vm, 1);
6973
6974 FOR_EACH_TEST_CHILD(tc)
6975 {
6976 /*
6977 * we don't really care how many times the children are visisted, as long as
6978 * it is more than once.
6979 */
6980 FIB_TEST(1 <= vec_len(tc->ctxs),
6981 "child %d visitsed %d times during looped async spawns async walk",
6982 ii, vec_len(tc->ctxs));
6983 vec_free(tc->ctxs);
6984 }
6985
6986
6987 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6988 1, // the first child
6989 fib_test_nodes[PARENT_INDEX].sibling);
6990
6991 /*
6992 * cleanup
6993 */
6994 FOR_EACH_TEST_CHILD(tc)
6995 {
6996 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6997 tc->sibling);
6998 fib_node_deinit(&tc->node);
6999 fib_node_unlock(&tc->node);
7000 }
7001 fib_node_deinit(PARENT());
7002
7003 /*
7004 * The parent will be destroyed when the last lock on it goes.
7005 * this test ensures all the walk objects are unlocking it.
7006 */
7007 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7008 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007009
7010 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007011}
7012
Neale Ranns88fc83e2017-04-05 08:11:14 -07007013/*
7014 * declaration of the otherwise static callback functions
7015 */
7016void fib_bfd_notify (bfd_listen_event_e event,
7017 const bfd_session_t *session);
7018void adj_bfd_notify (bfd_listen_event_e event,
7019 const bfd_session_t *session);
7020
7021/**
7022 * Test BFD session interaction with FIB
7023 */
7024static int
7025fib_test_bfd (void)
7026{
7027 fib_node_index_t fei;
7028 test_main_t *tm;
7029 int n_feis;
7030
7031 /* via 10.10.10.1 */
7032 ip46_address_t nh_10_10_10_1 = {
7033 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7034 };
7035 /* via 10.10.10.2 */
7036 ip46_address_t nh_10_10_10_2 = {
7037 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7038 };
7039 /* via 10.10.10.10 */
7040 ip46_address_t nh_10_10_10_10 = {
7041 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7042 };
7043 n_feis = fib_entry_pool_size();
7044
7045 tm = &test_main;
7046
7047 /*
7048 * add interface routes. we'll assume this works. it's tested elsewhere
7049 */
7050 fib_prefix_t pfx_10_10_10_10_s_24 = {
7051 .fp_len = 24,
7052 .fp_proto = FIB_PROTOCOL_IP4,
7053 .fp_addr = nh_10_10_10_10,
7054 };
7055
7056 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7057 FIB_SOURCE_INTERFACE,
7058 (FIB_ENTRY_FLAG_CONNECTED |
7059 FIB_ENTRY_FLAG_ATTACHED),
7060 FIB_PROTOCOL_IP4,
7061 NULL,
7062 tm->hw[0]->sw_if_index,
7063 ~0, // invalid fib index
7064 1, // weight
7065 NULL,
7066 FIB_ROUTE_PATH_FLAG_NONE);
7067
7068 fib_prefix_t pfx_10_10_10_10_s_32 = {
7069 .fp_len = 32,
7070 .fp_proto = FIB_PROTOCOL_IP4,
7071 .fp_addr = nh_10_10_10_10,
7072 };
7073 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7074 FIB_SOURCE_INTERFACE,
7075 (FIB_ENTRY_FLAG_CONNECTED |
7076 FIB_ENTRY_FLAG_LOCAL),
7077 FIB_PROTOCOL_IP4,
7078 NULL,
7079 tm->hw[0]->sw_if_index,
7080 ~0, // invalid fib index
7081 1, // weight
7082 NULL,
7083 FIB_ROUTE_PATH_FLAG_NONE);
7084
7085 /*
7086 * A BFD session via a neighbour we do not yet know
7087 */
7088 bfd_session_t bfd_10_10_10_1 = {
7089 .udp = {
7090 .key = {
7091 .fib_index = 0,
7092 .peer_addr = nh_10_10_10_1,
7093 },
7094 },
7095 .hop_type = BFD_HOP_TYPE_MULTI,
7096 .local_state = BFD_STATE_init,
7097 };
7098
7099 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7100
7101 /*
7102 * A new entry will be created that forwards via the adj
7103 */
7104 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7105 VNET_LINK_IP4,
7106 &nh_10_10_10_1,
7107 tm->hw[0]->sw_if_index);
7108 fib_prefix_t pfx_10_10_10_1_s_32 = {
7109 .fp_addr = nh_10_10_10_1,
7110 .fp_len = 32,
7111 .fp_proto = FIB_PROTOCOL_IP4,
7112 };
7113 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7114 .type = FT_LB_ADJ,
7115 .adj = {
7116 .adj = ai_10_10_10_1,
7117 },
7118 };
7119
7120 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7121 FIB_TEST(fib_test_validate_entry(fei,
7122 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7123 1,
7124 &adj_o_10_10_10_1),
7125 "BFD sourced %U via %U",
7126 format_fib_prefix, &pfx_10_10_10_1_s_32,
7127 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7128
7129 /*
7130 * Delete the BFD session. Expect the fib_entry to be removed
7131 */
7132 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7133
7134 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7135 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7136 "BFD sourced %U removed",
7137 format_fib_prefix, &pfx_10_10_10_1_s_32);
7138
7139 /*
7140 * Add the BFD source back
7141 */
7142 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7143
7144 /*
7145 * source the entry via the ADJ fib
7146 */
7147 fei = fib_table_entry_update_one_path(0,
7148 &pfx_10_10_10_1_s_32,
7149 FIB_SOURCE_ADJ,
7150 FIB_ENTRY_FLAG_ATTACHED,
7151 FIB_PROTOCOL_IP4,
7152 &nh_10_10_10_1,
7153 tm->hw[0]->sw_if_index,
7154 ~0, // invalid fib index
7155 1,
7156 NULL,
7157 FIB_ROUTE_PATH_FLAG_NONE);
7158
7159 /*
7160 * Delete the BFD session. Expect the fib_entry to remain
7161 */
7162 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7163
7164 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7165 FIB_TEST(fib_test_validate_entry(fei,
7166 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7167 1,
7168 &adj_o_10_10_10_1),
7169 "BFD sourced %U remains via %U",
7170 format_fib_prefix, &pfx_10_10_10_1_s_32,
7171 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7172
7173 /*
7174 * Add the BFD source back
7175 */
7176 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7177
7178 /*
7179 * Create another ADJ FIB
7180 */
7181 fib_prefix_t pfx_10_10_10_2_s_32 = {
7182 .fp_addr = nh_10_10_10_2,
7183 .fp_len = 32,
7184 .fp_proto = FIB_PROTOCOL_IP4,
7185 };
7186 fib_table_entry_update_one_path(0,
7187 &pfx_10_10_10_2_s_32,
7188 FIB_SOURCE_ADJ,
7189 FIB_ENTRY_FLAG_ATTACHED,
7190 FIB_PROTOCOL_IP4,
7191 &nh_10_10_10_2,
7192 tm->hw[0]->sw_if_index,
7193 ~0, // invalid fib index
7194 1,
7195 NULL,
7196 FIB_ROUTE_PATH_FLAG_NONE);
7197 /*
7198 * A BFD session for the new ADJ FIB
7199 */
7200 bfd_session_t bfd_10_10_10_2 = {
7201 .udp = {
7202 .key = {
7203 .fib_index = 0,
7204 .peer_addr = nh_10_10_10_2,
7205 },
7206 },
7207 .hop_type = BFD_HOP_TYPE_MULTI,
7208 .local_state = BFD_STATE_init,
7209 };
7210
7211 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7212
7213 /*
7214 * remove the adj-fib source whilst the session is present
7215 * then add it back
7216 */
7217 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7218 fib_table_entry_update_one_path(0,
7219 &pfx_10_10_10_2_s_32,
7220 FIB_SOURCE_ADJ,
7221 FIB_ENTRY_FLAG_ATTACHED,
7222 FIB_PROTOCOL_IP4,
7223 &nh_10_10_10_2,
7224 tm->hw[0]->sw_if_index,
7225 ~0, // invalid fib index
7226 1,
7227 NULL,
7228 FIB_ROUTE_PATH_FLAG_NONE);
7229
7230 /*
7231 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7232 * bring one of the sessions UP, leave the other down
7233 */
7234 bfd_10_10_10_1.local_state = BFD_STATE_up;
7235 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7236 bfd_10_10_10_2.local_state = BFD_STATE_down;
7237 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7238
7239 /*
7240 * A recursive prefix via both of the ADJ FIBs
7241 */
7242 fib_prefix_t pfx_200_0_0_0_s_24 = {
7243 .fp_proto = FIB_PROTOCOL_IP4,
7244 .fp_len = 32,
7245 .fp_addr = {
7246 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7247 },
7248 };
7249 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7250
7251 dpo_10_10_10_1 =
7252 fib_entry_contribute_ip_forwarding(
7253 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7254 dpo_10_10_10_2 =
7255 fib_entry_contribute_ip_forwarding(
7256 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7257
7258 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7259 .type = FT_LB_O_LB,
7260 .lb = {
7261 .lb = dpo_10_10_10_1->dpoi_index,
7262 },
7263 };
7264 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7265 .type = FT_LB_O_LB,
7266 .lb = {
7267 .lb = dpo_10_10_10_2->dpoi_index,
7268 },
7269 };
7270
7271 /*
7272 * A prefix via the adj-fib that is BFD down => DROP
7273 */
7274 fei = fib_table_entry_path_add(0,
7275 &pfx_200_0_0_0_s_24,
7276 FIB_SOURCE_API,
7277 FIB_ENTRY_FLAG_NONE,
7278 FIB_PROTOCOL_IP4,
7279 &nh_10_10_10_2,
7280 ~0, // recursive
7281 0, // default fib index
7282 1,
7283 NULL,
7284 FIB_ROUTE_PATH_FLAG_NONE);
7285 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7286 "%U resolves via drop",
7287 format_fib_prefix, &pfx_200_0_0_0_s_24);
7288
7289 /*
7290 * add a path via the UP BFD adj-fib.
7291 * we expect that the DOWN BFD ADJ FIB is not used.
7292 */
7293 fei = fib_table_entry_path_add(0,
7294 &pfx_200_0_0_0_s_24,
7295 FIB_SOURCE_API,
7296 FIB_ENTRY_FLAG_NONE,
7297 FIB_PROTOCOL_IP4,
7298 &nh_10_10_10_1,
7299 ~0, // recursive
7300 0, // default fib index
7301 1,
7302 NULL,
7303 FIB_ROUTE_PATH_FLAG_NONE);
7304
7305 FIB_TEST(fib_test_validate_entry(fei,
7306 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7307 1,
7308 &lb_o_10_10_10_1),
7309 "Recursive %U only UP BFD adj-fibs",
7310 format_fib_prefix, &pfx_200_0_0_0_s_24);
7311
7312 /*
7313 * Send a BFD state change to UP - both sessions are now up
7314 * the recursive prefix should LB over both
7315 */
7316 bfd_10_10_10_2.local_state = BFD_STATE_up;
7317 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7318
7319
7320 FIB_TEST(fib_test_validate_entry(fei,
7321 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7322 2,
7323 &lb_o_10_10_10_1,
7324 &lb_o_10_10_10_2),
7325 "Recursive %U via both UP BFD adj-fibs",
7326 format_fib_prefix, &pfx_200_0_0_0_s_24);
7327
7328 /*
7329 * Send a BFD state change to DOWN
7330 * the recursive prefix should exclude the down
7331 */
7332 bfd_10_10_10_2.local_state = BFD_STATE_down;
7333 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7334
7335
7336 FIB_TEST(fib_test_validate_entry(fei,
7337 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7338 1,
7339 &lb_o_10_10_10_1),
7340 "Recursive %U via only UP",
7341 format_fib_prefix, &pfx_200_0_0_0_s_24);
7342
7343 /*
7344 * Delete the BFD session while it is in the DOWN state.
7345 * FIB should consider the entry's state as back up
7346 */
7347 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
7348
7349 FIB_TEST(fib_test_validate_entry(fei,
7350 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7351 2,
7352 &lb_o_10_10_10_1,
7353 &lb_o_10_10_10_2),
7354 "Recursive %U via both UP BFD adj-fibs post down session delete",
7355 format_fib_prefix, &pfx_200_0_0_0_s_24);
7356
7357 /*
7358 * Delete the BFD other session while it is in the UP state.
7359 */
7360 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7361
7362 FIB_TEST(fib_test_validate_entry(fei,
7363 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7364 2,
7365 &lb_o_10_10_10_1,
7366 &lb_o_10_10_10_2),
7367 "Recursive %U via both UP BFD adj-fibs post up session delete",
7368 format_fib_prefix, &pfx_200_0_0_0_s_24);
7369
7370 /*
7371 * cleaup
7372 */
7373 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
7374 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
7375 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7376
7377 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
7378 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
7379
7380 adj_unlock(ai_10_10_10_1);
7381 /*
7382 * test no-one left behind
7383 */
7384 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7385 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7386
7387 /*
7388 * Single-hop BFD tests
7389 */
7390 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
7391 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
7392
7393 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7394
7395 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7396 VNET_LINK_IP4,
7397 &nh_10_10_10_1,
7398 tm->hw[0]->sw_if_index);
7399 /*
7400 * whilst the BFD session is not signalled, the adj is up
7401 */
7402 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
7403
7404 /*
7405 * bring the BFD session up
7406 */
7407 bfd_10_10_10_1.local_state = BFD_STATE_up;
7408 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7409 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
7410
7411 /*
7412 * bring the BFD session down
7413 */
7414 bfd_10_10_10_1.local_state = BFD_STATE_down;
7415 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7416 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
7417
7418
7419 /*
7420 * add an attached next hop FIB entry via the down adj
7421 */
7422 fib_prefix_t pfx_5_5_5_5_s_32 = {
7423 .fp_addr = {
7424 .ip4 = {
7425 .as_u32 = clib_host_to_net_u32(0x05050505),
7426 },
7427 },
7428 .fp_len = 32,
7429 .fp_proto = FIB_PROTOCOL_IP4,
7430 };
7431
7432 fei = fib_table_entry_path_add(0,
7433 &pfx_5_5_5_5_s_32,
7434 FIB_SOURCE_CLI,
7435 FIB_ENTRY_FLAG_NONE,
7436 FIB_PROTOCOL_IP4,
7437 &nh_10_10_10_1,
7438 tm->hw[0]->sw_if_index,
7439 ~0, // invalid fib index
7440 1,
7441 NULL,
7442 FIB_ROUTE_PATH_FLAG_NONE);
7443 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7444 "%U resolves via drop",
7445 format_fib_prefix, &pfx_5_5_5_5_s_32);
7446
7447 /*
7448 * Add a path via an ADJ that is up
7449 */
7450 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7451 VNET_LINK_IP4,
7452 &nh_10_10_10_2,
7453 tm->hw[0]->sw_if_index);
7454
7455 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
7456 .type = FT_LB_ADJ,
7457 .adj = {
7458 .adj = ai_10_10_10_2,
7459 },
7460 };
7461 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
7462
7463 fei = fib_table_entry_path_add(0,
7464 &pfx_5_5_5_5_s_32,
7465 FIB_SOURCE_CLI,
7466 FIB_ENTRY_FLAG_NONE,
7467 FIB_PROTOCOL_IP4,
7468 &nh_10_10_10_2,
7469 tm->hw[0]->sw_if_index,
7470 ~0, // invalid fib index
7471 1,
7472 NULL,
7473 FIB_ROUTE_PATH_FLAG_NONE);
7474
7475 FIB_TEST(fib_test_validate_entry(fei,
7476 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7477 1,
7478 &adj_o_10_10_10_2),
7479 "BFD sourced %U via %U",
7480 format_fib_prefix, &pfx_5_5_5_5_s_32,
7481 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
7482
7483 /*
7484 * Bring up the down session - should now LB
7485 */
7486 bfd_10_10_10_1.local_state = BFD_STATE_up;
7487 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7488 FIB_TEST(fib_test_validate_entry(fei,
7489 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7490 2,
7491 &adj_o_10_10_10_1,
7492 &adj_o_10_10_10_2),
7493 "BFD sourced %U via noth adjs",
7494 format_fib_prefix, &pfx_5_5_5_5_s_32);
7495
7496 /*
7497 * remove the BFD session state from the adj
7498 */
7499 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7500
7501 /*
7502 * clean-up
7503 */
7504 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
7505 adj_unlock(ai_10_10_10_1);
7506 adj_unlock(ai_10_10_10_2);
7507
7508 /*
7509 * test no-one left behind
7510 */
7511 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7512 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7513 return (0);
7514}
7515
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007516static int
7517lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007518{
7519 const mpls_label_t deag_label = 50;
7520 const u32 lfib_index = 0;
7521 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01007522 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007523 const dpo_id_t *dpo1;
7524 fib_node_index_t lfe;
7525 lookup_dpo_t *lkd;
7526 test_main_t *tm;
7527 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00007528 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007529
7530 tm = &test_main;
7531 lb_count = pool_elts(load_balance_pool);
7532
7533 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7534 adj_nbr_db_size());
7535
7536 /*
7537 * MPLS enable an interface so we get the MPLS table created
7538 */
7539 mpls_sw_interface_enable_disable(&mpls_main,
7540 tm->hw[0]->sw_if_index,
7541 1);
7542
Neale Rannsad422ed2016-11-02 14:20:04 +00007543 ip46_address_t nh_10_10_10_1 = {
7544 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7545 };
7546 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7547 VNET_LINK_MPLS,
7548 &nh_10_10_10_1,
7549 tm->hw[0]->sw_if_index);
7550
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007551 /*
7552 * Test the specials stack properly.
7553 */
7554 fib_prefix_t exp_null_v6_pfx = {
7555 .fp_proto = FIB_PROTOCOL_MPLS,
7556 .fp_eos = MPLS_EOS,
7557 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7558 .fp_payload_proto = DPO_PROTO_IP6,
7559 };
7560 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
7561 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
7562 "%U/%U present",
7563 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7564 format_mpls_eos_bit, MPLS_EOS);
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((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
7582 "%U/%U is lookup in interface's table",
7583 format_mpls_unicast_label, deag_label,
7584 format_mpls_eos_bit, MPLS_EOS);
7585 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
7586 "%U/%U is %U dst deag",
7587 format_mpls_unicast_label, deag_label,
7588 format_mpls_eos_bit, MPLS_EOS,
7589 format_dpo_proto, lkd->lkd_proto);
7590
7591
7592 /*
7593 * A route deag route for EOS
7594 */
7595 fib_prefix_t pfx = {
7596 .fp_proto = FIB_PROTOCOL_MPLS,
7597 .fp_eos = MPLS_EOS,
7598 .fp_label = deag_label,
7599 .fp_payload_proto = DPO_PROTO_IP4,
7600 };
7601 lfe = fib_table_entry_path_add(lfib_index,
7602 &pfx,
7603 FIB_SOURCE_CLI,
7604 FIB_ENTRY_FLAG_NONE,
7605 FIB_PROTOCOL_IP4,
7606 &zero_addr,
7607 ~0,
7608 fib_index,
7609 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007610 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007611 FIB_ROUTE_PATH_FLAG_NONE);
7612
7613 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7614 "%U/%U present",
7615 format_mpls_unicast_label, deag_label,
7616 format_mpls_eos_bit, MPLS_EOS);
7617
7618 fib_entry_contribute_forwarding(lfe,
7619 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7620 &dpo);
7621 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7622 lkd = lookup_dpo_get(dpo1->dpoi_index);
7623
7624 FIB_TEST((fib_index == lkd->lkd_fib_index),
7625 "%U/%U is deag in %d %U",
7626 format_mpls_unicast_label, deag_label,
7627 format_mpls_eos_bit, MPLS_EOS,
7628 lkd->lkd_fib_index,
7629 format_dpo_id, &dpo, 0);
7630 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7631 "%U/%U is dst deag",
7632 format_mpls_unicast_label, deag_label,
7633 format_mpls_eos_bit, MPLS_EOS);
7634 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
7635 "%U/%U is %U dst deag",
7636 format_mpls_unicast_label, deag_label,
7637 format_mpls_eos_bit, MPLS_EOS,
7638 format_dpo_proto, lkd->lkd_proto);
7639
7640 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7641
7642 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7643 &pfx)),
7644 "%U/%U not present",
7645 format_mpls_unicast_label, deag_label,
7646 format_mpls_eos_bit, MPLS_EOS);
7647
7648 /*
7649 * A route deag route for non-EOS
7650 */
7651 pfx.fp_eos = MPLS_NON_EOS;
7652 lfe = fib_table_entry_path_add(lfib_index,
7653 &pfx,
7654 FIB_SOURCE_CLI,
7655 FIB_ENTRY_FLAG_NONE,
7656 FIB_PROTOCOL_IP4,
7657 &zero_addr,
7658 ~0,
7659 lfib_index,
7660 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007661 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007662 FIB_ROUTE_PATH_FLAG_NONE);
7663
7664 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7665 "%U/%U present",
7666 format_mpls_unicast_label, deag_label,
7667 format_mpls_eos_bit, MPLS_NON_EOS);
7668
7669 fib_entry_contribute_forwarding(lfe,
7670 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7671 &dpo);
7672 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7673 lkd = lookup_dpo_get(dpo1->dpoi_index);
7674
7675 FIB_TEST((fib_index == lkd->lkd_fib_index),
7676 "%U/%U is deag in %d %U",
7677 format_mpls_unicast_label, deag_label,
7678 format_mpls_eos_bit, MPLS_NON_EOS,
7679 lkd->lkd_fib_index,
7680 format_dpo_id, &dpo, 0);
7681 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7682 "%U/%U is dst deag",
7683 format_mpls_unicast_label, deag_label,
7684 format_mpls_eos_bit, MPLS_NON_EOS);
7685
7686 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
7687 "%U/%U is %U dst deag",
7688 format_mpls_unicast_label, deag_label,
7689 format_mpls_eos_bit, MPLS_NON_EOS,
7690 format_dpo_proto, lkd->lkd_proto);
7691
7692 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7693
7694 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7695 &pfx)),
7696 "%U/%U not present",
7697 format_mpls_unicast_label, deag_label,
7698 format_mpls_eos_bit, MPLS_EOS);
7699
Neale Rannsad422ed2016-11-02 14:20:04 +00007700 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007701
Neale Rannsad422ed2016-11-02 14:20:04 +00007702 /*
7703 * An MPLS x-connect
7704 */
7705 fib_prefix_t pfx_1200 = {
7706 .fp_len = 21,
7707 .fp_proto = FIB_PROTOCOL_MPLS,
7708 .fp_label = 1200,
7709 .fp_eos = MPLS_NON_EOS,
7710 };
7711 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
7712 .type = FT_LB_LABEL_STACK_O_ADJ,
7713 .label_stack_o_adj = {
7714 .adj = ai_mpls_10_10_10_1,
7715 .label_stack_size = 4,
7716 .label_stack = {
7717 200, 300, 400, 500,
7718 },
7719 .eos = MPLS_NON_EOS,
7720 },
7721 };
7722 dpo_id_t neos_1200 = DPO_INVALID;
7723 dpo_id_t ip_1200 = DPO_INVALID;
7724 mpls_label_t *l200 = NULL;
7725 vec_add1(l200, 200);
7726 vec_add1(l200, 300);
7727 vec_add1(l200, 400);
7728 vec_add1(l200, 500);
7729
7730 lfe = fib_table_entry_update_one_path(fib_index,
7731 &pfx_1200,
7732 FIB_SOURCE_API,
7733 FIB_ENTRY_FLAG_NONE,
7734 FIB_PROTOCOL_IP4,
7735 &nh_10_10_10_1,
7736 tm->hw[0]->sw_if_index,
7737 ~0, // invalid fib index
7738 1,
7739 l200,
7740 FIB_ROUTE_PATH_FLAG_NONE);
7741
7742 FIB_TEST(fib_test_validate_entry(lfe,
7743 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7744 1,
7745 &neos_o_10_10_10_1),
7746 "1200/0 LB 1 buckets via: "
7747 "adj 10.10.11.1");
7748
7749 /*
7750 * A recursive route via the MPLS x-connect
7751 */
7752 fib_prefix_t pfx_2_2_2_3_s_32 = {
7753 .fp_len = 32,
7754 .fp_proto = FIB_PROTOCOL_IP4,
7755 .fp_addr = {
7756 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7757 },
7758 };
7759 fib_route_path_t *rpaths = NULL, rpath = {
7760 .frp_proto = FIB_PROTOCOL_MPLS,
7761 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007762 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00007763 .frp_sw_if_index = ~0, // recurive
7764 .frp_fib_index = 0, // Default MPLS fib
7765 .frp_weight = 1,
7766 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
7767 .frp_label_stack = NULL,
7768 };
7769 vec_add1(rpaths, rpath);
7770
7771 fib_table_entry_path_add2(fib_index,
7772 &pfx_2_2_2_3_s_32,
7773 FIB_SOURCE_API,
7774 FIB_ENTRY_FLAG_NONE,
7775 rpaths);
7776
7777 /*
7778 * A labelled recursive route via the MPLS x-connect
7779 */
7780 fib_prefix_t pfx_2_2_2_4_s_32 = {
7781 .fp_len = 32,
7782 .fp_proto = FIB_PROTOCOL_IP4,
7783 .fp_addr = {
7784 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7785 },
7786 };
7787 mpls_label_t *l999 = NULL;
7788 vec_add1(l999, 999);
7789 rpaths[0].frp_label_stack = l999,
7790
7791 fib_table_entry_path_add2(fib_index,
7792 &pfx_2_2_2_4_s_32,
7793 FIB_SOURCE_API,
7794 FIB_ENTRY_FLAG_NONE,
7795 rpaths);
7796
7797 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7798 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7799 &ip_1200);
7800 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7801 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7802 &neos_1200);
7803
7804 fib_test_lb_bucket_t ip_o_1200 = {
7805 .type = FT_LB_O_LB,
7806 .lb = {
7807 .lb = ip_1200.dpoi_index,
7808 },
7809 };
7810 fib_test_lb_bucket_t mpls_o_1200 = {
7811 .type = FT_LB_LABEL_O_LB,
7812 .label_o_lb = {
7813 .lb = neos_1200.dpoi_index,
7814 .label = 999,
7815 .eos = MPLS_EOS,
7816 },
7817 };
7818
7819 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7820 FIB_TEST(fib_test_validate_entry(lfe,
7821 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7822 1,
7823 &ip_o_1200),
7824 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
7825 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7826 FIB_TEST(fib_test_validate_entry(lfe,
7827 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7828 1,
7829 &mpls_o_1200),
7830 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
7831
7832 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
7833 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
7834 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7835
7836 dpo_reset(&neos_1200);
7837 dpo_reset(&ip_1200);
7838
7839 /*
7840 * A recursive via a label that does not exist
7841 */
7842 fib_test_lb_bucket_t bucket_drop = {
7843 .type = FT_LB_SPECIAL,
7844 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07007845 .adj = DPO_PROTO_IP4,
7846 },
7847 };
7848 fib_test_lb_bucket_t mpls_bucket_drop = {
7849 .type = FT_LB_SPECIAL,
7850 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00007851 .adj = DPO_PROTO_MPLS,
7852 },
7853 };
7854
7855 rpaths[0].frp_label_stack = NULL;
7856 lfe = fib_table_entry_path_add2(fib_index,
7857 &pfx_2_2_2_4_s_32,
7858 FIB_SOURCE_API,
7859 FIB_ENTRY_FLAG_NONE,
7860 rpaths);
7861
7862 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7864 &ip_1200);
7865 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7866
7867 FIB_TEST(fib_test_validate_entry(lfe,
7868 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7869 1,
7870 &ip_o_1200),
7871 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
7872 lfe = fib_table_lookup(fib_index, &pfx_1200);
7873 FIB_TEST(fib_test_validate_entry(lfe,
7874 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7875 1,
7876 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07007877 "1200/neos LB 1 buckets via: ip4-DROP");
7878 FIB_TEST(fib_test_validate_entry(lfe,
7879 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7880 1,
7881 &mpls_bucket_drop),
7882 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00007883
7884 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7885
7886 dpo_reset(&ip_1200);
7887
7888 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007889 * An rx-interface route.
7890 * like the tail of an mcast LSP
7891 */
7892 dpo_id_t idpo = DPO_INVALID;
7893
7894 interface_dpo_add_or_lock(DPO_PROTO_IP4,
7895 tm->hw[0]->sw_if_index,
7896 &idpo);
7897
7898 fib_prefix_t pfx_2500 = {
7899 .fp_len = 21,
7900 .fp_proto = FIB_PROTOCOL_MPLS,
7901 .fp_label = 2500,
7902 .fp_eos = MPLS_EOS,
7903 .fp_payload_proto = DPO_PROTO_IP4,
7904 };
7905 fib_test_lb_bucket_t rx_intf_0 = {
7906 .type = FT_LB_INTF,
7907 .adj = {
7908 .adj = idpo.dpoi_index,
7909 },
7910 };
7911
7912 lfe = fib_table_entry_update_one_path(fib_index,
7913 &pfx_2500,
7914 FIB_SOURCE_API,
7915 FIB_ENTRY_FLAG_NONE,
7916 FIB_PROTOCOL_IP4,
7917 NULL,
7918 tm->hw[0]->sw_if_index,
7919 ~0, // invalid fib index
7920 0,
7921 NULL,
7922 FIB_ROUTE_PATH_INTF_RX);
7923 FIB_TEST(fib_test_validate_entry(lfe,
7924 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7925 1,
7926 &rx_intf_0),
7927 "2500 rx-interface 0");
7928 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
7929
7930 /*
7931 * An MPLS mulicast entry
7932 */
7933 fib_prefix_t pfx_3500 = {
7934 .fp_len = 21,
7935 .fp_proto = FIB_PROTOCOL_MPLS,
7936 .fp_label = 3500,
7937 .fp_eos = MPLS_EOS,
7938 .fp_payload_proto = DPO_PROTO_IP4,
7939 };
7940 fib_test_rep_bucket_t mc_0 = {
7941 .type = FT_REP_LABEL_O_ADJ,
7942 .label_o_adj = {
7943 .adj = ai_mpls_10_10_10_1,
7944 .label = 3300,
7945 .eos = MPLS_EOS,
7946 },
7947 };
7948 fib_test_rep_bucket_t mc_intf_0 = {
7949 .type = FT_REP_INTF,
7950 .adj = {
7951 .adj = idpo.dpoi_index,
7952 },
7953 };
7954 mpls_label_t *l3300 = NULL;
7955 vec_add1(l3300, 3300);
7956
7957 lfe = fib_table_entry_update_one_path(lfib_index,
7958 &pfx_3500,
7959 FIB_SOURCE_API,
7960 FIB_ENTRY_FLAG_MULTICAST,
7961 FIB_PROTOCOL_IP4,
7962 &nh_10_10_10_1,
7963 tm->hw[0]->sw_if_index,
7964 ~0, // invalid fib index
7965 1,
7966 l3300,
7967 FIB_ROUTE_PATH_FLAG_NONE);
7968 FIB_TEST(fib_test_validate_entry(lfe,
7969 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7970 1,
7971 &mc_0),
7972 "3500 via replicate over 10.10.10.1");
7973
7974 /*
7975 * MPLS Bud-node. Add a replication via an interface-receieve path
7976 */
7977 lfe = fib_table_entry_path_add(lfib_index,
7978 &pfx_3500,
7979 FIB_SOURCE_API,
7980 FIB_ENTRY_FLAG_MULTICAST,
7981 FIB_PROTOCOL_IP4,
7982 NULL,
7983 tm->hw[0]->sw_if_index,
7984 ~0, // invalid fib index
7985 0,
7986 NULL,
7987 FIB_ROUTE_PATH_INTF_RX);
7988 FIB_TEST(fib_test_validate_entry(lfe,
7989 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7990 2,
7991 &mc_0,
7992 &mc_intf_0),
7993 "3500 via replicate over 10.10.10.1 and interface-rx");
7994
7995 /*
7996 * Add a replication via an interface-free for-us path
7997 */
7998 fib_test_rep_bucket_t mc_disp = {
7999 .type = FT_REP_DISP_MFIB_LOOKUP,
8000 .adj = {
8001 .adj = idpo.dpoi_index,
8002 },
8003 };
8004 lfe = fib_table_entry_path_add(lfib_index,
8005 &pfx_3500,
8006 FIB_SOURCE_API,
8007 FIB_ENTRY_FLAG_MULTICAST,
8008 FIB_PROTOCOL_IP4,
8009 NULL,
8010 5, // rpf-id
8011 0, // default table
8012 0,
8013 NULL,
8014 FIB_ROUTE_PATH_RPF_ID);
8015 FIB_TEST(fib_test_validate_entry(lfe,
8016 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8017 3,
8018 &mc_0,
8019 &mc_disp,
8020 &mc_intf_0),
8021 "3500 via replicate over 10.10.10.1 and interface-rx");
8022
8023
8024
8025 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8026 dpo_reset(&idpo);
8027
8028 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008029 * cleanup
8030 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008031 mpls_sw_interface_enable_disable(&mpls_main,
8032 tm->hw[0]->sw_if_index,
8033 0);
8034
Neale Rannsad422ed2016-11-02 14:20:04 +00008035 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008036 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008037 lb_count, pool_elts(load_balance_pool));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008038 FIB_TEST(0 == pool_elts(interface_dpo_pool),
8039 "interface_dpo resources freed %d of %d",
8040 0, pool_elts(interface_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008041
8042 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008043}
8044
8045static clib_error_t *
8046fib_test (vlib_main_t * vm,
8047 unformat_input_t * input,
8048 vlib_cli_command_t * cmd_arg)
8049{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008050 int res;
8051
8052 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008053 fib_test_mk_intf(4);
8054
Neale Ranns88fc83e2017-04-05 08:11:14 -07008055 if (unformat (input, "debug"))
8056 {
8057 fib_test_do_debug = 1;
8058 }
8059
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008060 if (unformat (input, "ip"))
8061 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008062 res += fib_test_v4();
8063 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008064 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008065 else if (unformat (input, "label"))
8066 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008067 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008068 }
8069 else if (unformat (input, "ae"))
8070 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008071 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008072 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008073 else if (unformat (input, "lfib"))
8074 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008075 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008076 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008077 else if (unformat (input, "walk"))
8078 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008079 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008080 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008081 else if (unformat (input, "bfd"))
8082 {
8083 res += fib_test_bfd();
8084 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008085 else
8086 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008087 res += fib_test_v4();
8088 res += fib_test_v6();
8089 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008090 res += fib_test_bfd();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008091 res += fib_test_label();
8092 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008093
8094 /*
8095 * fib-walk process must be disabled in order for the walk tests to work
8096 */
8097 fib_walk_process_disable();
8098 res += fib_test_walk();
8099 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008100 }
8101
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008102 if (res)
8103 {
8104 return clib_error_return(0, "FIB Unit Test Failed");
8105 }
8106 else
8107 {
8108 return (NULL);
8109 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008110}
8111
8112VLIB_CLI_COMMAND (test_fib_command, static) = {
8113 .path = "test fib",
8114 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8115 .function = fib_test,
8116};
8117
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008118clib_error_t *
8119fib_test_init (vlib_main_t *vm)
8120{
8121 return 0;
8122}
8123
8124VLIB_INIT_FUNCTION (fib_test_init);