blob: 1a9cce241d5f608f5a78f771be2bccb18615d9ba [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 Ranns0bfe5d82016-08-25 15:29:12 +010027
28#include <vnet/mpls/mpls.h>
29
30#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000031#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010032#include <vnet/fib/fib_walk.h>
33#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010034#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035
36#define FIB_TEST_I(_cond, _comment, _args...) \
37({ \
38 int _evald = (_cond); \
39 if (!(_evald)) { \
40 fformat(stderr, "FAIL:%d: " _comment "\n", \
41 __LINE__, ##_args); \
42 } else { \
43 fformat(stderr, "PASS:%d: " _comment "\n", \
44 __LINE__, ##_args); \
45 } \
46 _evald; \
47})
48#define FIB_TEST(_cond, _comment, _args...) \
49{ \
50 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000051 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010052 ASSERT(!("FAIL: " _comment)); \
53 } \
54}
55
56/**
57 * A 'i'm not fussed is this is not efficient' store of test data
58 */
59typedef struct test_main_t_ {
60 /**
61 * HW if indicies
62 */
63 u32 hw_if_indicies[4];
64 /**
65 * HW interfaces
66 */
67 vnet_hw_interface_t * hw[4];
68
69} test_main_t;
70static test_main_t test_main;
71
72/* fake ethernet device class, distinct from "fake-ethX" */
73static u8 * format_test_interface_name (u8 * s, va_list * args)
74{
75 u32 dev_instance = va_arg (*args, u32);
76 return format (s, "test-eth%d", dev_instance);
77}
78
79static uword dummy_interface_tx (vlib_main_t * vm,
80 vlib_node_runtime_t * node,
81 vlib_frame_t * frame)
82{
83 clib_warning ("you shouldn't be here, leaking buffers...");
84 return frame->n_vectors;
85}
86
Neale Ranns8b37b872016-11-21 12:25:22 +000087static clib_error_t *
88test_interface_admin_up_down (vnet_main_t * vnm,
89 u32 hw_if_index,
90 u32 flags)
91{
92 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
93 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
94 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
95 return 0;
96}
97
Neale Ranns0bfe5d82016-08-25 15:29:12 +010098VNET_DEVICE_CLASS (test_interface_device_class,static) = {
99 .name = "Test interface",
100 .format_device_name = format_test_interface_name,
101 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000102 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100103};
104
105static u8 *hw_address;
106
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000107static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100108fib_test_mk_intf (u32 ninterfaces)
109{
110 clib_error_t * error = NULL;
111 test_main_t *tm = &test_main;
112 u8 byte;
113 u32 i;
114
115 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
116
117 for (i=0; i<6; i++)
118 {
119 byte = 0xd0+i;
120 vec_add1(hw_address, byte);
121 }
122
123 for (i = 0; i < ninterfaces; i++)
124 {
125 hw_address[5] = i;
126
127 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000128 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100129 i /* instance */,
130 hw_address,
131 &tm->hw_if_indicies[i],
132 /* flag change */ 0);
133
134 FIB_TEST((NULL == error), "ADD interface %d", i);
135
Neale Ranns8b37b872016-11-21 12:25:22 +0000136 error = vnet_hw_interface_set_flags(vnet_get_main(),
137 tm->hw_if_indicies[i],
138 VNET_HW_INTERFACE_FLAG_LINK_UP);
139 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100140 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000141 vec_validate (ip4_main.fib_index_by_sw_if_index,
142 tm->hw[i]->sw_if_index);
143 vec_validate (ip6_main.fib_index_by_sw_if_index,
144 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100145 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
146 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000147
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100148 error = vnet_sw_interface_set_flags(vnet_get_main(),
149 tm->hw[i]->sw_if_index,
150 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
151 FIB_TEST((NULL == error), "UP interface %d", i);
152 }
153 /*
154 * re-eval after the inevitable realloc
155 */
156 for (i = 0; i < ninterfaces; i++)
157 {
158 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
159 tm->hw_if_indicies[i]);
160 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000161
162 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100163}
164
Neale Ranns3ee44042016-10-03 13:05:48 +0100165#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100166{ \
167 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
168 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
169 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
170 fib_table_lookup(fib_index, (_via_prefix))); \
171 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100172 load_balance_get_bucket(_rec_dpo->dpoi_index, \
173 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100174 "%U is recursive via %U", \
175 format_fib_prefix, (_rec_prefix), \
176 format_fib_prefix, _via_prefix); \
177}
178
179#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
180{ \
181 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
182 fib_table_lookup_exact_match(fib_index, (_prefix))); \
183 const dpo_id_t *_dpo1 = \
184 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
185 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
186 format_dpo_type, _dpo1->dpoi_type); \
187 FIB_TEST((_ai == _dpo1->dpoi_index), \
188 "%U bucket %d resolves via %U", \
189 format_fib_prefix, (_prefix), \
190 _bucket, \
191 format_dpo_id, _dpo1, 0); \
192}
193
Neale Ranns3ee44042016-10-03 13:05:48 +0100194#define FIB_TEST_RPF(_cond, _comment, _args...) \
195{ \
196 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
197 return (0); \
198 } \
199}
200
201static int
202fib_test_urpf_is_equal (fib_node_index_t fei,
203 fib_forward_chain_type_t fct,
204 u32 num, ...)
205{
Neale Ranns948e00f2016-10-20 13:39:34 +0100206 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100207 fib_urpf_list_t *urpf;
208 index_t ui;
209 va_list ap;
210 int ii;
211
212 va_start(ap, num);
213
214 fib_entry_contribute_forwarding(fei, fct, &dpo);
215 ui = load_balance_get_urpf(dpo.dpoi_index);
216
217 urpf = fib_urpf_list_get(ui);
218
219 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
220 "RPF:%U len %d == %d",
221 format_fib_urpf_list, ui,
222 num, vec_len(urpf->furpf_itfs));
223 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
224 "RPF:%U check-size %d == %d",
225 format_fib_urpf_list, ui,
226 num, vec_len(urpf->furpf_itfs));
227
228 for (ii = 0; ii < num; ii++)
229 {
230 adj_index_t ai = va_arg(ap, adj_index_t);
231
232 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
233 "RPF:%d item:%d - %d == %d",
234 ui, ii, ai, urpf->furpf_itfs[ii]);
235 FIB_TEST_RPF(fib_urpf_check(ui, ai),
236 "RPF:%d %d found",
237 ui, ai);
238 }
239
240 dpo_reset(&dpo);
241
Neale Ranns5899fde2016-10-12 13:51:05 +0100242 va_end(ap);
243
Neale Ranns3ee44042016-10-03 13:05:48 +0100244 return (1);
245}
246
Neale Rannsb80c5362016-10-08 13:03:40 +0100247static u8*
248fib_test_build_rewrite (u8 *eth_addr)
249{
250 u8* rewrite = NULL;
251
252 vec_validate(rewrite, 13);
253
254 memcpy(rewrite, eth_addr, 6);
255 memcpy(rewrite+6, eth_addr, 6);
256
257 return (rewrite);
258}
259
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000260typedef enum fib_test_lb_bucket_type_t_ {
261 FT_LB_LABEL_O_ADJ,
Neale Rannsad422ed2016-11-02 14:20:04 +0000262 FT_LB_LABEL_STACK_O_ADJ,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000263 FT_LB_LABEL_O_LB,
264 FT_LB_O_LB,
265 FT_LB_SPECIAL,
266 FT_LB_ADJ,
267} fib_test_lb_bucket_type_t;
268
269typedef struct fib_test_lb_bucket_t_ {
270 fib_test_lb_bucket_type_t type;
271
272 union
273 {
274 struct
275 {
276 mpls_eos_bit_t eos;
277 mpls_label_t label;
278 u8 ttl;
279 adj_index_t adj;
280 } label_o_adj;
281 struct
282 {
283 mpls_eos_bit_t eos;
Neale Rannsad422ed2016-11-02 14:20:04 +0000284 mpls_label_t label_stack[8];
285 u8 label_stack_size;
286 u8 ttl;
287 adj_index_t adj;
288 } label_stack_o_adj;
289 struct
290 {
291 mpls_eos_bit_t eos;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000292 mpls_label_t label;
293 u8 ttl;
294 index_t lb;
295 } label_o_lb;
296 struct
297 {
298 index_t adj;
299 } adj;
300 struct
301 {
302 index_t lb;
303 } lb;
304 struct
305 {
306 index_t adj;
307 } special;
308 };
309} fib_test_lb_bucket_t;
310
311#define FIB_TEST_LB(_cond, _comment, _args...) \
312{ \
313 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
314 return (0); \
315 } \
316}
317
318static int
319fib_test_validate_lb_v (const load_balance_t *lb,
320 u16 n_buckets,
321 va_list ap)
322{
323 const dpo_id_t *dpo;
324 int bucket;
325
326 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
327
328 for (bucket = 0; bucket < n_buckets; bucket++)
329 {
330 const fib_test_lb_bucket_t *exp;
331
332 exp = va_arg(ap, fib_test_lb_bucket_t*);
333 dpo = load_balance_get_bucket_i(lb, bucket);
334
335 switch (exp->type)
336 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000337 case FT_LB_LABEL_STACK_O_ADJ:
338 {
339 const mpls_label_dpo_t *mld;
340 mpls_label_t hdr;
341 u32 ii;
342
343 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
344 "bucket %d stacks on %U",
345 bucket,
346 format_dpo_type, dpo->dpoi_type);
347
348 mld = mpls_label_dpo_get(dpo->dpoi_index);
349
350 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
351 "label stack size",
352 mld->mld_n_labels);
353
354 for (ii = 0; ii < mld->mld_n_labels; ii++)
355 {
356 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
357 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
358 exp->label_stack_o_adj.label_stack[ii]),
359 "bucket %d stacks on label %d",
360 bucket,
361 exp->label_stack_o_adj.label_stack[ii]);
362
363 if (ii == mld->mld_n_labels-1)
364 {
365 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
366 exp->label_o_adj.eos),
367 "bucket %d stacks on label %d %U!=%U",
368 bucket,
369 exp->label_stack_o_adj.label_stack[ii],
370 format_mpls_eos_bit, exp->label_o_adj.eos,
371 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
372 }
373 else
374 {
375 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
376 "bucket %d stacks on label %d %U",
377 bucket,
378 exp->label_stack_o_adj.label_stack[ii],
379 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
380 }
381 }
382
383 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
384 "bucket %d label stacks on %U",
385 bucket,
386 format_dpo_type, mld->mld_dpo.dpoi_type);
387
388 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
389 "bucket %d label stacks on adj %d",
390 bucket,
391 exp->label_stack_o_adj.adj);
392 }
393 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000394 case FT_LB_LABEL_O_ADJ:
395 {
396 const mpls_label_dpo_t *mld;
397 mpls_label_t hdr;
398 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
399 "bucket %d stacks on %U",
400 bucket,
401 format_dpo_type, dpo->dpoi_type);
402
403 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000404 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000405
406 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
407 exp->label_o_adj.label),
408 "bucket %d stacks on label %d",
409 bucket,
410 exp->label_o_adj.label);
411
412 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
413 exp->label_o_adj.eos),
414 "bucket %d stacks on label %d %U",
415 bucket,
416 exp->label_o_adj.label,
417 format_mpls_eos_bit, exp->label_o_adj.eos);
418
419 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
420 "bucket %d label stacks on %U",
421 bucket,
422 format_dpo_type, mld->mld_dpo.dpoi_type);
423
424 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
425 "bucket %d label stacks on adj %d",
426 bucket,
427 exp->label_o_adj.adj);
428 }
429 break;
430 case FT_LB_LABEL_O_LB:
431 {
432 const mpls_label_dpo_t *mld;
433 mpls_label_t hdr;
434
435 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
436 "bucket %d stacks on %U",
437 bucket,
438 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000439
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000440 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000441 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000442
Neale Rannsad422ed2016-11-02 14:20:04 +0000443 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
444 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000445 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
446 exp->label_o_lb.label),
447 "bucket %d stacks on label %d",
448 bucket,
449 exp->label_o_lb.label);
450
451 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
452 exp->label_o_lb.eos),
453 "bucket %d stacks on label %d %U",
454 bucket,
455 exp->label_o_lb.label,
456 format_mpls_eos_bit, exp->label_o_lb.eos);
457
458 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
459 "bucket %d label stacks on %U",
460 bucket,
461 format_dpo_type, mld->mld_dpo.dpoi_type);
462
463 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
464 "bucket %d label stacks on LB %d",
465 bucket,
466 exp->label_o_lb.lb);
467 }
468 break;
469 case FT_LB_ADJ:
470 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
471 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
472 "bucket %d stacks on %U",
473 bucket,
474 format_dpo_type, dpo->dpoi_type);
475 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
476 "bucket %d stacks on adj %d",
477 bucket,
478 exp->adj.adj);
479 break;
480 case FT_LB_O_LB:
481 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
482 "bucket %d stacks on %U",
483 bucket,
484 format_dpo_type, dpo->dpoi_type);
485 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
486 "bucket %d stacks on lb %d",
487 bucket,
488 exp->lb.lb);
489 break;
490 case FT_LB_SPECIAL:
491 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
492 "bucket %d stacks on %U",
493 bucket,
494 format_dpo_type, dpo->dpoi_type);
495 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
496 "bucket %d stacks on drop %d",
497 bucket,
498 exp->special.adj);
499 break;
500 }
501 }
502 return (!0);
503}
504
505static int
506fib_test_validate_entry (fib_node_index_t fei,
507 fib_forward_chain_type_t fct,
508 u16 n_buckets,
509 ...)
510{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000511 dpo_id_t dpo = DPO_INVALID;
Neale Rannsad422ed2016-11-02 14:20:04 +0000512 const load_balance_t *lb;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000513 fib_prefix_t pfx;
514 index_t fw_lbi;
515 u32 fib_index;
516 va_list ap;
517 int res;
518
519 va_start(ap, n_buckets);
520
521 fib_entry_get_prefix(fei, &pfx);
522 fib_index = fib_entry_get_fib_index(fei);
523 fib_entry_contribute_forwarding(fei, fct, &dpo);
524
525 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
526 "Entry links to %U",
527 format_dpo_type, dpo.dpoi_type);
528 lb = load_balance_get(dpo.dpoi_index);
529
530 res = fib_test_validate_lb_v(lb, n_buckets, ap);
531
532 /*
533 * ensure that the LB contributed by the entry is the
534 * same as the LB in the forwarding tables
535 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000536 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000537 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000538 switch (pfx.fp_proto)
539 {
540 case FIB_PROTOCOL_IP4:
541 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
542 break;
543 case FIB_PROTOCOL_IP6:
544 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
545 break;
546 case FIB_PROTOCOL_MPLS:
547 {
548 mpls_unicast_header_t hdr = {
549 .label_exp_s_ttl = 0,
550 };
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000551
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
553 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
554 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000555
Neale Rannsad422ed2016-11-02 14:20:04 +0000556 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
557 break;
558 }
559 default:
560 fw_lbi = 0;
561 }
562 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
563 "Contributed LB = FW LB: %U\n %U",
564 format_load_balance, fw_lbi, 0,
565 format_load_balance, dpo.dpoi_index, 0);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000566 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000567
568 dpo_reset(&dpo);
569
570 va_end(ap);
571
572 return (res);
573}
574
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000575static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100576fib_test_v4 (void)
577{
578 /*
579 * In the default table check for the presence and correct forwarding
580 * of the special entries
581 */
582 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
583 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
584 const ip_adjacency_t *adj;
585 const load_balance_t *lb;
586 test_main_t *tm;
587 u32 fib_index;
588 int ii;
589
590 /* via 10.10.10.1 */
591 ip46_address_t nh_10_10_10_1 = {
592 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
593 };
594 /* via 10.10.10.2 */
595 ip46_address_t nh_10_10_10_2 = {
596 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
597 };
598
599 tm = &test_main;
600
601 /* Find or create FIB table 11 */
602 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
603
604 for (ii = 0; ii < 4; ii++)
605 {
606 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
607 }
608
609 fib_prefix_t pfx_0_0_0_0_s_0 = {
610 .fp_len = 0,
611 .fp_proto = FIB_PROTOCOL_IP4,
612 .fp_addr = {
613 .ip4 = {
614 {0}
615 },
616 },
617 };
618
619 fib_prefix_t pfx = {
620 .fp_len = 0,
621 .fp_proto = FIB_PROTOCOL_IP4,
622 .fp_addr = {
623 .ip4 = {
624 {0}
625 },
626 },
627 };
628
629 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
630
631 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
632 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
633 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
634 "Default route is DROP");
635
636 pfx.fp_len = 32;
637 fei = fib_table_lookup(fib_index, &pfx);
638 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
639 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
640 "all 0s route is DROP");
641
642 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
643 pfx.fp_len = 32;
644 fei = fib_table_lookup(fib_index, &pfx);
645 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
646 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
647 "all 1s route is DROP");
648
649 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
650 pfx.fp_len = 8;
651 fei = fib_table_lookup(fib_index, &pfx);
652 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
653 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
654 "all-mcast route is DROP");
655
656 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
657 pfx.fp_len = 8;
658 fei = fib_table_lookup(fib_index, &pfx);
659 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
660 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
661 "class-e route is DROP");
662
663 /*
664 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
665 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000666 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
667 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100668 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000669#define ENBR (5+5+2)
670#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100671 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000672 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100673 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000674 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100675 fib_entry_pool_size());
676
677 /*
678 * add interface routes.
679 * validate presence of /24 attached and /32 recieve.
680 * test for the presence of the receive address in the glean and local adj
681 */
682 fib_prefix_t local_pfx = {
683 .fp_len = 24,
684 .fp_proto = FIB_PROTOCOL_IP4,
685 .fp_addr = {
686 .ip4 = {
687 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
688 },
689 },
690 };
691
692 fib_table_entry_update_one_path(fib_index, &local_pfx,
693 FIB_SOURCE_INTERFACE,
694 (FIB_ENTRY_FLAG_CONNECTED |
695 FIB_ENTRY_FLAG_ATTACHED),
696 FIB_PROTOCOL_IP4,
697 NULL,
698 tm->hw[0]->sw_if_index,
699 ~0, // invalid fib index
700 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000701 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100702 FIB_ROUTE_PATH_FLAG_NONE);
703 fei = fib_table_lookup(fib_index, &local_pfx);
704 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
705 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
706 fib_entry_get_flags(fei)),
707 "Flags set on attached interface");
708
709 ai = fib_entry_get_adj(fei);
710 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
711 adj = adj_get(ai);
712 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
713 "attached interface adj is glean");
714 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
715 &adj->sub_type.glean.receive_addr)),
716 "attached interface adj is receive ok");
717
718 local_pfx.fp_len = 32;
719 fib_table_entry_update_one_path(fib_index, &local_pfx,
720 FIB_SOURCE_INTERFACE,
721 (FIB_ENTRY_FLAG_CONNECTED |
722 FIB_ENTRY_FLAG_LOCAL),
723 FIB_PROTOCOL_IP4,
724 NULL,
725 tm->hw[0]->sw_if_index,
726 ~0, // invalid fib index
727 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000728 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100729 FIB_ROUTE_PATH_FLAG_NONE);
730 fei = fib_table_lookup(fib_index, &local_pfx);
731 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
732 fib_entry_get_flags(fei)),
733 "Flags set on local interface");
734
735 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
736
737 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100738 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
739 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100740 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
741 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
742 "local interface adj is local");
743 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
744
745 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
746 &rd->rd_addr)),
747 "local interface adj is receive ok");
748
749 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
750 FIB_PROTOCOL_IP4,
751 FIB_SOURCE_INTERFACE)),
752 "2 Interface Source'd prefixes");
753
754 /*
755 * +2 interface routes +2 non-shared path-lists
756 */
757 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000758 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100759 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000760 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100761 fib_entry_pool_size());
762
763 /*
764 * Modify the default route to be via an adj not yet known.
765 * this sources the defalut route with the API source, which is
766 * a higher preference to the DEFAULT_ROUTE source
767 */
768 pfx.fp_addr.ip4.as_u32 = 0;
769 pfx.fp_len = 0;
770 fib_table_entry_path_add(fib_index, &pfx,
771 FIB_SOURCE_API,
772 FIB_ENTRY_FLAG_NONE,
773 FIB_PROTOCOL_IP4,
774 &nh_10_10_10_1,
775 tm->hw[0]->sw_if_index,
776 ~0, // invalid fib index
777 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000778 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100779 FIB_ROUTE_PATH_FLAG_NONE);
780 fei = fib_table_lookup(fib_index, &pfx);
781 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
782 "Flags set on API route");
783
784 FIB_TEST((fei == dfrt), "default route same index");
785 ai = fib_entry_get_adj(fei);
786 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
787 adj = adj_get(ai);
788 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
789 "adj is incomplete");
790 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
791 "adj nbr next-hop ok");
792 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
793 FIB_PROTOCOL_IP4,
794 FIB_SOURCE_API)),
795 "1 API Source'd prefixes");
796
797 /*
798 * find the adj in the shared db
799 */
800 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100801 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100802 &nh_10_10_10_1,
803 tm->hw[0]->sw_if_index);
804 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
805 adj_unlock(locked_ai);
806
807 /*
808 * +1 shared path-list
809 */
810 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
811 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000812 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100813 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000814 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100815 fib_entry_pool_size());
816
817 /*
818 * remove the API source from the default route. We expected
819 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
820 */
821 pfx.fp_addr.ip4.as_u32 = 0;
822 pfx.fp_len = 0;
823 fib_table_entry_path_remove(fib_index, &pfx,
824 FIB_SOURCE_API,
825 FIB_PROTOCOL_IP4,
826 &nh_10_10_10_1,
827 tm->hw[0]->sw_if_index,
828 ~0, // non-recursive path, so no FIB index
829 1,
830 FIB_ROUTE_PATH_FLAG_NONE);
831
832 fei = fib_table_lookup(fib_index, &pfx);
833
834 FIB_TEST((fei == dfrt), "default route same index");
835 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
836 "Default route is DROP");
837
838 /*
839 * -1 shared-path-list
840 */
841 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000842 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100843 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000844 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100845 fib_entry_pool_size());
846
847 /*
848 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
849 */
850 fib_prefix_t pfx_10_10_10_1_s_32 = {
851 .fp_len = 32,
852 .fp_proto = FIB_PROTOCOL_IP4,
853 .fp_addr = {
854 /* 10.10.10.1 */
855 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
856 },
857 };
858 fib_prefix_t pfx_10_10_10_2_s_32 = {
859 .fp_len = 32,
860 .fp_proto = FIB_PROTOCOL_IP4,
861 .fp_addr = {
862 /* 10.10.10.2 */
863 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
864 },
865 };
866 fib_prefix_t pfx_11_11_11_11_s_32 = {
867 .fp_len = 32,
868 .fp_proto = FIB_PROTOCOL_IP4,
869 .fp_addr = {
870 /* 11.11.11.11 */
871 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
872 },
873 };
874 u8 eth_addr[] = {
875 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
876 };
Neale Rannsb80c5362016-10-08 13:03:40 +0100877
Neale Ranns3ee44042016-10-03 13:05:48 +0100878 ip46_address_t nh_12_12_12_12 = {
879 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
880 };
881 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100882
883 /*
884 * Add a route via an incomplete ADJ. then complete the ADJ
885 * Expect the route LB is updated to use complete adj type.
886 */
887 fei = fib_table_entry_update_one_path(fib_index,
888 &pfx_11_11_11_11_s_32,
889 FIB_SOURCE_API,
890 FIB_ENTRY_FLAG_ATTACHED,
891 FIB_PROTOCOL_IP4,
892 &pfx_10_10_10_1_s_32.fp_addr,
893 tm->hw[0]->sw_if_index,
894 ~0, // invalid fib index
895 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000896 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100897 FIB_ROUTE_PATH_FLAG_NONE);
898
899 dpo = fib_entry_contribute_ip_forwarding(fei);
900 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
901 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
902 "11.11.11.11/32 via incomplete adj");
903
904 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100905 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100906 &pfx_10_10_10_1_s_32.fp_addr,
907 tm->hw[0]->sw_if_index);
908 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
909 adj = adj_get(ai_01);
910 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
911 "adj is incomplete");
912 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
913 &adj->sub_type.nbr.next_hop)),
914 "adj nbr next-hop ok");
915
Neale Rannsb80c5362016-10-08 13:03:40 +0100916 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
917 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100918 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
919 "adj is complete");
920 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
921 &adj->sub_type.nbr.next_hop)),
922 "adj nbr next-hop ok");
923 ai = fib_entry_get_adj(fei);
924 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
925
926 dpo = fib_entry_contribute_ip_forwarding(fei);
927 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
928 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
929 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +0100930 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
931 tm->hw[0]->sw_if_index),
932 "RPF list for adj-fib contains adj");
933
934 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100935 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +0100936 &nh_12_12_12_12,
937 tm->hw[1]->sw_if_index);
938 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
939 adj = adj_get(ai_12_12_12_12);
940 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
941 "adj is incomplete");
942 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
943 &adj->sub_type.nbr.next_hop)),
944 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +0100945 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
946 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +0100947 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
948 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100949
950 /*
951 * add the adj fib
952 */
953 fei = fib_table_entry_update_one_path(fib_index,
954 &pfx_10_10_10_1_s_32,
955 FIB_SOURCE_ADJ,
956 FIB_ENTRY_FLAG_ATTACHED,
957 FIB_PROTOCOL_IP4,
958 &pfx_10_10_10_1_s_32.fp_addr,
959 tm->hw[0]->sw_if_index,
960 ~0, // invalid fib index
961 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000962 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100963 FIB_ROUTE_PATH_FLAG_NONE);
964 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
965 "Flags set on adj-fib");
966 ai = fib_entry_get_adj(fei);
967 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
968
969 fib_table_entry_path_remove(fib_index,
970 &pfx_11_11_11_11_s_32,
971 FIB_SOURCE_API,
972 FIB_PROTOCOL_IP4,
973 &pfx_10_10_10_1_s_32.fp_addr,
974 tm->hw[0]->sw_if_index,
975 ~0, // invalid fib index
976 1,
977 FIB_ROUTE_PATH_FLAG_NONE);
978
979 eth_addr[5] = 0xb2;
980
981 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100982 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100983 &pfx_10_10_10_2_s_32.fp_addr,
984 tm->hw[0]->sw_if_index);
985 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
986 adj = adj_get(ai_02);
987 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
988 "adj is incomplete");
989 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
990 &adj->sub_type.nbr.next_hop)),
991 "adj nbr next-hop ok");
992
Neale Rannsb80c5362016-10-08 13:03:40 +0100993 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
994 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100995 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
996 "adj is complete");
997 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
998 &adj->sub_type.nbr.next_hop)),
999 "adj nbr next-hop ok");
1000 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1001
1002 fib_table_entry_update_one_path(fib_index,
1003 &pfx_10_10_10_2_s_32,
1004 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00001005 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001006 FIB_PROTOCOL_IP4,
1007 &pfx_10_10_10_2_s_32.fp_addr,
1008 tm->hw[0]->sw_if_index,
1009 ~0, // invalid fib index
1010 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001011 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001012 FIB_ROUTE_PATH_FLAG_NONE);
1013
1014 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1015 ai = fib_entry_get_adj(fei);
1016 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1017
1018 /*
1019 * +2 adj-fibs, and their non-shared path-lists
1020 */
1021 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001022 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001023 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001024 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001025 fib_entry_pool_size());
1026
1027 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001028 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001029 */
1030 fib_prefix_t pfx_1_1_1_1_s_32 = {
1031 .fp_len = 32,
1032 .fp_proto = FIB_PROTOCOL_IP4,
1033 .fp_addr = {
1034 /* 1.1.1.1/32 */
1035 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1036 },
1037 };
1038
1039 fib_table_entry_path_add(fib_index,
1040 &pfx_1_1_1_1_s_32,
1041 FIB_SOURCE_API,
1042 FIB_ENTRY_FLAG_NONE,
1043 FIB_PROTOCOL_IP4,
1044 &nh_10_10_10_1,
1045 tm->hw[0]->sw_if_index,
1046 ~0, // invalid fib index
1047 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001048 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001049 FIB_ROUTE_PATH_FLAG_NONE);
1050 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1051 ai = fib_entry_get_adj(fei);
1052 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1053
1054 /*
1055 * +1 entry and a shared path-list
1056 */
1057 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001058 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001059 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001060 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001061 fib_entry_pool_size());
1062
1063 /* 1.1.2.0/24 */
1064 fib_prefix_t pfx_1_1_2_0_s_24 = {
1065 .fp_len = 24,
1066 .fp_proto = FIB_PROTOCOL_IP4,
1067 .fp_addr = {
1068 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1069 }
1070 };
1071
1072 fib_table_entry_path_add(fib_index,
1073 &pfx_1_1_2_0_s_24,
1074 FIB_SOURCE_API,
1075 FIB_ENTRY_FLAG_NONE,
1076 FIB_PROTOCOL_IP4,
1077 &nh_10_10_10_1,
1078 tm->hw[0]->sw_if_index,
1079 ~0, // invalid fib index
1080 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001081 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001082 FIB_ROUTE_PATH_FLAG_NONE);
1083 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1084 ai = fib_entry_get_adj(fei);
1085 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1086
1087 /*
1088 * +1 entry only
1089 */
1090 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001091 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001092 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001093 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001094 fib_entry_pool_size());
1095
1096 /*
1097 * modify 1.1.2.0/24 to use multipath.
1098 */
1099 fib_table_entry_path_add(fib_index,
1100 &pfx_1_1_2_0_s_24,
1101 FIB_SOURCE_API,
1102 FIB_ENTRY_FLAG_NONE,
1103 FIB_PROTOCOL_IP4,
1104 &nh_10_10_10_2,
1105 tm->hw[0]->sw_if_index,
1106 ~0, // invalid fib index
1107 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001108 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001109 FIB_ROUTE_PATH_FLAG_NONE);
1110 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1111 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001112 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1113 1, tm->hw[0]->sw_if_index),
1114 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001115
1116 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1117 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1118 FIB_TEST((ai_01 == dpo1->dpoi_index),
1119 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1120 ai_01, dpo1->dpoi_index);
1121
1122 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1123 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1124 FIB_TEST((ai_02 == dpo1->dpoi_index),
1125 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1126
1127 /*
1128 * +1 shared-pathlist
1129 */
1130 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001131 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001132 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001133 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001134 fib_entry_pool_size());
1135
1136 /*
1137 * revert the modify
1138 */
1139 fib_table_entry_path_remove(fib_index,
1140 &pfx_1_1_2_0_s_24,
1141 FIB_SOURCE_API,
1142 FIB_PROTOCOL_IP4,
1143 &nh_10_10_10_2,
1144 tm->hw[0]->sw_if_index,
1145 ~0,
1146 1,
1147 FIB_ROUTE_PATH_FLAG_NONE);
1148 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001149 dpo = fib_entry_contribute_ip_forwarding(fei);
1150 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1151 1, tm->hw[0]->sw_if_index),
1152 "RPF list for 1.1.2.0/24 contains one adj");
1153
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001154 ai = fib_entry_get_adj(fei);
1155 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1156
1157 /*
1158 * +1 shared-pathlist
1159 */
1160 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1161 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001162 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001163 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001164 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001165 fib_entry_pool_size());
1166
1167 /*
1168 * Add 2 recursive routes:
1169 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1170 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1171 */
1172 fib_prefix_t bgp_100_pfx = {
1173 .fp_len = 32,
1174 .fp_proto = FIB_PROTOCOL_IP4,
1175 .fp_addr = {
1176 /* 100.100.100.100/32 */
1177 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1178 },
1179 };
1180 /* via 1.1.1.1 */
1181 ip46_address_t nh_1_1_1_1 = {
1182 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1183 };
1184
Neale Ranns3ee44042016-10-03 13:05:48 +01001185 fei = fib_table_entry_path_add(fib_index,
1186 &bgp_100_pfx,
1187 FIB_SOURCE_API,
1188 FIB_ENTRY_FLAG_NONE,
1189 FIB_PROTOCOL_IP4,
1190 &nh_1_1_1_1,
1191 ~0, // no index provided.
1192 fib_index, // nexthop in same fib as route
1193 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001194 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001195 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001196
Neale Ranns3ee44042016-10-03 13:05:48 +01001197 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1198 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1199 tm->hw[0]->sw_if_index),
1200 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001201
1202 /*
1203 * +1 entry and +1 shared-path-list
1204 */
1205 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1206 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001207 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001208 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001209 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001210 fib_entry_pool_size());
1211
1212 fib_prefix_t bgp_101_pfx = {
1213 .fp_len = 32,
1214 .fp_proto = FIB_PROTOCOL_IP4,
1215 .fp_addr = {
1216 /* 100.100.100.101/32 */
1217 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1218 },
1219 };
1220
1221 fib_table_entry_path_add(fib_index,
1222 &bgp_101_pfx,
1223 FIB_SOURCE_API,
1224 FIB_ENTRY_FLAG_NONE,
1225 FIB_PROTOCOL_IP4,
1226 &nh_1_1_1_1,
1227 ~0, // no index provided.
1228 fib_index, // nexthop in same fib as route
1229 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001230 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001231 FIB_ROUTE_PATH_FLAG_NONE);
1232
Neale Ranns3ee44042016-10-03 13:05:48 +01001233 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1234 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1235 tm->hw[0]->sw_if_index),
1236 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001237
1238 /*
1239 * +1 entry, but the recursive path-list is shared.
1240 */
1241 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1242 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001243 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001244 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001245 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001246 fib_entry_pool_size());
1247
1248 /*
1249 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1250 * adjacency through which the route will resovle
1251 */
1252 fib_prefix_t ex_pfx = {
1253 .fp_len = 32,
1254 .fp_proto = FIB_PROTOCOL_IP4,
1255 .fp_addr = {
1256 /* 4.4.4.4/32 */
1257 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1258 },
1259 };
1260
1261 fib_table_entry_special_add(fib_index,
1262 &ex_pfx,
1263 FIB_SOURCE_SPECIAL,
1264 FIB_ENTRY_FLAG_EXCLUSIVE,
1265 locked_ai);
1266 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1267 FIB_TEST((ai == fib_entry_get_adj(fei)),
1268 "Exclusive route links to user adj");
1269
1270 fib_table_entry_special_remove(fib_index,
1271 &ex_pfx,
1272 FIB_SOURCE_SPECIAL);
1273 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1274 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1275 "Exclusive reoute removed");
1276
1277 /*
1278 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1279 * adjacency through which the route will resovle
1280 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001281 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001282
1283 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1284 DPO_PROTO_IP4,
1285 LOOKUP_INPUT_DST_ADDR,
1286 LOOKUP_TABLE_FROM_CONFIG,
1287 &ex_dpo);
1288
1289 fib_table_entry_special_dpo_add(fib_index,
1290 &ex_pfx,
1291 FIB_SOURCE_SPECIAL,
1292 FIB_ENTRY_FLAG_EXCLUSIVE,
1293 &ex_dpo);
1294 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1295 dpo = fib_entry_contribute_ip_forwarding(fei);
1296 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1297 "exclusive remote uses lookup DPO");
1298
Neale Ranns948e00f2016-10-20 13:39:34 +01001299 /*
1300 * update the exclusive to use a different DPO
1301 */
Neale Ranns450cd302016-11-09 17:49:42 +00001302 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001303 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1304 &ex_dpo);
1305 fib_table_entry_special_dpo_update(fib_index,
1306 &ex_pfx,
1307 FIB_SOURCE_SPECIAL,
1308 FIB_ENTRY_FLAG_EXCLUSIVE,
1309 &ex_dpo);
1310 dpo = fib_entry_contribute_ip_forwarding(fei);
1311 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1312 "exclusive remote uses now uses NULL DPO");
1313
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001314 fib_table_entry_special_remove(fib_index,
1315 &ex_pfx,
1316 FIB_SOURCE_SPECIAL);
1317 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1318 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1319 "Exclusive reoute removed");
1320 dpo_reset(&ex_dpo);
1321
1322 /*
1323 * Add a recursive route:
1324 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1325 */
1326 fib_prefix_t bgp_200_pfx = {
1327 .fp_len = 32,
1328 .fp_proto = FIB_PROTOCOL_IP4,
1329 .fp_addr = {
1330 /* 200.200.200.200/32 */
1331 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1332 },
1333 };
1334 /* via 1.1.1.2 */
1335 fib_prefix_t pfx_1_1_1_2_s_32 = {
1336 .fp_len = 32,
1337 .fp_proto = FIB_PROTOCOL_IP4,
1338 .fp_addr = {
1339 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1340 },
1341 };
1342
1343 fib_table_entry_path_add(fib_index,
1344 &bgp_200_pfx,
1345 FIB_SOURCE_API,
1346 FIB_ENTRY_FLAG_NONE,
1347 FIB_PROTOCOL_IP4,
1348 &pfx_1_1_1_2_s_32.fp_addr,
1349 ~0, // no index provided.
1350 fib_index, // nexthop in same fib as route
1351 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001352 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001353 FIB_ROUTE_PATH_FLAG_NONE);
1354
Neale Ranns3ee44042016-10-03 13:05:48 +01001355 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001356
1357 /*
1358 * the adj should be recursive via drop, since the route resolves via
1359 * the default route, which is itself a DROP
1360 */
1361 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1362 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1363 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001364 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1365 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001366
1367 /*
1368 * +2 entry and +1 shared-path-list
1369 */
1370 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1371 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001372 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001373 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001374 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001375 fib_entry_pool_size());
1376
1377 /*
1378 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001379 * The paths are sort by NH first. in this case the the path with greater
1380 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001381 */
1382 fib_prefix_t pfx_1_2_3_4_s_32 = {
1383 .fp_len = 32,
1384 .fp_proto = FIB_PROTOCOL_IP4,
1385 .fp_addr = {
1386 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1387 },
1388 };
1389 fib_table_entry_path_add(fib_index,
1390 &pfx_1_2_3_4_s_32,
1391 FIB_SOURCE_API,
1392 FIB_ENTRY_FLAG_NONE,
1393 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001394 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001395 tm->hw[0]->sw_if_index,
1396 ~0,
1397 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001398 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001399 FIB_ROUTE_PATH_FLAG_NONE);
1400 fei = fib_table_entry_path_add(fib_index,
1401 &pfx_1_2_3_4_s_32,
1402 FIB_SOURCE_API,
1403 FIB_ENTRY_FLAG_NONE,
1404 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001405 &nh_12_12_12_12,
1406 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001407 ~0,
1408 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001409 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001410 FIB_ROUTE_PATH_FLAG_NONE);
1411
1412 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1413 dpo = fib_entry_contribute_ip_forwarding(fei);
1414 lb = load_balance_get(dpo->dpoi_index);
1415 FIB_TEST((lb->lb_n_buckets == 4),
1416 "1.2.3.4/32 LB has %d bucket",
1417 lb->lb_n_buckets);
1418
Neale Ranns3ee44042016-10-03 13:05:48 +01001419 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1420 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1421 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1422 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001423
Neale Ranns3ee44042016-10-03 13:05:48 +01001424 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1425 tm->hw[0]->sw_if_index,
1426 tm->hw[1]->sw_if_index),
1427 "RPF list for 1.2.3.4/32 contains both adjs");
1428
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001429
1430 /*
1431 * Unequal Cost load-balance. 4:1 ratio.
1432 * fits in a 16 bucket LB with ratio 13:3
1433 */
1434 fib_prefix_t pfx_1_2_3_5_s_32 = {
1435 .fp_len = 32,
1436 .fp_proto = FIB_PROTOCOL_IP4,
1437 .fp_addr = {
1438 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1439 },
1440 };
1441 fib_table_entry_path_add(fib_index,
1442 &pfx_1_2_3_5_s_32,
1443 FIB_SOURCE_API,
1444 FIB_ENTRY_FLAG_NONE,
1445 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001446 &nh_12_12_12_12,
1447 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001448 ~0,
1449 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001450 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001451 FIB_ROUTE_PATH_FLAG_NONE);
1452 fei = fib_table_entry_path_add(fib_index,
1453 &pfx_1_2_3_5_s_32,
1454 FIB_SOURCE_API,
1455 FIB_ENTRY_FLAG_NONE,
1456 FIB_PROTOCOL_IP4,
1457 &nh_10_10_10_1,
1458 tm->hw[0]->sw_if_index,
1459 ~0,
1460 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001461 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001462 FIB_ROUTE_PATH_FLAG_NONE);
1463
1464 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1465 dpo = fib_entry_contribute_ip_forwarding(fei);
1466 lb = load_balance_get(dpo->dpoi_index);
1467 FIB_TEST((lb->lb_n_buckets == 16),
1468 "1.2.3.5/32 LB has %d bucket",
1469 lb->lb_n_buckets);
1470
1471 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1472 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1473 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1474 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1475 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1476 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1477 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1478 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1479 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1480 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1481 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1482 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1483 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001484 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1485 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1486 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1487
1488 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1489 tm->hw[0]->sw_if_index,
1490 tm->hw[1]->sw_if_index),
1491 "RPF list for 1.2.3.4/32 contains both adjs");
1492
1493 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001494 * Test UCMP with a large weight skew - this produces load-balance objects with large
1495 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1496 * laso testing the LB in placce modify code when number of buckets is large.
1497 */
1498 fib_prefix_t pfx_6_6_6_6_s_32 = {
1499 .fp_len = 32,
1500 .fp_proto = FIB_PROTOCOL_IP4,
1501 .fp_addr = {
1502 /* 1.1.1.1/32 */
1503 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1504 },
1505 };
1506 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
1507 .type = FT_LB_ADJ,
1508 .adj = {
1509 .adj = ai_01,
1510 },
1511 };
1512 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
1513 .type = FT_LB_ADJ,
1514 .adj = {
1515 .adj = ai_02,
1516 },
1517 };
1518 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1519 .type = FT_LB_ADJ,
1520 .adj = {
1521 .adj = ai_12_12_12_12,
1522 },
1523 };
1524 fib_table_entry_update_one_path(fib_index,
1525 &pfx_6_6_6_6_s_32,
1526 FIB_SOURCE_API,
1527 FIB_ENTRY_FLAG_NONE,
1528 FIB_PROTOCOL_IP4,
1529 &nh_10_10_10_1,
1530 tm->hw[0]->sw_if_index,
1531 ~0, // invalid fib index
1532 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001533 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001534 FIB_ROUTE_PATH_FLAG_NONE);
1535
1536 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1537 FIB_TEST(fib_test_validate_entry(fei,
1538 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1539 1,
1540 &ip_6_6_6_6_o_10_10_10_1),
1541 "6.6.6.6/32 via 10.10.10.1");
1542
1543 fib_table_entry_path_add(fib_index,
1544 &pfx_6_6_6_6_s_32,
1545 FIB_SOURCE_API,
1546 FIB_ENTRY_FLAG_NONE,
1547 FIB_PROTOCOL_IP4,
1548 &nh_10_10_10_2,
1549 tm->hw[0]->sw_if_index,
1550 ~0, // invalid fib index
1551 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001552 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001553 FIB_ROUTE_PATH_FLAG_NONE);
1554
1555 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1556 FIB_TEST(fib_test_validate_entry(fei,
1557 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1558 64,
1559 &ip_6_6_6_6_o_10_10_10_2,
1560 &ip_6_6_6_6_o_10_10_10_2,
1561 &ip_6_6_6_6_o_10_10_10_2,
1562 &ip_6_6_6_6_o_10_10_10_2,
1563 &ip_6_6_6_6_o_10_10_10_2,
1564 &ip_6_6_6_6_o_10_10_10_2,
1565 &ip_6_6_6_6_o_10_10_10_2,
1566 &ip_6_6_6_6_o_10_10_10_2,
1567 &ip_6_6_6_6_o_10_10_10_2,
1568 &ip_6_6_6_6_o_10_10_10_2,
1569 &ip_6_6_6_6_o_10_10_10_2,
1570 &ip_6_6_6_6_o_10_10_10_2,
1571 &ip_6_6_6_6_o_10_10_10_2,
1572 &ip_6_6_6_6_o_10_10_10_2,
1573 &ip_6_6_6_6_o_10_10_10_2,
1574 &ip_6_6_6_6_o_10_10_10_2,
1575 &ip_6_6_6_6_o_10_10_10_2,
1576 &ip_6_6_6_6_o_10_10_10_2,
1577 &ip_6_6_6_6_o_10_10_10_2,
1578 &ip_6_6_6_6_o_10_10_10_2,
1579 &ip_6_6_6_6_o_10_10_10_2,
1580 &ip_6_6_6_6_o_10_10_10_2,
1581 &ip_6_6_6_6_o_10_10_10_2,
1582 &ip_6_6_6_6_o_10_10_10_2,
1583 &ip_6_6_6_6_o_10_10_10_2,
1584 &ip_6_6_6_6_o_10_10_10_2,
1585 &ip_6_6_6_6_o_10_10_10_2,
1586 &ip_6_6_6_6_o_10_10_10_2,
1587 &ip_6_6_6_6_o_10_10_10_2,
1588 &ip_6_6_6_6_o_10_10_10_2,
1589 &ip_6_6_6_6_o_10_10_10_2,
1590 &ip_6_6_6_6_o_10_10_10_2,
1591 &ip_6_6_6_6_o_10_10_10_2,
1592 &ip_6_6_6_6_o_10_10_10_2,
1593 &ip_6_6_6_6_o_10_10_10_2,
1594 &ip_6_6_6_6_o_10_10_10_2,
1595 &ip_6_6_6_6_o_10_10_10_2,
1596 &ip_6_6_6_6_o_10_10_10_2,
1597 &ip_6_6_6_6_o_10_10_10_2,
1598 &ip_6_6_6_6_o_10_10_10_2,
1599 &ip_6_6_6_6_o_10_10_10_2,
1600 &ip_6_6_6_6_o_10_10_10_2,
1601 &ip_6_6_6_6_o_10_10_10_2,
1602 &ip_6_6_6_6_o_10_10_10_2,
1603 &ip_6_6_6_6_o_10_10_10_2,
1604 &ip_6_6_6_6_o_10_10_10_2,
1605 &ip_6_6_6_6_o_10_10_10_2,
1606 &ip_6_6_6_6_o_10_10_10_2,
1607 &ip_6_6_6_6_o_10_10_10_2,
1608 &ip_6_6_6_6_o_10_10_10_2,
1609 &ip_6_6_6_6_o_10_10_10_2,
1610 &ip_6_6_6_6_o_10_10_10_2,
1611 &ip_6_6_6_6_o_10_10_10_2,
1612 &ip_6_6_6_6_o_10_10_10_2,
1613 &ip_6_6_6_6_o_10_10_10_2,
1614 &ip_6_6_6_6_o_10_10_10_2,
1615 &ip_6_6_6_6_o_10_10_10_2,
1616 &ip_6_6_6_6_o_10_10_10_2,
1617 &ip_6_6_6_6_o_10_10_10_2,
1618 &ip_6_6_6_6_o_10_10_10_2,
1619 &ip_6_6_6_6_o_10_10_10_2,
1620 &ip_6_6_6_6_o_10_10_10_2,
1621 &ip_6_6_6_6_o_10_10_10_2,
1622 &ip_6_6_6_6_o_10_10_10_1),
1623 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1624
1625 fib_table_entry_path_add(fib_index,
1626 &pfx_6_6_6_6_s_32,
1627 FIB_SOURCE_API,
1628 FIB_ENTRY_FLAG_NONE,
1629 FIB_PROTOCOL_IP4,
1630 &nh_12_12_12_12,
1631 tm->hw[1]->sw_if_index,
1632 ~0, // invalid fib index
1633 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001634 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001635 FIB_ROUTE_PATH_FLAG_NONE);
1636
1637 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1638 FIB_TEST(fib_test_validate_entry(fei,
1639 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1640 128,
1641 &ip_6_6_6_6_o_10_10_10_1,
1642 &ip_6_6_6_6_o_10_10_10_2,
1643 &ip_6_6_6_6_o_10_10_10_2,
1644 &ip_6_6_6_6_o_10_10_10_2,
1645 &ip_6_6_6_6_o_10_10_10_2,
1646 &ip_6_6_6_6_o_10_10_10_2,
1647 &ip_6_6_6_6_o_10_10_10_2,
1648 &ip_6_6_6_6_o_10_10_10_2,
1649 &ip_6_6_6_6_o_10_10_10_2,
1650 &ip_6_6_6_6_o_10_10_10_2,
1651 &ip_6_6_6_6_o_10_10_10_2,
1652 &ip_6_6_6_6_o_10_10_10_2,
1653 &ip_6_6_6_6_o_10_10_10_2,
1654 &ip_6_6_6_6_o_10_10_10_2,
1655 &ip_6_6_6_6_o_10_10_10_2,
1656 &ip_6_6_6_6_o_10_10_10_2,
1657 &ip_6_6_6_6_o_10_10_10_2,
1658 &ip_6_6_6_6_o_10_10_10_2,
1659 &ip_6_6_6_6_o_10_10_10_2,
1660 &ip_6_6_6_6_o_10_10_10_2,
1661 &ip_6_6_6_6_o_10_10_10_2,
1662 &ip_6_6_6_6_o_10_10_10_2,
1663 &ip_6_6_6_6_o_10_10_10_2,
1664 &ip_6_6_6_6_o_10_10_10_2,
1665 &ip_6_6_6_6_o_10_10_10_2,
1666 &ip_6_6_6_6_o_10_10_10_2,
1667 &ip_6_6_6_6_o_10_10_10_2,
1668 &ip_6_6_6_6_o_10_10_10_2,
1669 &ip_6_6_6_6_o_10_10_10_2,
1670 &ip_6_6_6_6_o_10_10_10_2,
1671 &ip_6_6_6_6_o_10_10_10_2,
1672 &ip_6_6_6_6_o_10_10_10_2,
1673 &ip_6_6_6_6_o_10_10_10_2,
1674 &ip_6_6_6_6_o_10_10_10_2,
1675 &ip_6_6_6_6_o_10_10_10_2,
1676 &ip_6_6_6_6_o_10_10_10_2,
1677 &ip_6_6_6_6_o_10_10_10_2,
1678 &ip_6_6_6_6_o_10_10_10_2,
1679 &ip_6_6_6_6_o_10_10_10_2,
1680 &ip_6_6_6_6_o_10_10_10_2,
1681 &ip_6_6_6_6_o_10_10_10_2,
1682 &ip_6_6_6_6_o_10_10_10_2,
1683 &ip_6_6_6_6_o_10_10_10_2,
1684 &ip_6_6_6_6_o_10_10_10_2,
1685 &ip_6_6_6_6_o_10_10_10_2,
1686 &ip_6_6_6_6_o_10_10_10_2,
1687 &ip_6_6_6_6_o_10_10_10_2,
1688 &ip_6_6_6_6_o_10_10_10_2,
1689 &ip_6_6_6_6_o_10_10_10_2,
1690 &ip_6_6_6_6_o_10_10_10_2,
1691 &ip_6_6_6_6_o_10_10_10_2,
1692 &ip_6_6_6_6_o_10_10_10_2,
1693 &ip_6_6_6_6_o_10_10_10_2,
1694 &ip_6_6_6_6_o_10_10_10_2,
1695 &ip_6_6_6_6_o_10_10_10_2,
1696 &ip_6_6_6_6_o_10_10_10_2,
1697 &ip_6_6_6_6_o_10_10_10_2,
1698 &ip_6_6_6_6_o_10_10_10_2,
1699 &ip_6_6_6_6_o_10_10_10_2,
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_12_12_12_12,
1707 &ip_6_6_6_6_o_12_12_12_12,
1708 &ip_6_6_6_6_o_12_12_12_12,
1709 &ip_6_6_6_6_o_12_12_12_12,
1710 &ip_6_6_6_6_o_12_12_12_12,
1711 &ip_6_6_6_6_o_12_12_12_12,
1712 &ip_6_6_6_6_o_12_12_12_12,
1713 &ip_6_6_6_6_o_12_12_12_12,
1714 &ip_6_6_6_6_o_12_12_12_12,
1715 &ip_6_6_6_6_o_12_12_12_12,
1716 &ip_6_6_6_6_o_12_12_12_12,
1717 &ip_6_6_6_6_o_12_12_12_12,
1718 &ip_6_6_6_6_o_12_12_12_12,
1719 &ip_6_6_6_6_o_12_12_12_12,
1720 &ip_6_6_6_6_o_12_12_12_12,
1721 &ip_6_6_6_6_o_12_12_12_12,
1722 &ip_6_6_6_6_o_12_12_12_12,
1723 &ip_6_6_6_6_o_12_12_12_12,
1724 &ip_6_6_6_6_o_12_12_12_12,
1725 &ip_6_6_6_6_o_12_12_12_12,
1726 &ip_6_6_6_6_o_12_12_12_12,
1727 &ip_6_6_6_6_o_12_12_12_12,
1728 &ip_6_6_6_6_o_12_12_12_12,
1729 &ip_6_6_6_6_o_12_12_12_12,
1730 &ip_6_6_6_6_o_12_12_12_12,
1731 &ip_6_6_6_6_o_12_12_12_12,
1732 &ip_6_6_6_6_o_12_12_12_12,
1733 &ip_6_6_6_6_o_12_12_12_12,
1734 &ip_6_6_6_6_o_12_12_12_12,
1735 &ip_6_6_6_6_o_12_12_12_12,
1736 &ip_6_6_6_6_o_12_12_12_12,
1737 &ip_6_6_6_6_o_12_12_12_12,
1738 &ip_6_6_6_6_o_12_12_12_12,
1739 &ip_6_6_6_6_o_12_12_12_12,
1740 &ip_6_6_6_6_o_12_12_12_12,
1741 &ip_6_6_6_6_o_12_12_12_12,
1742 &ip_6_6_6_6_o_12_12_12_12,
1743 &ip_6_6_6_6_o_12_12_12_12,
1744 &ip_6_6_6_6_o_12_12_12_12,
1745 &ip_6_6_6_6_o_12_12_12_12,
1746 &ip_6_6_6_6_o_12_12_12_12,
1747 &ip_6_6_6_6_o_12_12_12_12,
1748 &ip_6_6_6_6_o_12_12_12_12,
1749 &ip_6_6_6_6_o_12_12_12_12,
1750 &ip_6_6_6_6_o_12_12_12_12,
1751 &ip_6_6_6_6_o_12_12_12_12,
1752 &ip_6_6_6_6_o_12_12_12_12,
1753 &ip_6_6_6_6_o_12_12_12_12,
1754 &ip_6_6_6_6_o_12_12_12_12,
1755 &ip_6_6_6_6_o_12_12_12_12,
1756 &ip_6_6_6_6_o_12_12_12_12,
1757 &ip_6_6_6_6_o_12_12_12_12,
1758 &ip_6_6_6_6_o_12_12_12_12,
1759 &ip_6_6_6_6_o_12_12_12_12,
1760 &ip_6_6_6_6_o_12_12_12_12,
1761 &ip_6_6_6_6_o_12_12_12_12,
1762 &ip_6_6_6_6_o_12_12_12_12,
1763 &ip_6_6_6_6_o_12_12_12_12,
1764 &ip_6_6_6_6_o_12_12_12_12,
1765 &ip_6_6_6_6_o_12_12_12_12,
1766 &ip_6_6_6_6_o_12_12_12_12,
1767 &ip_6_6_6_6_o_12_12_12_12,
1768 &ip_6_6_6_6_o_12_12_12_12),
1769 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1770
1771 fib_table_entry_path_remove(fib_index,
1772 &pfx_6_6_6_6_s_32,
1773 FIB_SOURCE_API,
1774 FIB_PROTOCOL_IP4,
1775 &nh_12_12_12_12,
1776 tm->hw[1]->sw_if_index,
1777 ~0, // invalid fib index
1778 100,
1779 FIB_ROUTE_PATH_FLAG_NONE);
1780
1781 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1782 FIB_TEST(fib_test_validate_entry(fei,
1783 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1784 64,
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_10_10_10_2,
1848 &ip_6_6_6_6_o_10_10_10_1),
1849 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1850
1851 fib_table_entry_path_remove(fib_index,
1852 &pfx_6_6_6_6_s_32,
1853 FIB_SOURCE_API,
1854 FIB_PROTOCOL_IP4,
1855 &nh_10_10_10_2,
1856 tm->hw[0]->sw_if_index,
1857 ~0, // invalid fib index
1858 100,
1859 FIB_ROUTE_PATH_FLAG_NONE);
1860
1861 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1862 FIB_TEST(fib_test_validate_entry(fei,
1863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1864 1,
1865 &ip_6_6_6_6_o_10_10_10_1),
1866 "6.6.6.6/32 via 10.10.10.1");
1867
1868 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1869
1870 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001871 * A recursive via the two unequal cost entries
1872 */
1873 fib_prefix_t bgp_44_s_32 = {
1874 .fp_len = 32,
1875 .fp_proto = FIB_PROTOCOL_IP4,
1876 .fp_addr = {
1877 /* 200.200.200.201/32 */
1878 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1879 },
1880 };
1881 fei = fib_table_entry_path_add(fib_index,
1882 &bgp_44_s_32,
1883 FIB_SOURCE_API,
1884 FIB_ENTRY_FLAG_NONE,
1885 FIB_PROTOCOL_IP4,
1886 &pfx_1_2_3_4_s_32.fp_addr,
1887 ~0,
1888 fib_index,
1889 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001890 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001891 FIB_ROUTE_PATH_FLAG_NONE);
1892 fei = fib_table_entry_path_add(fib_index,
1893 &bgp_44_s_32,
1894 FIB_SOURCE_API,
1895 FIB_ENTRY_FLAG_NONE,
1896 FIB_PROTOCOL_IP4,
1897 &pfx_1_2_3_5_s_32.fp_addr,
1898 ~0,
1899 fib_index,
1900 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001901 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001902 FIB_ROUTE_PATH_FLAG_NONE);
1903
1904 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
1905 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
1906 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1907 tm->hw[0]->sw_if_index,
1908 tm->hw[1]->sw_if_index),
1909 "RPF list for 1.2.3.4/32 contains both adjs");
1910
1911 /*
1912 * test the uRPF check functions
1913 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001914 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01001915 index_t urpfi;
1916
1917 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
1918 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
1919
1920 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
1921 "uRPF check for 68.68.68.68/32 on %d OK",
1922 tm->hw[0]->sw_if_index);
1923 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
1924 "uRPF check for 68.68.68.68/32 on %d OK",
1925 tm->hw[1]->sw_if_index);
1926 FIB_TEST(!fib_urpf_check(urpfi, 99),
1927 "uRPF check for 68.68.68.68/32 on 99 not-OK",
1928 99);
1929 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001930
1931 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01001932 &bgp_44_s_32,
1933 FIB_SOURCE_API);
1934 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001935 &pfx_1_2_3_5_s_32,
1936 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01001937 fib_table_entry_delete(fib_index,
1938 &pfx_1_2_3_4_s_32,
1939 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001940
1941 /*
1942 * Add a recursive route:
1943 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
1944 */
1945 fib_prefix_t bgp_201_pfx = {
1946 .fp_len = 32,
1947 .fp_proto = FIB_PROTOCOL_IP4,
1948 .fp_addr = {
1949 /* 200.200.200.201/32 */
1950 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
1951 },
1952 };
1953 /* via 1.1.1.200 */
1954 fib_prefix_t pfx_1_1_1_200_s_32 = {
1955 .fp_len = 32,
1956 .fp_proto = FIB_PROTOCOL_IP4,
1957 .fp_addr = {
1958 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
1959 },
1960 };
1961
1962 fib_table_entry_path_add(fib_index,
1963 &bgp_201_pfx,
1964 FIB_SOURCE_API,
1965 FIB_ENTRY_FLAG_NONE,
1966 FIB_PROTOCOL_IP4,
1967 &pfx_1_1_1_200_s_32.fp_addr,
1968 ~0, // no index provided.
1969 fib_index, // nexthop in same fib as route
1970 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001971 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001972 FIB_ROUTE_PATH_FLAG_NONE);
1973
Neale Ranns3ee44042016-10-03 13:05:48 +01001974 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001975
1976 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
1977 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1978 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01001979 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1980 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001981
1982 /*
1983 * +2 entry (BGP & RR) and +1 shared-path-list
1984 */
1985 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
1986 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001987 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001988 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001989 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001990 fib_entry_pool_size());
1991
1992 /*
1993 * insert a route that covers the missing 1.1.1.2/32. we epxect
1994 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
1995 */
1996 fib_prefix_t pfx_1_1_1_0_s_24 = {
1997 .fp_len = 24,
1998 .fp_proto = FIB_PROTOCOL_IP4,
1999 .fp_addr = {
2000 /* 1.1.1.0/24 */
2001 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2002 },
2003 };
2004
2005 fib_table_entry_path_add(fib_index,
2006 &pfx_1_1_1_0_s_24,
2007 FIB_SOURCE_API,
2008 FIB_ENTRY_FLAG_NONE,
2009 FIB_PROTOCOL_IP4,
2010 &nh_10_10_10_1,
2011 tm->hw[0]->sw_if_index,
2012 ~0, // invalid fib index
2013 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002014 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002015 FIB_ROUTE_PATH_FLAG_NONE);
2016 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2017 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2018 ai = fib_entry_get_adj(fei);
2019 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2020 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2021 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2022 ai = fib_entry_get_adj(fei);
2023 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2024 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2025 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2026 ai = fib_entry_get_adj(fei);
2027 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2028
2029 /*
2030 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2031 */
2032 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2033 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002034 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002035 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002036 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002037 fib_entry_pool_size());
2038
2039 /*
2040 * the recursive adj for 200.200.200.200 should be updated.
2041 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002042 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2043 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2044 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2045 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2046 tm->hw[0]->sw_if_index),
2047 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002048
2049 /*
2050 * insert a more specific route than 1.1.1.0/24 that also covers the
2051 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2052 * 200.200.200.200 to resolve through it.
2053 */
2054 fib_prefix_t pfx_1_1_1_0_s_28 = {
2055 .fp_len = 28,
2056 .fp_proto = FIB_PROTOCOL_IP4,
2057 .fp_addr = {
2058 /* 1.1.1.0/24 */
2059 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2060 },
2061 };
2062
2063 fib_table_entry_path_add(fib_index,
2064 &pfx_1_1_1_0_s_28,
2065 FIB_SOURCE_API,
2066 FIB_ENTRY_FLAG_NONE,
2067 FIB_PROTOCOL_IP4,
2068 &nh_10_10_10_2,
2069 tm->hw[0]->sw_if_index,
2070 ~0, // invalid fib index
2071 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002072 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002073 FIB_ROUTE_PATH_FLAG_NONE);
2074 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2075 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2076 ai = fib_entry_get_adj(fei);
2077 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2078
2079 /*
2080 * +1 entry. +1 shared path-list
2081 */
2082 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2083 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002084 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002085 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002086 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002087 fib_entry_pool_size());
2088
2089 /*
2090 * the recursive adj for 200.200.200.200 should be updated.
2091 * 200.200.200.201 remains unchanged.
2092 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002093 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2094 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002095
2096 /*
2097 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2098 */
2099 fib_table_entry_path_remove(fib_index,
2100 &pfx_1_1_1_0_s_28,
2101 FIB_SOURCE_API,
2102 FIB_PROTOCOL_IP4,
2103 &nh_10_10_10_2,
2104 tm->hw[0]->sw_if_index,
2105 ~0,
2106 1,
2107 FIB_ROUTE_PATH_FLAG_NONE);
2108 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2109 FIB_NODE_INDEX_INVALID),
2110 "1.1.1.0/28 removed");
2111 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2112 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2113 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002114 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2115 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002116
2117 /*
2118 * -1 entry. -1 shared path-list
2119 */
2120 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2121 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002122 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002123 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002124 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002125 fib_entry_pool_size());
2126
2127 /*
2128 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2129 */
2130 fib_table_entry_path_remove(fib_index,
2131 &pfx_1_1_1_0_s_24,
2132 FIB_SOURCE_API,
2133 FIB_PROTOCOL_IP4,
2134 &nh_10_10_10_1,
2135 tm->hw[0]->sw_if_index,
2136 ~0,
2137 1,
2138 FIB_ROUTE_PATH_FLAG_NONE);
2139 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2140 FIB_NODE_INDEX_INVALID),
2141 "1.1.1.0/24 removed");
2142
2143 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2144 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2145 "1.1.1.2/32 route is DROP");
2146 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2147 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2148 "1.1.1.200/32 route is DROP");
2149
Neale Ranns3ee44042016-10-03 13:05:48 +01002150 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2151 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002152
2153 /*
2154 * -1 entry
2155 */
2156 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2157 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002158 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002159 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002160 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002161 fib_entry_pool_size());
2162
2163 /*
2164 * insert the missing 1.1.1.2/32
2165 */
2166 fei = fib_table_entry_path_add(fib_index,
2167 &pfx_1_1_1_2_s_32,
2168 FIB_SOURCE_API,
2169 FIB_ENTRY_FLAG_NONE,
2170 FIB_PROTOCOL_IP4,
2171 &nh_10_10_10_1,
2172 tm->hw[0]->sw_if_index,
2173 ~0, // invalid fib index
2174 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002175 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002176 FIB_ROUTE_PATH_FLAG_NONE);
2177 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2178 ai = fib_entry_get_adj(fei);
2179 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2180
Neale Ranns3ee44042016-10-03 13:05:48 +01002181 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2182 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002183
2184 /*
2185 * no change. 1.1.1.2/32 was already there RR sourced.
2186 */
2187 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2188 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002189 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002190 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002191 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002192 fib_entry_pool_size());
2193
2194 /*
2195 * remove 200.200.200.201/32 which does not have a valid via FIB
2196 */
2197 fib_table_entry_path_remove(fib_index,
2198 &bgp_201_pfx,
2199 FIB_SOURCE_API,
2200 FIB_PROTOCOL_IP4,
2201 &pfx_1_1_1_200_s_32.fp_addr,
2202 ~0, // no index provided.
2203 fib_index,
2204 1,
2205 FIB_ROUTE_PATH_FLAG_NONE);
2206
2207 /*
2208 * -2 entries (BGP and RR). -1 shared path-list;
2209 */
2210 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2211 FIB_NODE_INDEX_INVALID),
2212 "200.200.200.201/32 removed");
2213 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2214 FIB_NODE_INDEX_INVALID),
2215 "1.1.1.200/32 removed");
2216
2217 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2218 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002219 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002220 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002221 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002222 fib_entry_pool_size());
2223
2224 /*
2225 * remove 200.200.200.200/32 which does have a valid via FIB
2226 */
2227 fib_table_entry_path_remove(fib_index,
2228 &bgp_200_pfx,
2229 FIB_SOURCE_API,
2230 FIB_PROTOCOL_IP4,
2231 &pfx_1_1_1_2_s_32.fp_addr,
2232 ~0, // no index provided.
2233 fib_index,
2234 1,
2235 FIB_ROUTE_PATH_FLAG_NONE);
2236
2237 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2238 FIB_NODE_INDEX_INVALID),
2239 "200.200.200.200/32 removed");
2240 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2241 FIB_NODE_INDEX_INVALID),
2242 "1.1.1.2/32 still present");
2243
2244 /*
2245 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2246 */
2247 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2248 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002249 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002250 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002251 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002252 fib_entry_pool_size());
2253
2254 /*
2255 * A recursive prefix that has a 2 path load-balance.
2256 * It also shares a next-hop with other BGP prefixes and hence
2257 * test the ref counting of RR sourced prefixes and 2 level LB.
2258 */
2259 const fib_prefix_t bgp_102 = {
2260 .fp_len = 32,
2261 .fp_proto = FIB_PROTOCOL_IP4,
2262 .fp_addr = {
2263 /* 100.100.100.101/32 */
2264 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2265 },
2266 };
2267 fib_table_entry_path_add(fib_index,
2268 &bgp_102,
2269 FIB_SOURCE_API,
2270 FIB_ENTRY_FLAG_NONE,
2271 FIB_PROTOCOL_IP4,
2272 &pfx_1_1_1_1_s_32.fp_addr,
2273 ~0, // no index provided.
2274 fib_index, // same as route
2275 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002276 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002277 FIB_ROUTE_PATH_FLAG_NONE);
2278 fib_table_entry_path_add(fib_index,
2279 &bgp_102,
2280 FIB_SOURCE_API,
2281 FIB_ENTRY_FLAG_NONE,
2282 FIB_PROTOCOL_IP4,
2283 &pfx_1_1_1_2_s_32.fp_addr,
2284 ~0, // no index provided.
2285 fib_index, // same as route's FIB
2286 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002287 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002288 FIB_ROUTE_PATH_FLAG_NONE);
2289 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2290 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2291 dpo = fib_entry_contribute_ip_forwarding(fei);
2292
2293 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2294 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2295 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2296 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2297
2298 lb = load_balance_get(dpo->dpoi_index);
2299 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2300 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2301 "First via 10.10.10.1");
2302 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2303 "Second via 10.10.10.1");
2304
2305 fib_table_entry_path_remove(fib_index,
2306 &bgp_102,
2307 FIB_SOURCE_API,
2308 FIB_PROTOCOL_IP4,
2309 &pfx_1_1_1_1_s_32.fp_addr,
2310 ~0, // no index provided.
2311 fib_index, // same as route's FIB
2312 1,
2313 FIB_ROUTE_PATH_FLAG_NONE);
2314 fib_table_entry_path_remove(fib_index,
2315 &bgp_102,
2316 FIB_SOURCE_API,
2317 FIB_PROTOCOL_IP4,
2318 &pfx_1_1_1_2_s_32.fp_addr,
2319 ~0, // no index provided.
2320 fib_index, // same as route's FIB
2321 1,
2322 FIB_ROUTE_PATH_FLAG_NONE);
2323 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2324 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2325
2326 /*
2327 * remove the remaining recursives
2328 */
2329 fib_table_entry_path_remove(fib_index,
2330 &bgp_100_pfx,
2331 FIB_SOURCE_API,
2332 FIB_PROTOCOL_IP4,
2333 &pfx_1_1_1_1_s_32.fp_addr,
2334 ~0, // no index provided.
2335 fib_index, // same as route's FIB
2336 1,
2337 FIB_ROUTE_PATH_FLAG_NONE);
2338 fib_table_entry_path_remove(fib_index,
2339 &bgp_101_pfx,
2340 FIB_SOURCE_API,
2341 FIB_PROTOCOL_IP4,
2342 &pfx_1_1_1_1_s_32.fp_addr,
2343 ~0, // no index provided.
2344 fib_index, // same as route's FIB
2345 1,
2346 FIB_ROUTE_PATH_FLAG_NONE);
2347 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2348 FIB_NODE_INDEX_INVALID),
2349 "100.100.100.100/32 removed");
2350 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2351 FIB_NODE_INDEX_INVALID),
2352 "100.100.100.101/32 removed");
2353
2354 /*
2355 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2356 */
2357 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2358 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002359 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002360 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002361 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002362 fib_entry_pool_size());
2363
2364 /*
2365 * Add a recursive route via a connected cover, using an adj-fib that does exist
2366 */
2367 fib_table_entry_path_add(fib_index,
2368 &bgp_200_pfx,
2369 FIB_SOURCE_API,
2370 FIB_ENTRY_FLAG_NONE,
2371 FIB_PROTOCOL_IP4,
2372 &nh_10_10_10_1,
2373 ~0, // no index provided.
2374 fib_index, // Same as route's FIB
2375 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002376 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002377 FIB_ROUTE_PATH_FLAG_NONE);
2378
2379 /*
2380 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2381 */
2382 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2383 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002384 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002385 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002386 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002387 fib_entry_pool_size());
2388
2389 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2390 dpo = fib_entry_contribute_ip_forwarding(fei);
2391
2392 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2393 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2394
2395 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2396 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2397
2398 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2399 "Flags set on RR via existing attached");
2400
2401 /*
2402 * Add a recursive route via a connected cover, using and adj-fib that does
2403 * not exist
2404 */
2405 ip46_address_t nh_10_10_10_3 = {
2406 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2407 };
2408 fib_prefix_t pfx_10_10_10_3 = {
2409 .fp_len = 32,
2410 .fp_proto = FIB_PROTOCOL_IP4,
2411 .fp_addr = nh_10_10_10_3,
2412 };
2413
2414 fib_table_entry_path_add(fib_index,
2415 &bgp_201_pfx,
2416 FIB_SOURCE_API,
2417 FIB_ENTRY_FLAG_NONE,
2418 FIB_PROTOCOL_IP4,
2419 &nh_10_10_10_3,
2420 ~0, // no index provided.
2421 fib_index,
2422 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002423 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002424 FIB_ROUTE_PATH_FLAG_NONE);
2425
2426 /*
2427 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2428 * one unshared non-recursive via 10.10.10.3
2429 */
2430 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2431 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002432 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002433 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002434 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002435 fib_entry_pool_size());
2436
2437 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002438 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002439 &nh_10_10_10_3,
2440 tm->hw[0]->sw_if_index);
2441
2442 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2443 dpo = fib_entry_contribute_ip_forwarding(fei);
2444 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2445 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2446
2447 ai = fib_entry_get_adj(fei);
2448 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2449 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2450 fib_entry_get_flags(fei)),
2451 "Flags set on RR via non-existing attached");
2452
2453 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2454 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2455
2456 adj_unlock(ai_03);
2457
2458 /*
2459 * remove the recursives
2460 */
2461 fib_table_entry_path_remove(fib_index,
2462 &bgp_200_pfx,
2463 FIB_SOURCE_API,
2464 FIB_PROTOCOL_IP4,
2465 &nh_10_10_10_1,
2466 ~0, // no index provided.
2467 fib_index, // same as route's FIB
2468 1,
2469 FIB_ROUTE_PATH_FLAG_NONE);
2470 fib_table_entry_path_remove(fib_index,
2471 &bgp_201_pfx,
2472 FIB_SOURCE_API,
2473 FIB_PROTOCOL_IP4,
2474 &nh_10_10_10_3,
2475 ~0, // no index provided.
2476 fib_index, // same as route's FIB
2477 1,
2478 FIB_ROUTE_PATH_FLAG_NONE);
2479
2480 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2481 FIB_NODE_INDEX_INVALID),
2482 "200.200.200.201/32 removed");
2483 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2484 FIB_NODE_INDEX_INVALID),
2485 "200.200.200.200/32 removed");
2486 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2487 FIB_NODE_INDEX_INVALID),
2488 "10.10.10.3/32 removed");
2489
2490 /*
2491 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2492 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2493 */
2494 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2495 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002496 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002497 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002498 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002499 fib_entry_pool_size());
2500
2501
2502 /*
2503 * RECURSION LOOPS
2504 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2505 */
2506 fib_prefix_t pfx_5_5_5_5_s_32 = {
2507 .fp_len = 32,
2508 .fp_proto = FIB_PROTOCOL_IP4,
2509 .fp_addr = {
2510 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2511 },
2512 };
2513 fib_prefix_t pfx_5_5_5_6_s_32 = {
2514 .fp_len = 32,
2515 .fp_proto = FIB_PROTOCOL_IP4,
2516 .fp_addr = {
2517 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2518 },
2519 };
2520 fib_prefix_t pfx_5_5_5_7_s_32 = {
2521 .fp_len = 32,
2522 .fp_proto = FIB_PROTOCOL_IP4,
2523 .fp_addr = {
2524 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2525 },
2526 };
2527
2528 fib_table_entry_path_add(fib_index,
2529 &pfx_5_5_5_5_s_32,
2530 FIB_SOURCE_API,
2531 FIB_ENTRY_FLAG_NONE,
2532 FIB_PROTOCOL_IP4,
2533 &pfx_5_5_5_6_s_32.fp_addr,
2534 ~0, // no index provided.
2535 fib_index,
2536 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002537 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002538 FIB_ROUTE_PATH_FLAG_NONE);
2539 fib_table_entry_path_add(fib_index,
2540 &pfx_5_5_5_6_s_32,
2541 FIB_SOURCE_API,
2542 FIB_ENTRY_FLAG_NONE,
2543 FIB_PROTOCOL_IP4,
2544 &pfx_5_5_5_7_s_32.fp_addr,
2545 ~0, // no index provided.
2546 fib_index,
2547 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002548 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002549 FIB_ROUTE_PATH_FLAG_NONE);
2550 fib_table_entry_path_add(fib_index,
2551 &pfx_5_5_5_7_s_32,
2552 FIB_SOURCE_API,
2553 FIB_ENTRY_FLAG_NONE,
2554 FIB_PROTOCOL_IP4,
2555 &pfx_5_5_5_5_s_32.fp_addr,
2556 ~0, // no index provided.
2557 fib_index,
2558 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002559 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002560 FIB_ROUTE_PATH_FLAG_NONE);
2561 /*
2562 * +3 entries, +3 shared path-list
2563 */
2564 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2565 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002566 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002567 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002568 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002569 fib_entry_pool_size());
2570
2571 /*
2572 * All the entries have only looped paths, so they are all drop
2573 */
2574 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2575 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2576 "LB for 5.5.5.7/32 is via adj for DROP");
2577 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2578 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2579 "LB for 5.5.5.5/32 is via adj for DROP");
2580 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2581 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2582 "LB for 5.5.5.6/32 is via adj for DROP");
2583
2584 /*
2585 * provide 5.5.5.6/32 with alternate path.
2586 * this will allow only 5.5.5.6/32 to forward with this path, the others
2587 * are still drop since the loop is still present.
2588 */
2589 fib_table_entry_path_add(fib_index,
2590 &pfx_5_5_5_6_s_32,
2591 FIB_SOURCE_API,
2592 FIB_ENTRY_FLAG_NONE,
2593 FIB_PROTOCOL_IP4,
2594 &nh_10_10_10_1,
2595 tm->hw[0]->sw_if_index,
2596 ~0,
2597 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002598 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002599 FIB_ROUTE_PATH_FLAG_NONE);
2600
2601
2602 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2603 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2604
2605 lb = load_balance_get(dpo1->dpoi_index);
2606 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2607
2608 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2609 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2610 FIB_TEST((ai_01 == dpo2->dpoi_index),
2611 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2612
2613 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2614 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2615 "LB for 5.5.5.7/32 is via adj for DROP");
2616 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2617 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2618 "LB for 5.5.5.5/32 is via adj for DROP");
2619
2620 /*
2621 * remove the alternate path for 5.5.5.6/32
2622 * back to all drop
2623 */
2624 fib_table_entry_path_remove(fib_index,
2625 &pfx_5_5_5_6_s_32,
2626 FIB_SOURCE_API,
2627 FIB_PROTOCOL_IP4,
2628 &nh_10_10_10_1,
2629 tm->hw[0]->sw_if_index,
2630 ~0,
2631 1,
2632 FIB_ROUTE_PATH_FLAG_NONE);
2633
2634 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2635 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2636 "LB for 5.5.5.7/32 is via adj for DROP");
2637 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2638 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2639 "LB for 5.5.5.5/32 is via adj for DROP");
2640 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2641 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2642 "LB for 5.5.5.6/32 is via adj for DROP");
2643
2644 /*
2645 * break the loop by giving 5.5.5.5/32 a new set of paths
2646 * expect all to forward via this new path.
2647 */
2648 fib_table_entry_update_one_path(fib_index,
2649 &pfx_5_5_5_5_s_32,
2650 FIB_SOURCE_API,
2651 FIB_ENTRY_FLAG_NONE,
2652 FIB_PROTOCOL_IP4,
2653 &nh_10_10_10_1,
2654 tm->hw[0]->sw_if_index,
2655 ~0, // invalid fib index
2656 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002657 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002658 FIB_ROUTE_PATH_FLAG_NONE);
2659
2660 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2661 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2662 lb = load_balance_get(dpo1->dpoi_index);
2663 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2664
2665 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2666 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2667 FIB_TEST((ai_01 == dpo2->dpoi_index),
2668 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2669
2670 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2671 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2672
2673 lb = load_balance_get(dpo2->dpoi_index);
2674 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2675 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2676 "5.5.5.5.7 via 5.5.5.5");
2677
2678 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2679 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2680
2681 lb = load_balance_get(dpo1->dpoi_index);
2682 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2683 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2684 "5.5.5.5.6 via 5.5.5.7");
2685
2686 /*
2687 * revert back to the loop. so we can remove the prefixes with
2688 * the loop intact
2689 */
2690 fib_table_entry_update_one_path(fib_index,
2691 &pfx_5_5_5_5_s_32,
2692 FIB_SOURCE_API,
2693 FIB_ENTRY_FLAG_NONE,
2694 FIB_PROTOCOL_IP4,
2695 &pfx_5_5_5_6_s_32.fp_addr,
2696 ~0, // no index provided.
2697 fib_index,
2698 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002699 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002700 FIB_ROUTE_PATH_FLAG_NONE);
2701
2702 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2703 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2704 "LB for 5.5.5.7/32 is via adj for DROP");
2705 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2706 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2707 "LB for 5.5.5.5/32 is via adj for DROP");
2708 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2709 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2710 "LB for 5.5.5.6/32 is via adj for DROP");
2711
2712 /*
2713 * remove all the 5.5.5.x/32 prefixes
2714 */
2715 fib_table_entry_path_remove(fib_index,
2716 &pfx_5_5_5_5_s_32,
2717 FIB_SOURCE_API,
2718 FIB_PROTOCOL_IP4,
2719 &pfx_5_5_5_6_s_32.fp_addr,
2720 ~0, // no index provided.
2721 fib_index, // same as route's FIB
2722 1,
2723 FIB_ROUTE_PATH_FLAG_NONE);
2724 fib_table_entry_path_remove(fib_index,
2725 &pfx_5_5_5_6_s_32,
2726 FIB_SOURCE_API,
2727 FIB_PROTOCOL_IP4,
2728 &pfx_5_5_5_7_s_32.fp_addr,
2729 ~0, // no index provided.
2730 fib_index, // same as route's FIB
2731 1,
2732 FIB_ROUTE_PATH_FLAG_NONE);
2733 fib_table_entry_path_remove(fib_index,
2734 &pfx_5_5_5_7_s_32,
2735 FIB_SOURCE_API,
2736 FIB_PROTOCOL_IP4,
2737 &pfx_5_5_5_5_s_32.fp_addr,
2738 ~0, // no index provided.
2739 fib_index, // same as route's FIB
2740 1,
2741 FIB_ROUTE_PATH_FLAG_NONE);
2742 fib_table_entry_path_remove(fib_index,
2743 &pfx_5_5_5_6_s_32,
2744 FIB_SOURCE_API,
2745 FIB_PROTOCOL_IP4,
2746 &nh_10_10_10_2,
2747 ~0, // no index provided.
2748 fib_index, // same as route's FIB
2749 1,
2750 FIB_ROUTE_PATH_FLAG_NONE);
2751
2752 /*
2753 * -3 entries, -3 shared path-list
2754 */
2755 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2756 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002757 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002758 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002759 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002760 fib_entry_pool_size());
2761
2762 /*
2763 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2764 */
2765 fib_table_entry_path_add(fib_index,
2766 &pfx_5_5_5_6_s_32,
2767 FIB_SOURCE_API,
2768 FIB_ENTRY_FLAG_NONE,
2769 FIB_PROTOCOL_IP4,
2770 &pfx_5_5_5_6_s_32.fp_addr,
2771 ~0, // no index provided.
2772 fib_index,
2773 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002774 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002775 FIB_ROUTE_PATH_FLAG_NONE);
2776 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2777 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2778 "1-level 5.5.5.6/32 loop is via adj for DROP");
2779
2780 fib_table_entry_path_remove(fib_index,
2781 &pfx_5_5_5_6_s_32,
2782 FIB_SOURCE_API,
2783 FIB_PROTOCOL_IP4,
2784 &pfx_5_5_5_6_s_32.fp_addr,
2785 ~0, // no index provided.
2786 fib_index, // same as route's FIB
2787 1,
2788 FIB_ROUTE_PATH_FLAG_NONE);
2789 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2790 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2791 "1-level 5.5.5.6/32 loop is removed");
2792
2793 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002794 * A recursive route whose next-hop is covered by the prefix.
2795 * This would mean the via-fib, which inherits forwarding from its
2796 * cover, thus picks up forwarding from the prfix, which is via the
2797 * via-fib, and we have a loop.
2798 */
2799 fib_prefix_t pfx_23_23_23_0_s_24 = {
2800 .fp_len = 24,
2801 .fp_proto = FIB_PROTOCOL_IP4,
2802 .fp_addr = {
2803 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2804 },
2805 };
2806 fib_prefix_t pfx_23_23_23_23_s_32 = {
2807 .fp_len = 32,
2808 .fp_proto = FIB_PROTOCOL_IP4,
2809 .fp_addr = {
2810 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2811 },
2812 };
2813 fei = fib_table_entry_path_add(fib_index,
2814 &pfx_23_23_23_0_s_24,
2815 FIB_SOURCE_API,
2816 FIB_ENTRY_FLAG_NONE,
2817 FIB_PROTOCOL_IP4,
2818 &pfx_23_23_23_23_s_32.fp_addr,
2819 ~0, // recursive
2820 fib_index,
2821 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002822 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002823 FIB_ROUTE_PATH_FLAG_NONE);
2824 dpo = fib_entry_contribute_ip_forwarding(fei);
2825 FIB_TEST(load_balance_is_drop(dpo),
2826 "23.23.23.0/24 via covered is DROP");
2827 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2828
2829 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002830 * add-remove test. no change.
2831 */
2832 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2833 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002834 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002835 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002836 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002837 fib_entry_pool_size());
2838
2839 /*
2840 * A recursive route with recursion constraints.
2841 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2842 */
2843 fib_table_entry_path_add(fib_index,
2844 &bgp_200_pfx,
2845 FIB_SOURCE_API,
2846 FIB_ENTRY_FLAG_NONE,
2847 FIB_PROTOCOL_IP4,
2848 &nh_1_1_1_1,
2849 ~0,
2850 fib_index,
2851 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002852 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002853 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2854
2855 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2856 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2857
2858 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2859 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2860
2861 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2862 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2863
2864 /*
2865 * save the load-balance. we expect it to be inplace modified
2866 */
2867 lb = load_balance_get(dpo1->dpoi_index);
2868
2869 /*
2870 * add a covering prefix for the via fib that would otherwise serve
2871 * as the resolving route when the host is removed
2872 */
2873 fib_table_entry_path_add(fib_index,
2874 &pfx_1_1_1_0_s_28,
2875 FIB_SOURCE_API,
2876 FIB_ENTRY_FLAG_NONE,
2877 FIB_PROTOCOL_IP4,
2878 &nh_10_10_10_1,
2879 tm->hw[0]->sw_if_index,
2880 ~0, // invalid fib index
2881 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002882 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002883 FIB_ROUTE_PATH_FLAG_NONE);
2884 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
2885 ai = fib_entry_get_adj(fei);
2886 FIB_TEST((ai == ai_01),
2887 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
2888
2889 /*
2890 * remove the host via FIB - expect the BGP prefix to be drop
2891 */
2892 fib_table_entry_path_remove(fib_index,
2893 &pfx_1_1_1_1_s_32,
2894 FIB_SOURCE_API,
2895 FIB_PROTOCOL_IP4,
2896 &nh_10_10_10_1,
2897 tm->hw[0]->sw_if_index,
2898 ~0, // invalid fib index
2899 1,
2900 FIB_ROUTE_PATH_FLAG_NONE);
2901
2902 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2903 "adj for 200.200.200.200/32 is recursive via adj for DROP");
2904
2905 /*
2906 * add the via-entry host reoute back. expect to resolve again
2907 */
2908 fib_table_entry_path_add(fib_index,
2909 &pfx_1_1_1_1_s_32,
2910 FIB_SOURCE_API,
2911 FIB_ENTRY_FLAG_NONE,
2912 FIB_PROTOCOL_IP4,
2913 &nh_10_10_10_1,
2914 tm->hw[0]->sw_if_index,
2915 ~0, // invalid fib index
2916 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002917 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002918 FIB_ROUTE_PATH_FLAG_NONE);
2919 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2920 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2921
2922 /*
2923 * add another path for the recursive. it will then have 2.
2924 */
2925 fib_prefix_t pfx_1_1_1_3_s_32 = {
2926 .fp_len = 32,
2927 .fp_proto = FIB_PROTOCOL_IP4,
2928 .fp_addr = {
2929 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
2930 },
2931 };
2932 fib_table_entry_path_add(fib_index,
2933 &pfx_1_1_1_3_s_32,
2934 FIB_SOURCE_API,
2935 FIB_ENTRY_FLAG_NONE,
2936 FIB_PROTOCOL_IP4,
2937 &nh_10_10_10_2,
2938 tm->hw[0]->sw_if_index,
2939 ~0, // invalid fib index
2940 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002941 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002942 FIB_ROUTE_PATH_FLAG_NONE);
2943
2944 fib_table_entry_path_add(fib_index,
2945 &bgp_200_pfx,
2946 FIB_SOURCE_API,
2947 FIB_ENTRY_FLAG_NONE,
2948 FIB_PROTOCOL_IP4,
2949 &pfx_1_1_1_3_s_32.fp_addr,
2950 ~0,
2951 fib_index,
2952 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002953 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002954 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2955
2956 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2957 dpo = fib_entry_contribute_ip_forwarding(fei);
2958
2959 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2960 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2961 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
2962 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2963 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
2964 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2965 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
2966 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
2967
2968 /*
2969 * expect the lb-map used by the recursive's load-balance is using both buckets
2970 */
2971 load_balance_map_t *lbm;
2972 index_t lbmi;
2973
2974 lb = load_balance_get(dpo->dpoi_index);
2975 lbmi = lb->lb_map;
2976 load_balance_map_lock(lbmi);
2977 lbm = load_balance_map_get(lbmi);
2978
2979 FIB_TEST(lbm->lbm_buckets[0] == 0,
2980 "LB maps's bucket 0 is %d",
2981 lbm->lbm_buckets[0]);
2982 FIB_TEST(lbm->lbm_buckets[1] == 1,
2983 "LB maps's bucket 1 is %d",
2984 lbm->lbm_buckets[1]);
2985
2986 /*
2987 * withdraw one of the /32 via-entrys.
2988 * that ECMP path will be unresolved and forwarding should continue on the
2989 * other available path. this is an iBGP PIC edge failover.
2990 * Test the forwarding changes without re-fetching the adj from the
2991 * recursive entry. this ensures its the same one that is updated; i.e. an
2992 * inplace-modify.
2993 */
2994 fib_table_entry_path_remove(fib_index,
2995 &pfx_1_1_1_1_s_32,
2996 FIB_SOURCE_API,
2997 FIB_PROTOCOL_IP4,
2998 &nh_10_10_10_1,
2999 tm->hw[0]->sw_if_index,
3000 ~0, // invalid fib index
3001 1,
3002 FIB_ROUTE_PATH_FLAG_NONE);
3003
3004 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3005 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3006 "post PIC 200.200.200.200/32 was inplace modified");
3007
3008 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3009 "post PIC adj for 200.200.200.200/32 is recursive"
3010 " via adj for 1.1.1.3");
3011
3012 /*
3013 * the LB maps that was locked above should have been modified to remove
3014 * the path that was down, and thus its bucket points to a path that is
3015 * still up.
3016 */
3017 FIB_TEST(lbm->lbm_buckets[0] == 1,
3018 "LB maps's bucket 0 is %d",
3019 lbm->lbm_buckets[0]);
3020 FIB_TEST(lbm->lbm_buckets[1] == 1,
3021 "LB maps's bucket 1 is %d",
3022 lbm->lbm_buckets[1]);
3023
3024 load_balance_map_unlock(lb->lb_map);
3025
3026 /*
3027 * add it back. again
3028 */
3029 fib_table_entry_path_add(fib_index,
3030 &pfx_1_1_1_1_s_32,
3031 FIB_SOURCE_API,
3032 FIB_ENTRY_FLAG_NONE,
3033 FIB_PROTOCOL_IP4,
3034 &nh_10_10_10_1,
3035 tm->hw[0]->sw_if_index,
3036 ~0, // invalid fib index
3037 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003038 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003039 FIB_ROUTE_PATH_FLAG_NONE);
3040
3041 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3042 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3043 "via adj for 1.1.1.1");
3044 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3045 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3046 "via adj for 1.1.1.3");
3047
3048 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3049 dpo = fib_entry_contribute_ip_forwarding(fei);
3050 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3051 "post PIC 200.200.200.200/32 was inplace modified");
3052
3053 /*
3054 * add a 3rd path. this makes the LB 16 buckets.
3055 */
3056 fib_table_entry_path_add(fib_index,
3057 &bgp_200_pfx,
3058 FIB_SOURCE_API,
3059 FIB_ENTRY_FLAG_NONE,
3060 FIB_PROTOCOL_IP4,
3061 &pfx_1_1_1_2_s_32.fp_addr,
3062 ~0,
3063 fib_index,
3064 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003065 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003066 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3067
3068 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3069 dpo = fib_entry_contribute_ip_forwarding(fei);
3070 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3071 "200.200.200.200/32 was inplace modified for 3rd path");
3072 FIB_TEST(16 == lb->lb_n_buckets,
3073 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3074
3075 lbmi = lb->lb_map;
3076 load_balance_map_lock(lbmi);
3077 lbm = load_balance_map_get(lbmi);
3078
3079 for (ii = 0; ii < 16; ii++)
3080 {
3081 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3082 "LB Map for 200.200.200.200/32 at %d is %d",
3083 ii, lbm->lbm_buckets[ii]);
3084 }
3085
3086 /*
3087 * trigger PIC by removing the first via-entry
3088 * the first 6 buckets of the map should map to the next 6
3089 */
3090 fib_table_entry_path_remove(fib_index,
3091 &pfx_1_1_1_1_s_32,
3092 FIB_SOURCE_API,
3093 FIB_PROTOCOL_IP4,
3094 &nh_10_10_10_1,
3095 tm->hw[0]->sw_if_index,
3096 ~0,
3097 1,
3098 FIB_ROUTE_PATH_FLAG_NONE);
3099
3100 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3101 dpo = fib_entry_contribute_ip_forwarding(fei);
3102 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3103 "200.200.200.200/32 was inplace modified for 3rd path");
3104 FIB_TEST(2 == lb->lb_n_buckets,
3105 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3106
3107 for (ii = 0; ii < 6; ii++)
3108 {
3109 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3110 "LB Map for 200.200.200.200/32 at %d is %d",
3111 ii, lbm->lbm_buckets[ii]);
3112 }
3113 for (ii = 6; ii < 16; ii++)
3114 {
3115 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3116 "LB Map for 200.200.200.200/32 at %d is %d",
3117 ii, lbm->lbm_buckets[ii]);
3118 }
3119
3120
3121 /*
3122 * tidy up
3123 */
3124 fib_table_entry_path_add(fib_index,
3125 &pfx_1_1_1_1_s_32,
3126 FIB_SOURCE_API,
3127 FIB_ENTRY_FLAG_NONE,
3128 FIB_PROTOCOL_IP4,
3129 &nh_10_10_10_1,
3130 tm->hw[0]->sw_if_index,
3131 ~0,
3132 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003133 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003134 FIB_ROUTE_PATH_FLAG_NONE);
3135
3136 fib_table_entry_path_remove(fib_index,
3137 &bgp_200_pfx,
3138 FIB_SOURCE_API,
3139 FIB_PROTOCOL_IP4,
3140 &pfx_1_1_1_2_s_32.fp_addr,
3141 ~0,
3142 fib_index,
3143 1,
3144 MPLS_LABEL_INVALID);
3145 fib_table_entry_path_remove(fib_index,
3146 &bgp_200_pfx,
3147 FIB_SOURCE_API,
3148 FIB_PROTOCOL_IP4,
3149 &nh_1_1_1_1,
3150 ~0,
3151 fib_index,
3152 1,
3153 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3154 fib_table_entry_path_remove(fib_index,
3155 &bgp_200_pfx,
3156 FIB_SOURCE_API,
3157 FIB_PROTOCOL_IP4,
3158 &pfx_1_1_1_3_s_32.fp_addr,
3159 ~0,
3160 fib_index,
3161 1,
3162 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3163 fib_table_entry_delete(fib_index,
3164 &pfx_1_1_1_3_s_32,
3165 FIB_SOURCE_API);
3166 fib_table_entry_delete(fib_index,
3167 &pfx_1_1_1_0_s_28,
3168 FIB_SOURCE_API);
3169 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3170 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3171 "1.1.1.1/28 removed");
3172 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3173 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3174 "1.1.1.3/32 removed");
3175 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3176 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3177 "200.200.200.200/32 removed");
3178
3179 /*
3180 * add-remove test. no change.
3181 */
3182 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3183 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003184 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003185 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003186 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003187 fib_entry_pool_size());
3188
3189 /*
3190 * A route whose paths are built up iteratively and then removed
3191 * all at once
3192 */
3193 fib_prefix_t pfx_4_4_4_4_s_32 = {
3194 .fp_len = 32,
3195 .fp_proto = FIB_PROTOCOL_IP4,
3196 .fp_addr = {
3197 /* 4.4.4.4/32 */
3198 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3199 },
3200 };
3201
3202 fib_table_entry_path_add(fib_index,
3203 &pfx_4_4_4_4_s_32,
3204 FIB_SOURCE_API,
3205 FIB_ENTRY_FLAG_NONE,
3206 FIB_PROTOCOL_IP4,
3207 &nh_10_10_10_1,
3208 tm->hw[0]->sw_if_index,
3209 ~0,
3210 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003211 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003212 FIB_ROUTE_PATH_FLAG_NONE);
3213 fib_table_entry_path_add(fib_index,
3214 &pfx_4_4_4_4_s_32,
3215 FIB_SOURCE_API,
3216 FIB_ENTRY_FLAG_NONE,
3217 FIB_PROTOCOL_IP4,
3218 &nh_10_10_10_2,
3219 tm->hw[0]->sw_if_index,
3220 ~0,
3221 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003222 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003223 FIB_ROUTE_PATH_FLAG_NONE);
3224 fib_table_entry_path_add(fib_index,
3225 &pfx_4_4_4_4_s_32,
3226 FIB_SOURCE_API,
3227 FIB_ENTRY_FLAG_NONE,
3228 FIB_PROTOCOL_IP4,
3229 &nh_10_10_10_3,
3230 tm->hw[0]->sw_if_index,
3231 ~0,
3232 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003233 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003234 FIB_ROUTE_PATH_FLAG_NONE);
3235 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3236 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3237 "4.4.4.4/32 present");
3238
3239 fib_table_entry_delete(fib_index,
3240 &pfx_4_4_4_4_s_32,
3241 FIB_SOURCE_API);
3242 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3243 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3244 "4.4.4.4/32 removed");
3245
3246 /*
3247 * add-remove test. no change.
3248 */
3249 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3250 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003251 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003252 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003253 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003254 fib_entry_pool_size());
3255
3256 /*
3257 * A route with multiple paths at once
3258 */
3259 fib_route_path_t *r_paths = NULL;
3260
3261 for (ii = 0; ii < 4; ii++)
3262 {
3263 fib_route_path_t r_path = {
3264 .frp_proto = FIB_PROTOCOL_IP4,
3265 .frp_addr = {
3266 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3267 },
3268 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3269 .frp_weight = 1,
3270 .frp_fib_index = ~0,
3271 };
3272 vec_add1(r_paths, r_path);
3273 }
3274
3275 fib_table_entry_update(fib_index,
3276 &pfx_4_4_4_4_s_32,
3277 FIB_SOURCE_API,
3278 FIB_ENTRY_FLAG_NONE,
3279 r_paths);
3280
3281 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3282 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3283 dpo = fib_entry_contribute_ip_forwarding(fei);
3284
3285 lb = load_balance_get(dpo->dpoi_index);
3286 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3287
3288 fib_table_entry_delete(fib_index,
3289 &pfx_4_4_4_4_s_32,
3290 FIB_SOURCE_API);
3291 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3292 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3293 "4.4.4.4/32 removed");
3294 vec_free(r_paths);
3295
3296 /*
3297 * add-remove test. no change.
3298 */
3299 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3300 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003301 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003302 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003303 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003304 fib_entry_pool_size());
3305
3306 /*
3307 * A route deag route
3308 */
3309 fib_table_entry_path_add(fib_index,
3310 &pfx_4_4_4_4_s_32,
3311 FIB_SOURCE_API,
3312 FIB_ENTRY_FLAG_NONE,
3313 FIB_PROTOCOL_IP4,
3314 &zero_addr,
3315 ~0,
3316 fib_index,
3317 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003318 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003319 FIB_ROUTE_PATH_FLAG_NONE);
3320
3321 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3322 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3323
3324 dpo = fib_entry_contribute_ip_forwarding(fei);
3325 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3326 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3327
3328 FIB_TEST((fib_index == lkd->lkd_fib_index),
3329 "4.4.4.4/32 is deag in %d %U",
3330 lkd->lkd_fib_index,
3331 format_dpo_id, dpo, 0);
3332
3333 fib_table_entry_delete(fib_index,
3334 &pfx_4_4_4_4_s_32,
3335 FIB_SOURCE_API);
3336 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3337 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3338 "4.4.4.4/32 removed");
3339 vec_free(r_paths);
3340
3341 /*
3342 * add-remove test. no change.
3343 */
3344 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3345 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003346 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003347 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003348 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003349 fib_entry_pool_size());
3350
3351 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003352 * Duplicate paths:
3353 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3354 */
3355 fib_prefix_t pfx_34_1_1_1_s_32 = {
3356 .fp_len = 32,
3357 .fp_proto = FIB_PROTOCOL_IP4,
3358 .fp_addr = {
3359 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3360 },
3361 };
3362 fib_prefix_t pfx_34_34_1_1_s_32 = {
3363 .fp_len = 32,
3364 .fp_proto = FIB_PROTOCOL_IP4,
3365 .fp_addr = {
3366 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3367 },
3368 };
3369 fei = fib_table_entry_path_add(fib_index,
3370 &pfx_34_1_1_1_s_32,
3371 FIB_SOURCE_API,
3372 FIB_ENTRY_FLAG_NONE,
3373 FIB_PROTOCOL_IP4,
3374 &pfx_34_34_1_1_s_32.fp_addr,
3375 ~0,
3376 fib_index,
3377 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003378 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003379 FIB_ROUTE_PATH_FLAG_NONE);
3380 fei = fib_table_entry_path_add(fib_index,
3381 &pfx_34_1_1_1_s_32,
3382 FIB_SOURCE_API,
3383 FIB_ENTRY_FLAG_NONE,
3384 FIB_PROTOCOL_IP4,
3385 &pfx_34_34_1_1_s_32.fp_addr,
3386 ~0,
3387 fib_index,
3388 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003389 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003390 FIB_ROUTE_PATH_FLAG_NONE);
3391 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3392 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3393
3394 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003395 * CLEANUP
3396 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3397 * all of which are via 10.10.10.1, Itf1
3398 */
3399 fib_table_entry_path_remove(fib_index,
3400 &pfx_1_1_1_2_s_32,
3401 FIB_SOURCE_API,
3402 FIB_PROTOCOL_IP4,
3403 &nh_10_10_10_1,
3404 tm->hw[0]->sw_if_index,
3405 ~0,
3406 1,
3407 FIB_ROUTE_PATH_FLAG_NONE);
3408 fib_table_entry_path_remove(fib_index,
3409 &pfx_1_1_1_1_s_32,
3410 FIB_SOURCE_API,
3411 FIB_PROTOCOL_IP4,
3412 &nh_10_10_10_1,
3413 tm->hw[0]->sw_if_index,
3414 ~0,
3415 1,
3416 FIB_ROUTE_PATH_FLAG_NONE);
3417 fib_table_entry_path_remove(fib_index,
3418 &pfx_1_1_2_0_s_24,
3419 FIB_SOURCE_API,
3420 FIB_PROTOCOL_IP4,
3421 &nh_10_10_10_1,
3422 tm->hw[0]->sw_if_index,
3423 ~0,
3424 1,
3425 FIB_ROUTE_PATH_FLAG_NONE);
3426
3427 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3428 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3429 "1.1.1.1/32 removed");
3430 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3431 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3432 "1.1.1.2/32 removed");
3433 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3434 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3435 "1.1.2.0/24 removed");
3436
3437 /*
3438 * -3 entries and -1 shared path-list
3439 */
3440 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3441 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003442 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003443 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003444 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003445 fib_entry_pool_size());
3446
3447 /*
3448 * An attached-host route. Expect to link to the incomplete adj
3449 */
3450 fib_prefix_t pfx_4_1_1_1_s_32 = {
3451 .fp_len = 32,
3452 .fp_proto = FIB_PROTOCOL_IP4,
3453 .fp_addr = {
3454 /* 4.1.1.1/32 */
3455 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3456 },
3457 };
3458 fib_table_entry_path_add(fib_index,
3459 &pfx_4_1_1_1_s_32,
3460 FIB_SOURCE_API,
3461 FIB_ENTRY_FLAG_NONE,
3462 FIB_PROTOCOL_IP4,
3463 &zero_addr,
3464 tm->hw[0]->sw_if_index,
3465 fib_index,
3466 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003467 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003468 FIB_ROUTE_PATH_FLAG_NONE);
3469
3470 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3471 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3472 ai = fib_entry_get_adj(fei);
3473
3474 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003475 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003476 &pfx_4_1_1_1_s_32.fp_addr,
3477 tm->hw[0]->sw_if_index);
3478 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3479 adj_unlock(ai2);
3480
3481 /*
3482 * +1 entry and +1 shared path-list
3483 */
3484 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3485 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003486 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003487 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003488 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003489 fib_entry_pool_size());
3490
3491 fib_table_entry_delete(fib_index,
3492 &pfx_4_1_1_1_s_32,
3493 FIB_SOURCE_API);
3494
3495 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3496 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003497 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003498 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003499 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003500 fib_entry_pool_size());
3501
3502 /*
3503 * add a v6 prefix via v4 next-hops
3504 */
3505 fib_prefix_t pfx_2001_s_64 = {
3506 .fp_len = 64,
3507 .fp_proto = FIB_PROTOCOL_IP6,
3508 .fp_addr = {
3509 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3510 },
3511 };
3512 fei = fib_table_entry_path_add(0, //default v6 table
3513 &pfx_2001_s_64,
3514 FIB_SOURCE_API,
3515 FIB_ENTRY_FLAG_NONE,
3516 FIB_PROTOCOL_IP4,
3517 &nh_10_10_10_1,
3518 tm->hw[0]->sw_if_index,
3519 fib_index,
3520 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003521 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003522 FIB_ROUTE_PATH_FLAG_NONE);
3523
3524 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3525 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3526 ai = fib_entry_get_adj(fei);
3527 adj = adj_get(ai);
3528 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3529 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003530 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003531 "2001::/64 is link type v6");
3532 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3533 "2001::/64 ADJ-adj is NH proto v4");
3534 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3535
Neale Ranns3ee44042016-10-03 13:05:48 +01003536 /*
3537 * add a uRPF exempt prefix:
3538 * test:
3539 * - it's forwarding is drop
3540 * - it's uRPF list is not empty
3541 * - the uRPF list for the default route (it's cover) is empty
3542 */
3543 fei = fib_table_entry_special_add(fib_index,
3544 &pfx_4_1_1_1_s_32,
3545 FIB_SOURCE_URPF_EXEMPT,
3546 FIB_ENTRY_FLAG_DROP,
3547 ADJ_INDEX_INVALID);
3548 dpo = fib_entry_contribute_ip_forwarding(fei);
3549 FIB_TEST(load_balance_is_drop(dpo),
3550 "uRPF exempt 4.1.1.1/32 DROP");
3551 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3552 "uRPF list for exempt prefix has itf index 0");
3553 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3554 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3555 "uRPF list for 0.0.0.0/0 empty");
3556
3557 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003558
3559 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003560 * An adj-fib that fails the refinement criteria - no connected cover
3561 */
3562 fib_prefix_t pfx_12_10_10_2_s_32 = {
3563 .fp_len = 32,
3564 .fp_proto = FIB_PROTOCOL_IP4,
3565 .fp_addr = {
3566 /* 12.10.10.2 */
3567 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3568 },
3569 };
3570
3571 fib_table_entry_update_one_path(fib_index,
3572 &pfx_12_10_10_2_s_32,
3573 FIB_SOURCE_ADJ,
3574 FIB_ENTRY_FLAG_ATTACHED,
3575 FIB_PROTOCOL_IP4,
3576 &pfx_12_10_10_2_s_32.fp_addr,
3577 tm->hw[0]->sw_if_index,
3578 ~0, // invalid fib index
3579 1,
3580 NULL,
3581 FIB_ROUTE_PATH_FLAG_NONE);
3582
3583 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3584 dpo = fib_entry_contribute_ip_forwarding(fei);
3585 FIB_TEST(!dpo_id_is_valid(dpo),
3586 "no connected cover adj-fib fails refinement");
3587
3588 fib_table_entry_delete(fib_index,
3589 &pfx_12_10_10_2_s_32,
3590 FIB_SOURCE_ADJ);
3591
3592 /*
3593 * An adj-fib that fails the refinement criteria - cover is connected
3594 * but on a different interface
3595 */
3596 fib_prefix_t pfx_10_10_10_127_s_32 = {
3597 .fp_len = 32,
3598 .fp_proto = FIB_PROTOCOL_IP4,
3599 .fp_addr = {
3600 /* 10.10.10.127 */
3601 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3602 },
3603 };
3604
3605 fib_table_entry_update_one_path(fib_index,
3606 &pfx_10_10_10_127_s_32,
3607 FIB_SOURCE_ADJ,
3608 FIB_ENTRY_FLAG_ATTACHED,
3609 FIB_PROTOCOL_IP4,
3610 &pfx_10_10_10_127_s_32.fp_addr,
3611 tm->hw[1]->sw_if_index,
3612 ~0, // invalid fib index
3613 1,
3614 NULL,
3615 FIB_ROUTE_PATH_FLAG_NONE);
3616
3617 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3618 dpo = fib_entry_contribute_ip_forwarding(fei);
3619 FIB_TEST(!dpo_id_is_valid(dpo),
3620 "wrong interface adj-fib fails refinement");
3621
3622 fib_table_entry_delete(fib_index,
3623 &pfx_10_10_10_127_s_32,
3624 FIB_SOURCE_ADJ);
3625
3626 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003627 * CLEANUP
3628 * remove adj-fibs:
3629 */
3630 fib_table_entry_delete(fib_index,
3631 &pfx_10_10_10_1_s_32,
3632 FIB_SOURCE_ADJ);
3633 fib_table_entry_delete(fib_index,
3634 &pfx_10_10_10_2_s_32,
3635 FIB_SOURCE_ADJ);
3636 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3637 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3638 "10.10.10.1/32 adj-fib removed");
3639 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3640 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3641 "10.10.10.2/32 adj-fib removed");
3642
3643 /*
3644 * -2 entries and -2 non-shared path-list
3645 */
3646 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3647 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003648 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003649 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003650 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003651 fib_entry_pool_size());
3652
3653 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01003654 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003655 * These are the last locks on these adjs. they should thus go away.
3656 */
3657 adj_unlock(ai_02);
3658 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01003659 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003660
3661 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3662 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003663
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003664 /*
3665 * CLEANUP
3666 * remove the interface prefixes
3667 */
3668 local_pfx.fp_len = 32;
3669 fib_table_entry_special_remove(fib_index, &local_pfx,
3670 FIB_SOURCE_INTERFACE);
3671 fei = fib_table_lookup(fib_index, &local_pfx);
3672
3673 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3674 fib_table_lookup_exact_match(fib_index, &local_pfx),
3675 "10.10.10.10/32 adj-fib removed");
3676
3677 local_pfx.fp_len = 24;
3678 fib_table_entry_delete(fib_index, &local_pfx,
3679 FIB_SOURCE_INTERFACE);
3680
3681 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3682 fib_table_lookup_exact_match(fib_index, &local_pfx),
3683 "10.10.10.10/24 adj-fib removed");
3684
3685 /*
3686 * -2 entries and -2 non-shared path-list
3687 */
3688 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3689 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003690 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003691 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003692 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003693 fib_entry_pool_size());
3694
3695 /*
3696 * Last but not least, remove the VRF
3697 */
3698 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3699 FIB_PROTOCOL_IP4,
3700 FIB_SOURCE_API)),
3701 "NO API Source'd prefixes");
3702 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3703 FIB_PROTOCOL_IP4,
3704 FIB_SOURCE_RR)),
3705 "NO RR Source'd prefixes");
3706 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3707 FIB_PROTOCOL_IP4,
3708 FIB_SOURCE_INTERFACE)),
3709 "NO INterface Source'd prefixes");
3710
3711 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3712
3713 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3714 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003715 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003716 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003717 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003718 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003719 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01003720 pool_elts(fib_urpf_list_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003721
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003722 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003723}
3724
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003725static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003726fib_test_v6 (void)
3727{
3728 /*
3729 * In the default table check for the presence and correct forwarding
3730 * of the special entries
3731 */
3732 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
3733 const dpo_id_t *dpo, *dpo_drop;
3734 const ip_adjacency_t *adj;
3735 const receive_dpo_t *rd;
3736 test_main_t *tm;
3737 u32 fib_index;
3738 int ii;
3739
3740 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3741 adj_nbr_db_size());
3742
3743 /* via 2001:0:0:1::2 */
3744 ip46_address_t nh_2001_2 = {
3745 .ip6 = {
3746 .as_u64 = {
3747 [0] = clib_host_to_net_u64(0x2001000000000001),
3748 [1] = clib_host_to_net_u64(0x0000000000000002),
3749 },
3750 },
3751 };
3752
3753 tm = &test_main;
3754
3755 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
3756
3757 /* Find or create FIB table 11 */
3758 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
3759
3760 for (ii = 0; ii < 4; ii++)
3761 {
3762 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
3763 }
3764
3765 fib_prefix_t pfx_0_0 = {
3766 .fp_len = 0,
3767 .fp_proto = FIB_PROTOCOL_IP6,
3768 .fp_addr = {
3769 .ip6 = {
3770 {0, 0},
3771 },
3772 },
3773 };
3774
3775 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
3776 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
3777 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3778 "Default route is DROP");
3779
3780 dpo = fib_entry_contribute_ip_forwarding(dfrt);
3781 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3782 &ip6_main,
3783 1,
3784 &pfx_0_0.fp_addr.ip6)),
3785 "default-route; fwd and non-fwd tables match");
3786
3787 // FIXME - check specials.
3788
3789 /*
3790 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00003791 * each with 2 entries and a v6 mfib with 4 path-lists.
3792 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003793 */
Neale Ranns32e1c012016-11-22 17:07:28 +00003794#define ENPS (5+4)
3795#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003796 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00003797 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003798 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003799 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003800 fib_entry_pool_size());
3801
3802 /*
3803 * add interface routes.
3804 * validate presence of /64 attached and /128 recieve.
3805 * test for the presence of the receive address in the glean and local adj
3806 *
3807 * receive on 2001:0:0:1::1/128
3808 */
3809 fib_prefix_t local_pfx = {
3810 .fp_len = 64,
3811 .fp_proto = FIB_PROTOCOL_IP6,
3812 .fp_addr = {
3813 .ip6 = {
3814 .as_u64 = {
3815 [0] = clib_host_to_net_u64(0x2001000000000001),
3816 [1] = clib_host_to_net_u64(0x0000000000000001),
3817 },
3818 },
3819 }
3820 };
3821
3822 fib_table_entry_update_one_path(fib_index, &local_pfx,
3823 FIB_SOURCE_INTERFACE,
3824 (FIB_ENTRY_FLAG_CONNECTED |
3825 FIB_ENTRY_FLAG_ATTACHED),
3826 FIB_PROTOCOL_IP6,
3827 NULL,
3828 tm->hw[0]->sw_if_index,
3829 ~0,
3830 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003831 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003832 FIB_ROUTE_PATH_FLAG_NONE);
3833 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
3834
3835 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
3836
3837 ai = fib_entry_get_adj(fei);
3838 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
3839 adj = adj_get(ai);
3840 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
3841 "attached interface adj is glean");
3842 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3843 &adj->sub_type.glean.receive_addr)),
3844 "attached interface adj is receive ok");
3845 dpo = fib_entry_contribute_ip_forwarding(fei);
3846 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3847 &ip6_main,
3848 1,
3849 &local_pfx.fp_addr.ip6)),
3850 "attached-route; fwd and non-fwd tables match");
3851
3852 local_pfx.fp_len = 128;
3853 fib_table_entry_update_one_path(fib_index, &local_pfx,
3854 FIB_SOURCE_INTERFACE,
3855 (FIB_ENTRY_FLAG_CONNECTED |
3856 FIB_ENTRY_FLAG_LOCAL),
3857 FIB_PROTOCOL_IP6,
3858 NULL,
3859 tm->hw[0]->sw_if_index,
3860 ~0, // invalid fib index
3861 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003862 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003863 FIB_ROUTE_PATH_FLAG_NONE);
3864 fei = fib_table_lookup(fib_index, &local_pfx);
3865
3866 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
3867
3868 dpo = fib_entry_contribute_ip_forwarding(fei);
3869 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3870 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
3871 "local interface adj is local");
3872 rd = receive_dpo_get(dpo->dpoi_index);
3873
3874 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3875 &rd->rd_addr)),
3876 "local interface adj is receive ok");
3877
3878 dpo = fib_entry_contribute_ip_forwarding(fei);
3879 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3880 &ip6_main,
3881 1,
3882 &local_pfx.fp_addr.ip6)),
3883 "local-route; fwd and non-fwd tables match");
3884
3885 /*
3886 * +2 entries. +2 unshared path-lists
3887 */
3888 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00003889 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003890 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003891 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003892 fib_entry_pool_size());
3893
3894 /*
3895 * Modify the default route to be via an adj not yet known.
3896 * this sources the defalut route with the API source, which is
3897 * a higher preference to the DEFAULT_ROUTE source
3898 */
3899 fib_table_entry_path_add(fib_index, &pfx_0_0,
3900 FIB_SOURCE_API,
3901 FIB_ENTRY_FLAG_NONE,
3902 FIB_PROTOCOL_IP6,
3903 &nh_2001_2,
3904 tm->hw[0]->sw_if_index,
3905 ~0,
3906 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003907 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003908 FIB_ROUTE_PATH_FLAG_NONE);
3909 fei = fib_table_lookup(fib_index, &pfx_0_0);
3910
3911 FIB_TEST((fei == dfrt), "default route same index");
3912 ai = fib_entry_get_adj(fei);
3913 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
3914 adj = adj_get(ai);
3915 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3916 "adj is incomplete");
3917 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
3918 "adj nbr next-hop ok");
3919
3920 /*
3921 * find the adj in the shared db
3922 */
3923 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003924 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003925 &nh_2001_2,
3926 tm->hw[0]->sw_if_index);
3927 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
3928 adj_unlock(locked_ai);
3929
3930 /*
3931 * no more entires. +1 shared path-list
3932 */
3933 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3934 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003935 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003936 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003937 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003938 fib_entry_pool_size());
3939
3940 /*
3941 * remove the API source from the default route. We expected
3942 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
3943 */
3944 fib_table_entry_path_remove(fib_index, &pfx_0_0,
3945 FIB_SOURCE_API,
3946 FIB_PROTOCOL_IP6,
3947 &nh_2001_2,
3948 tm->hw[0]->sw_if_index,
3949 ~0,
3950 1,
3951 FIB_ROUTE_PATH_FLAG_NONE);
3952 fei = fib_table_lookup(fib_index, &pfx_0_0);
3953
3954 FIB_TEST((fei == dfrt), "default route same index");
3955 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3956 "Default route is DROP");
3957
3958 /*
3959 * no more entires. -1 shared path-list
3960 */
3961 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3962 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003963 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003964 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003965 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003966 fib_entry_pool_size());
3967
3968 /*
3969 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
3970 */
3971 fib_prefix_t pfx_2001_1_2_s_128 = {
3972 .fp_len = 128,
3973 .fp_proto = FIB_PROTOCOL_IP6,
3974 .fp_addr = {
3975 .ip6 = {
3976 .as_u64 = {
3977 [0] = clib_host_to_net_u64(0x2001000000000001),
3978 [1] = clib_host_to_net_u64(0x0000000000000002),
3979 },
3980 },
3981 }
3982 };
3983 fib_prefix_t pfx_2001_1_3_s_128 = {
3984 .fp_len = 128,
3985 .fp_proto = FIB_PROTOCOL_IP6,
3986 .fp_addr = {
3987 .ip6 = {
3988 .as_u64 = {
3989 [0] = clib_host_to_net_u64(0x2001000000000001),
3990 [1] = clib_host_to_net_u64(0x0000000000000003),
3991 },
3992 },
3993 }
3994 };
3995 u8 eth_addr[] = {
3996 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
3997 };
3998
3999 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004000 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004001 &pfx_2001_1_2_s_128.fp_addr,
4002 tm->hw[0]->sw_if_index);
4003 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4004 adj = adj_get(ai_01);
4005 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4006 "adj is incomplete");
4007 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4008 &adj->sub_type.nbr.next_hop)),
4009 "adj nbr next-hop ok");
4010
Neale Rannsb80c5362016-10-08 13:03:40 +01004011 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4012 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004013 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4014 "adj is complete");
4015 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4016 &adj->sub_type.nbr.next_hop)),
4017 "adj nbr next-hop ok");
4018
4019 fib_table_entry_update_one_path(fib_index,
4020 &pfx_2001_1_2_s_128,
4021 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004022 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004023 FIB_PROTOCOL_IP6,
4024 &pfx_2001_1_2_s_128.fp_addr,
4025 tm->hw[0]->sw_if_index,
4026 ~0,
4027 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004028 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004029 FIB_ROUTE_PATH_FLAG_NONE);
4030
4031 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4032 ai = fib_entry_get_adj(fei);
4033 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4034
4035 eth_addr[5] = 0xb2;
4036
4037 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004038 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004039 &pfx_2001_1_3_s_128.fp_addr,
4040 tm->hw[0]->sw_if_index);
4041 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4042 adj = adj_get(ai_02);
4043 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4044 "adj is incomplete");
4045 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4046 &adj->sub_type.nbr.next_hop)),
4047 "adj nbr next-hop ok");
4048
Neale Rannsb80c5362016-10-08 13:03:40 +01004049 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4050 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004051 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4052 "adj is complete");
4053 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4054 &adj->sub_type.nbr.next_hop)),
4055 "adj nbr next-hop ok");
4056 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4057
4058 fib_table_entry_update_one_path(fib_index,
4059 &pfx_2001_1_3_s_128,
4060 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004061 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004062 FIB_PROTOCOL_IP6,
4063 &pfx_2001_1_3_s_128.fp_addr,
4064 tm->hw[0]->sw_if_index,
4065 ~0,
4066 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004067 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004068 FIB_ROUTE_PATH_FLAG_NONE);
4069
4070 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4071 ai = fib_entry_get_adj(fei);
4072 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4073
4074 /*
4075 * +2 entries, +2 unshread path-lists.
4076 */
4077 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4078 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004079 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004080 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004081 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004082 fib_entry_pool_size());
4083
4084 /*
4085 * Add a 2 routes via the first ADJ. ensure path-list sharing
4086 */
4087 fib_prefix_t pfx_2001_a_s_64 = {
4088 .fp_len = 64,
4089 .fp_proto = FIB_PROTOCOL_IP6,
4090 .fp_addr = {
4091 .ip6 = {
4092 .as_u64 = {
4093 [0] = clib_host_to_net_u64(0x200100000000000a),
4094 [1] = clib_host_to_net_u64(0x0000000000000000),
4095 },
4096 },
4097 }
4098 };
4099 fib_prefix_t pfx_2001_b_s_64 = {
4100 .fp_len = 64,
4101 .fp_proto = FIB_PROTOCOL_IP6,
4102 .fp_addr = {
4103 .ip6 = {
4104 .as_u64 = {
4105 [0] = clib_host_to_net_u64(0x200100000000000b),
4106 [1] = clib_host_to_net_u64(0x0000000000000000),
4107 },
4108 },
4109 }
4110 };
4111
4112 fib_table_entry_path_add(fib_index,
4113 &pfx_2001_a_s_64,
4114 FIB_SOURCE_API,
4115 FIB_ENTRY_FLAG_NONE,
4116 FIB_PROTOCOL_IP6,
4117 &nh_2001_2,
4118 tm->hw[0]->sw_if_index,
4119 ~0,
4120 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004121 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004122 FIB_ROUTE_PATH_FLAG_NONE);
4123 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4124 ai = fib_entry_get_adj(fei);
4125 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4126 fib_table_entry_path_add(fib_index,
4127 &pfx_2001_b_s_64,
4128 FIB_SOURCE_API,
4129 FIB_ENTRY_FLAG_NONE,
4130 FIB_PROTOCOL_IP6,
4131 &nh_2001_2,
4132 tm->hw[0]->sw_if_index,
4133 ~0,
4134 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004135 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004136 FIB_ROUTE_PATH_FLAG_NONE);
4137 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4138 ai = fib_entry_get_adj(fei);
4139 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4140
4141 /*
4142 * +2 entries, +1 shared path-list.
4143 */
4144 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4145 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004146 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004147 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004148 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004149 fib_entry_pool_size());
4150
4151 /*
4152 * add a v4 prefix via a v6 next-hop
4153 */
4154 fib_prefix_t pfx_1_1_1_1_s_32 = {
4155 .fp_len = 32,
4156 .fp_proto = FIB_PROTOCOL_IP4,
4157 .fp_addr = {
4158 .ip4.as_u32 = 0x01010101,
4159 },
4160 };
4161 fei = fib_table_entry_path_add(0, // default table
4162 &pfx_1_1_1_1_s_32,
4163 FIB_SOURCE_API,
4164 FIB_ENTRY_FLAG_NONE,
4165 FIB_PROTOCOL_IP6,
4166 &nh_2001_2,
4167 tm->hw[0]->sw_if_index,
4168 ~0,
4169 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004170 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004171 FIB_ROUTE_PATH_FLAG_NONE);
4172 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4173 "1.1.1.1/32 o v6 route present");
4174 ai = fib_entry_get_adj(fei);
4175 adj = adj_get(ai);
4176 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4177 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004178 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004179 "1.1.1.1/32 ADJ-adj is link type v4");
4180 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4181 "1.1.1.1/32 ADJ-adj is NH proto v6");
4182 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4183
4184 /*
4185 * An attached route
4186 */
4187 fib_prefix_t pfx_2001_c_s_64 = {
4188 .fp_len = 64,
4189 .fp_proto = FIB_PROTOCOL_IP6,
4190 .fp_addr = {
4191 .ip6 = {
4192 .as_u64 = {
4193 [0] = clib_host_to_net_u64(0x200100000000000c),
4194 [1] = clib_host_to_net_u64(0x0000000000000000),
4195 },
4196 },
4197 }
4198 };
4199 fib_table_entry_path_add(fib_index,
4200 &pfx_2001_c_s_64,
4201 FIB_SOURCE_CLI,
4202 FIB_ENTRY_FLAG_ATTACHED,
4203 FIB_PROTOCOL_IP6,
4204 NULL,
4205 tm->hw[0]->sw_if_index,
4206 ~0,
4207 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004208 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004209 FIB_ROUTE_PATH_FLAG_NONE);
4210 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4211 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4212 ai = fib_entry_get_adj(fei);
4213 adj = adj_get(ai);
4214 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4215 "2001:0:0:c/64 attached resolves via glean");
4216
4217 fib_table_entry_path_remove(fib_index,
4218 &pfx_2001_c_s_64,
4219 FIB_SOURCE_CLI,
4220 FIB_PROTOCOL_IP6,
4221 NULL,
4222 tm->hw[0]->sw_if_index,
4223 ~0,
4224 1,
4225 FIB_ROUTE_PATH_FLAG_NONE);
4226 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4227 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4228
4229 /*
4230 * Shutdown the interface on which we have a connected and through
4231 * which the routes are reachable.
4232 * This will result in the connected, adj-fibs, and routes linking to drop
4233 * The local/for-us prefix continues to receive.
4234 */
4235 clib_error_t * error;
4236
4237 error = vnet_sw_interface_set_flags(vnet_get_main(),
4238 tm->hw[0]->sw_if_index,
4239 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4240 FIB_TEST((NULL == error), "Interface shutdown OK");
4241
4242 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4243 dpo = fib_entry_contribute_ip_forwarding(fei);
4244 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4245 "2001::b/64 resolves via drop");
4246
4247 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4248 dpo = fib_entry_contribute_ip_forwarding(fei);
4249 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4250 "2001::a/64 resolves via drop");
4251 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4252 dpo = fib_entry_contribute_ip_forwarding(fei);
4253 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4254 "2001:0:0:1::3/64 resolves via drop");
4255 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4256 dpo = fib_entry_contribute_ip_forwarding(fei);
4257 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4258 "2001:0:0:1::2/64 resolves via drop");
4259 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4260 dpo = fib_entry_contribute_ip_forwarding(fei);
4261 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4262 "2001:0:0:1::1/128 not drop");
4263 local_pfx.fp_len = 64;
4264 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4265 dpo = fib_entry_contribute_ip_forwarding(fei);
4266 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4267 "2001:0:0:1/64 resolves via drop");
4268
4269 /*
4270 * no change
4271 */
4272 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4273 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004274 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004275 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004276 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004277 fib_entry_pool_size());
4278
4279 /*
4280 * shutdown one of the other interfaces, then add a connected.
4281 * and swap one of the routes to it.
4282 */
4283 error = vnet_sw_interface_set_flags(vnet_get_main(),
4284 tm->hw[1]->sw_if_index,
4285 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4286 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4287
4288 fib_prefix_t connected_pfx = {
4289 .fp_len = 64,
4290 .fp_proto = FIB_PROTOCOL_IP6,
4291 .fp_addr = {
4292 .ip6 = {
4293 /* 2001:0:0:2::1/64 */
4294 .as_u64 = {
4295 [0] = clib_host_to_net_u64(0x2001000000000002),
4296 [1] = clib_host_to_net_u64(0x0000000000000001),
4297 },
4298 },
4299 }
4300 };
4301 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4302 FIB_SOURCE_INTERFACE,
4303 (FIB_ENTRY_FLAG_CONNECTED |
4304 FIB_ENTRY_FLAG_ATTACHED),
4305 FIB_PROTOCOL_IP6,
4306 NULL,
4307 tm->hw[1]->sw_if_index,
4308 ~0,
4309 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004310 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004311 FIB_ROUTE_PATH_FLAG_NONE);
4312 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4313 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4314 dpo = fib_entry_contribute_ip_forwarding(fei);
4315 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4316 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4317 "2001:0:0:2/64 not resolves via drop");
4318
4319 connected_pfx.fp_len = 128;
4320 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4321 FIB_SOURCE_INTERFACE,
4322 (FIB_ENTRY_FLAG_CONNECTED |
4323 FIB_ENTRY_FLAG_LOCAL),
4324 FIB_PROTOCOL_IP6,
4325 NULL,
4326 tm->hw[0]->sw_if_index,
4327 ~0, // invalid fib index
4328 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004329 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004330 FIB_ROUTE_PATH_FLAG_NONE);
4331 fei = fib_table_lookup(fib_index, &connected_pfx);
4332
4333 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4334 dpo = fib_entry_contribute_ip_forwarding(fei);
4335 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4336 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4337 "local interface adj is local");
4338 rd = receive_dpo_get(dpo->dpoi_index);
4339 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4340 &rd->rd_addr)),
4341 "local interface adj is receive ok");
4342
4343 /*
4344 * +2 entries, +2 unshared path-lists
4345 */
4346 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4347 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004348 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004349 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004350 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004351 fib_entry_pool_size());
4352
4353
4354 /*
4355 * bring the interface back up. we expected the routes to return
4356 * to normal forwarding.
4357 */
4358 error = vnet_sw_interface_set_flags(vnet_get_main(),
4359 tm->hw[0]->sw_if_index,
4360 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4361 FIB_TEST((NULL == error), "Interface bring-up OK");
4362 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4363 ai = fib_entry_get_adj(fei);
4364 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4365 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4366 ai = fib_entry_get_adj(fei);
4367 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4368 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4369 ai = fib_entry_get_adj(fei);
4370 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4371 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4372 ai = fib_entry_get_adj(fei);
4373 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4374 local_pfx.fp_len = 64;
4375 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4376 ai = fib_entry_get_adj(fei);
4377 adj = adj_get(ai);
4378 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4379 "attached interface adj is glean");
4380
4381 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004382 * Same test as above, but this time the HW interface goes down
4383 */
4384 error = vnet_hw_interface_set_flags(vnet_get_main(),
4385 tm->hw_if_indicies[0],
4386 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4387 FIB_TEST((NULL == error), "Interface shutdown OK");
4388
4389 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4390 dpo = fib_entry_contribute_ip_forwarding(fei);
4391 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4392 "2001::b/64 resolves via drop");
4393 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4394 dpo = fib_entry_contribute_ip_forwarding(fei);
4395 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4396 "2001::a/64 resolves via drop");
4397 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4398 dpo = fib_entry_contribute_ip_forwarding(fei);
4399 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4400 "2001:0:0:1::3/128 resolves via drop");
4401 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4402 dpo = fib_entry_contribute_ip_forwarding(fei);
4403 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4404 "2001:0:0:1::2/128 resolves via drop");
4405 local_pfx.fp_len = 128;
4406 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4407 dpo = fib_entry_contribute_ip_forwarding(fei);
4408 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4409 "2001:0:0:1::1/128 not drop");
4410 local_pfx.fp_len = 64;
4411 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4412 dpo = fib_entry_contribute_ip_forwarding(fei);
4413 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4414 "2001:0:0:1/64 resolves via drop");
4415
4416 error = vnet_hw_interface_set_flags(vnet_get_main(),
4417 tm->hw_if_indicies[0],
4418 VNET_HW_INTERFACE_FLAG_LINK_UP);
4419 FIB_TEST((NULL == error), "Interface bring-up OK");
4420 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4421 ai = fib_entry_get_adj(fei);
4422 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4423 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4424 ai = fib_entry_get_adj(fei);
4425 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4426 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4427 ai = fib_entry_get_adj(fei);
4428 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4429 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4430 ai = fib_entry_get_adj(fei);
4431 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4432 local_pfx.fp_len = 64;
4433 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4434 ai = fib_entry_get_adj(fei);
4435 adj = adj_get(ai);
4436 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4437 "attached interface adj is glean");
4438
4439 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004440 * Delete the interface that the routes reolve through.
4441 * Again no routes are removed. They all point to drop.
4442 *
4443 * This is considered an error case. The control plane should
4444 * not remove interfaces through which routes resolve, but
4445 * such things can happen. ALL affected routes will drop.
4446 */
4447 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4448
4449 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4450 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4451 "2001::b/64 resolves via drop");
4452 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4453 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4454 "2001::b/64 resolves via drop");
4455 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4456 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4457 "2001:0:0:1::3/64 resolves via drop");
4458 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4459 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4460 "2001:0:0:1::2/64 resolves via drop");
4461 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4462 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4463 "2001:0:0:1::1/128 is drop");
4464 local_pfx.fp_len = 64;
4465 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4466 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4467 "2001:0:0:1/64 resolves via drop");
4468
4469 /*
4470 * no change
4471 */
4472 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4473 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004474 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004475 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004476 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004477 fib_entry_pool_size());
4478
4479 /*
4480 * Add the interface back. routes stay unresolved.
4481 */
4482 error = ethernet_register_interface(vnet_get_main(),
4483 test_interface_device_class.index,
4484 0 /* instance */,
4485 hw_address,
4486 &tm->hw_if_indicies[0],
4487 /* flag change */ 0);
4488
4489 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4490 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4491 "2001::b/64 resolves via drop");
4492 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4493 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4494 "2001::b/64 resolves via drop");
4495 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4496 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4497 "2001:0:0:1::3/64 resolves via drop");
4498 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4499 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4500 "2001:0:0:1::2/64 resolves via drop");
4501 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4502 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4503 "2001:0:0:1::1/128 is drop");
4504 local_pfx.fp_len = 64;
4505 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4506 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4507 "2001:0:0:1/64 resolves via drop");
4508
4509 /*
4510 * CLEANUP ALL the routes
4511 */
4512 fib_table_entry_delete(fib_index,
4513 &pfx_2001_c_s_64,
4514 FIB_SOURCE_API);
4515 fib_table_entry_delete(fib_index,
4516 &pfx_2001_a_s_64,
4517 FIB_SOURCE_API);
4518 fib_table_entry_delete(fib_index,
4519 &pfx_2001_b_s_64,
4520 FIB_SOURCE_API);
4521 fib_table_entry_delete(fib_index,
4522 &pfx_2001_1_3_s_128,
4523 FIB_SOURCE_ADJ);
4524 fib_table_entry_delete(fib_index,
4525 &pfx_2001_1_2_s_128,
4526 FIB_SOURCE_ADJ);
4527 local_pfx.fp_len = 64;
4528 fib_table_entry_delete(fib_index, &local_pfx,
4529 FIB_SOURCE_INTERFACE);
4530 local_pfx.fp_len = 128;
4531 fib_table_entry_special_remove(fib_index, &local_pfx,
4532 FIB_SOURCE_INTERFACE);
4533 connected_pfx.fp_len = 64;
4534 fib_table_entry_delete(fib_index, &connected_pfx,
4535 FIB_SOURCE_INTERFACE);
4536 connected_pfx.fp_len = 128;
4537 fib_table_entry_special_remove(fib_index, &connected_pfx,
4538 FIB_SOURCE_INTERFACE);
4539
4540 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4541 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4542 "2001::a/64 removed");
4543 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4544 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4545 "2001::b/64 removed");
4546 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4547 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4548 "2001:0:0:1::3/128 removed");
4549 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4550 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4551 "2001:0:0:1::3/128 removed");
4552 local_pfx.fp_len = 64;
4553 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4554 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4555 "2001:0:0:1/64 removed");
4556 local_pfx.fp_len = 128;
4557 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4558 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4559 "2001:0:0:1::1/128 removed");
4560 connected_pfx.fp_len = 64;
4561 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4562 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4563 "2001:0:0:2/64 removed");
4564 connected_pfx.fp_len = 128;
4565 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4566 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4567 "2001:0:0:2::1/128 removed");
4568
4569 /*
4570 * -8 entries. -7 path-lists (1 was shared).
4571 */
4572 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4573 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004574 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004575 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004576 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004577 fib_entry_pool_size());
4578
4579 /*
4580 * now remove the VRF
4581 */
4582 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4583
4584 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4585 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004586 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004587 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004588 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004589 fib_entry_pool_size());
4590
4591 adj_unlock(ai_02);
4592 adj_unlock(ai_01);
4593
4594 /*
4595 * return the interfaces to up state
4596 */
4597 error = vnet_sw_interface_set_flags(vnet_get_main(),
4598 tm->hw[0]->sw_if_index,
4599 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4600 error = vnet_sw_interface_set_flags(vnet_get_main(),
4601 tm->hw[1]->sw_if_index,
4602 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4603
4604 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4605 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004606
4607 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004608}
4609
4610/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004611 * Test Attached Exports
4612 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004613static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004614fib_test_ae (void)
4615{
4616 const dpo_id_t *dpo, *dpo_drop;
4617 const u32 fib_index = 0;
4618 fib_node_index_t fei;
4619 test_main_t *tm;
4620 ip4_main_t *im;
4621
4622 tm = &test_main;
4623 im = &ip4_main;
4624
4625 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4626 adj_nbr_db_size());
4627
4628 /*
4629 * add interface routes. We'll assume this works. It's more rigorously
4630 * tested elsewhere.
4631 */
4632 fib_prefix_t local_pfx = {
4633 .fp_len = 24,
4634 .fp_proto = FIB_PROTOCOL_IP4,
4635 .fp_addr = {
4636 .ip4 = {
4637 /* 10.10.10.10 */
4638 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4639 },
4640 },
4641 };
4642
4643 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4644 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4645
4646 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4647
4648 fib_table_entry_update_one_path(fib_index, &local_pfx,
4649 FIB_SOURCE_INTERFACE,
4650 (FIB_ENTRY_FLAG_CONNECTED |
4651 FIB_ENTRY_FLAG_ATTACHED),
4652 FIB_PROTOCOL_IP4,
4653 NULL,
4654 tm->hw[0]->sw_if_index,
4655 ~0,
4656 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004657 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004658 FIB_ROUTE_PATH_FLAG_NONE);
4659 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4660 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4661 "attached interface route present");
4662
4663 local_pfx.fp_len = 32;
4664 fib_table_entry_update_one_path(fib_index, &local_pfx,
4665 FIB_SOURCE_INTERFACE,
4666 (FIB_ENTRY_FLAG_CONNECTED |
4667 FIB_ENTRY_FLAG_LOCAL),
4668 FIB_PROTOCOL_IP4,
4669 NULL,
4670 tm->hw[0]->sw_if_index,
4671 ~0, // invalid fib index
4672 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004673 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004674 FIB_ROUTE_PATH_FLAG_NONE);
4675 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4676
4677 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4678 "local interface route present");
4679
4680 /*
4681 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4682 */
4683 fib_prefix_t pfx_10_10_10_1_s_32 = {
4684 .fp_len = 32,
4685 .fp_proto = FIB_PROTOCOL_IP4,
4686 .fp_addr = {
4687 /* 10.10.10.1 */
4688 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4689 },
4690 };
4691 fib_node_index_t ai;
4692
4693 fib_table_entry_update_one_path(fib_index,
4694 &pfx_10_10_10_1_s_32,
4695 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004696 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004697 FIB_PROTOCOL_IP4,
4698 &pfx_10_10_10_1_s_32.fp_addr,
4699 tm->hw[0]->sw_if_index,
4700 ~0, // invalid fib index
4701 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004702 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004703 FIB_ROUTE_PATH_FLAG_NONE);
4704
4705 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4706 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4707 ai = fib_entry_get_adj(fei);
4708
4709 /*
4710 * create another FIB table into which routes will be imported
4711 */
4712 u32 import_fib_index1;
4713
4714 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4715
4716 /*
4717 * Add an attached route in the import FIB
4718 */
4719 local_pfx.fp_len = 24;
4720 fib_table_entry_update_one_path(import_fib_index1,
4721 &local_pfx,
4722 FIB_SOURCE_API,
4723 FIB_ENTRY_FLAG_NONE,
4724 FIB_PROTOCOL_IP4,
4725 NULL,
4726 tm->hw[0]->sw_if_index,
4727 ~0, // invalid fib index
4728 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004729 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004730 FIB_ROUTE_PATH_FLAG_NONE);
4731 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4732 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4733
4734 /*
4735 * check for the presence of the adj-fibs in the import table
4736 */
4737 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4738 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4739 FIB_TEST((ai == fib_entry_get_adj(fei)),
4740 "adj-fib1 Import uses same adj as export");
4741
4742 /*
4743 * check for the presence of the local in the import table
4744 */
4745 local_pfx.fp_len = 32;
4746 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4747 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4748
4749 /*
4750 * Add another adj-fin in the export table. Expect this
4751 * to get magically exported;
4752 */
4753 fib_prefix_t pfx_10_10_10_2_s_32 = {
4754 .fp_len = 32,
4755 .fp_proto = FIB_PROTOCOL_IP4,
4756 .fp_addr = {
4757 /* 10.10.10.2 */
4758 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
4759 },
4760 };
4761
4762 fib_table_entry_update_one_path(fib_index,
4763 &pfx_10_10_10_2_s_32,
4764 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004765 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004766 FIB_PROTOCOL_IP4,
4767 &pfx_10_10_10_2_s_32.fp_addr,
4768 tm->hw[0]->sw_if_index,
4769 ~0, // invalid fib index
4770 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004771 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004772 FIB_ROUTE_PATH_FLAG_NONE);
4773 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
4774 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
4775 ai = fib_entry_get_adj(fei);
4776
4777 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4778 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4779 FIB_TEST((ai == fib_entry_get_adj(fei)),
4780 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00004781 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
4782 "ADJ-fib2 imported flags %d",
4783 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004784
4785 /*
4786 * create a 2nd FIB table into which routes will be imported
4787 */
4788 u32 import_fib_index2;
4789
4790 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
4791
4792 /*
4793 * Add an attached route in the import FIB
4794 */
4795 local_pfx.fp_len = 24;
4796 fib_table_entry_update_one_path(import_fib_index2,
4797 &local_pfx,
4798 FIB_SOURCE_API,
4799 FIB_ENTRY_FLAG_NONE,
4800 FIB_PROTOCOL_IP4,
4801 NULL,
4802 tm->hw[0]->sw_if_index,
4803 ~0, // invalid fib index
4804 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004805 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004806 FIB_ROUTE_PATH_FLAG_NONE);
4807 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4808 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4809
4810 /*
4811 * check for the presence of all the adj-fibs and local in the import table
4812 */
4813 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4814 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4815 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4816 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4817 local_pfx.fp_len = 32;
4818 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4819 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4820
4821 /*
4822 * add a 3rd adj-fib. expect it to be exported to both tables.
4823 */
4824 fib_prefix_t pfx_10_10_10_3_s_32 = {
4825 .fp_len = 32,
4826 .fp_proto = FIB_PROTOCOL_IP4,
4827 .fp_addr = {
4828 /* 10.10.10.3 */
4829 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4830 },
4831 };
4832
4833 fib_table_entry_update_one_path(fib_index,
4834 &pfx_10_10_10_3_s_32,
4835 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004836 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004837 FIB_PROTOCOL_IP4,
4838 &pfx_10_10_10_3_s_32.fp_addr,
4839 tm->hw[0]->sw_if_index,
4840 ~0, // invalid fib index
4841 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004842 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004843 FIB_ROUTE_PATH_FLAG_NONE);
4844 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4845 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
4846 ai = fib_entry_get_adj(fei);
4847
4848 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4849 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
4850 FIB_TEST((ai == fib_entry_get_adj(fei)),
4851 "Import uses same adj as export");
4852 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4853 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
4854 FIB_TEST((ai == fib_entry_get_adj(fei)),
4855 "Import uses same adj as export");
4856
4857 /*
4858 * remove the 3rd adj fib. we expect it to be removed from both FIBs
4859 */
4860 fib_table_entry_delete(fib_index,
4861 &pfx_10_10_10_3_s_32,
4862 FIB_SOURCE_ADJ);
4863
4864 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4865 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
4866
4867 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4868 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
4869
4870 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4871 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
4872
4873 /*
4874 * remove the attached route from the 2nd FIB. expect the imported
4875 * entires to be removed
4876 */
4877 local_pfx.fp_len = 24;
4878 fib_table_entry_delete(import_fib_index2,
4879 &local_pfx,
4880 FIB_SOURCE_API);
4881 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4882 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
4883
4884 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4885 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
4886 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4887 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
4888 local_pfx.fp_len = 32;
4889 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4890 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
4891
4892 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4893 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
4894 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4895 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
4896 local_pfx.fp_len = 32;
4897 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4898 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
4899
4900 /*
4901 * modify the route in FIB1 so it is no longer attached. expect the imported
4902 * entires to be removed
4903 */
4904 local_pfx.fp_len = 24;
4905 fib_table_entry_update_one_path(import_fib_index1,
4906 &local_pfx,
4907 FIB_SOURCE_API,
4908 FIB_ENTRY_FLAG_NONE,
4909 FIB_PROTOCOL_IP4,
4910 &pfx_10_10_10_2_s_32.fp_addr,
4911 tm->hw[0]->sw_if_index,
4912 ~0, // invalid fib index
4913 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004914 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004915 FIB_ROUTE_PATH_FLAG_NONE);
4916 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4917 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
4918 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4919 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4920 local_pfx.fp_len = 32;
4921 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4922 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4923
4924 /*
4925 * modify it back to attached. expect the adj-fibs back
4926 */
4927 local_pfx.fp_len = 24;
4928 fib_table_entry_update_one_path(import_fib_index1,
4929 &local_pfx,
4930 FIB_SOURCE_API,
4931 FIB_ENTRY_FLAG_NONE,
4932 FIB_PROTOCOL_IP4,
4933 NULL,
4934 tm->hw[0]->sw_if_index,
4935 ~0, // invalid fib index
4936 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004937 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004938 FIB_ROUTE_PATH_FLAG_NONE);
4939 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4940 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
4941 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4942 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
4943 local_pfx.fp_len = 32;
4944 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4945 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
4946
4947 /*
4948 * add a covering attached next-hop for the interface address, so we have
4949 * a valid adj to find when we check the forwarding tables
4950 */
4951 fib_prefix_t pfx_10_0_0_0_s_8 = {
4952 .fp_len = 8,
4953 .fp_proto = FIB_PROTOCOL_IP4,
4954 .fp_addr = {
4955 /* 10.0.0.0 */
4956 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
4957 },
4958 };
4959
4960 fei = fib_table_entry_update_one_path(fib_index,
4961 &pfx_10_0_0_0_s_8,
4962 FIB_SOURCE_API,
4963 FIB_ENTRY_FLAG_NONE,
4964 FIB_PROTOCOL_IP4,
4965 &pfx_10_10_10_3_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 dpo = fib_entry_contribute_ip_forwarding(fei);
4972
4973 /*
4974 * remove the route in the export fib. expect the adj-fibs to be removed
4975 */
4976 local_pfx.fp_len = 24;
4977 fib_table_entry_delete(fib_index,
4978 &local_pfx,
4979 FIB_SOURCE_INTERFACE);
4980
4981 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4982 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
4983 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4984 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4985 local_pfx.fp_len = 32;
4986 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4987 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4988
4989 /*
4990 * the adj-fibs in the export VRF are present in the FIB table,
4991 * but not installed in forwarding, since they have no attached cover.
4992 * Consequently a lookup in the MTRIE gives the adj for the covering
4993 * route 10.0.0.0/8.
4994 */
4995 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4996 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
4997
4998 index_t lbi;
4999 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5000 FIB_TEST(lbi == dpo->dpoi_index,
5001 "10.10.10.1 forwards on \n%U not \n%U",
5002 format_load_balance, lbi, 0,
5003 format_dpo_id, dpo, 0);
5004 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5005 FIB_TEST(lbi == dpo->dpoi_index,
5006 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5007 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5008 FIB_TEST(lbi == dpo->dpoi_index,
5009 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5010
5011 /*
5012 * add the export prefix back, but not as attached.
5013 * No adj-fibs in export nor import tables
5014 */
5015 local_pfx.fp_len = 24;
5016 fei = fib_table_entry_update_one_path(fib_index,
5017 &local_pfx,
5018 FIB_SOURCE_API,
5019 FIB_ENTRY_FLAG_NONE,
5020 FIB_PROTOCOL_IP4,
5021 &pfx_10_10_10_1_s_32.fp_addr,
5022 tm->hw[0]->sw_if_index,
5023 ~0, // invalid fib index
5024 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005025 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005026 FIB_ROUTE_PATH_FLAG_NONE);
5027 dpo = fib_entry_contribute_ip_forwarding(fei);
5028
5029 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5030 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5031 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5032 FIB_TEST(lbi == dpo->dpoi_index,
5033 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5034 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5035 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5036 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5037 FIB_TEST(lbi == dpo->dpoi_index,
5038 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5039
5040 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5041 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5042 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5043 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5044 local_pfx.fp_len = 32;
5045 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5046 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5047
5048 /*
5049 * modify the export prefix so it is attached. expect all covereds to return
5050 */
5051 local_pfx.fp_len = 24;
5052 fib_table_entry_update_one_path(fib_index,
5053 &local_pfx,
5054 FIB_SOURCE_API,
5055 FIB_ENTRY_FLAG_NONE,
5056 FIB_PROTOCOL_IP4,
5057 NULL,
5058 tm->hw[0]->sw_if_index,
5059 ~0, // invalid fib index
5060 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005061 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005062 FIB_ROUTE_PATH_FLAG_NONE);
5063
5064 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5065 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5066 dpo = fib_entry_contribute_ip_forwarding(fei);
5067 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5068 "Adj-fib1 is not drop in export");
5069 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5070 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5071 local_pfx.fp_len = 32;
5072 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5073 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5074 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5075 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5076 dpo = fib_entry_contribute_ip_forwarding(fei);
5077 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5078 "Adj-fib1 is not drop in export");
5079 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5080 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5081 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5082 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5083 local_pfx.fp_len = 32;
5084 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5085 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5086
5087 /*
5088 * modify the export prefix so connected. no change.
5089 */
5090 local_pfx.fp_len = 24;
5091 fib_table_entry_update_one_path(fib_index, &local_pfx,
5092 FIB_SOURCE_INTERFACE,
5093 (FIB_ENTRY_FLAG_CONNECTED |
5094 FIB_ENTRY_FLAG_ATTACHED),
5095 FIB_PROTOCOL_IP4,
5096 NULL,
5097 tm->hw[0]->sw_if_index,
5098 ~0,
5099 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005100 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005101 FIB_ROUTE_PATH_FLAG_NONE);
5102
5103 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5104 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5105 dpo = fib_entry_contribute_ip_forwarding(fei);
5106 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5107 "Adj-fib1 is not drop in export");
5108 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5109 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5110 local_pfx.fp_len = 32;
5111 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5112 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5113 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5114 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5115 dpo = fib_entry_contribute_ip_forwarding(fei);
5116 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5117 "Adj-fib1 is not drop in export");
5118 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5119 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5120 local_pfx.fp_len = 32;
5121 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5122 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5123
5124 /*
5125 * CLEANUP
5126 */
5127 fib_table_entry_delete(fib_index,
5128 &pfx_10_0_0_0_s_8,
5129 FIB_SOURCE_API);
5130 fib_table_entry_delete(fib_index,
5131 &pfx_10_10_10_1_s_32,
5132 FIB_SOURCE_ADJ);
5133 fib_table_entry_delete(fib_index,
5134 &pfx_10_10_10_2_s_32,
5135 FIB_SOURCE_ADJ);
5136 local_pfx.fp_len = 32;
5137 fib_table_entry_delete(fib_index,
5138 &local_pfx,
5139 FIB_SOURCE_INTERFACE);
5140 local_pfx.fp_len = 24;
5141 fib_table_entry_delete(fib_index,
5142 &local_pfx,
5143 FIB_SOURCE_API);
5144 fib_table_entry_delete(fib_index,
5145 &local_pfx,
5146 FIB_SOURCE_INTERFACE);
5147 local_pfx.fp_len = 24;
5148 fib_table_entry_delete(import_fib_index1,
5149 &local_pfx,
5150 FIB_SOURCE_API);
5151
5152 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5153 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5154
5155 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5156 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005157
5158 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005159}
5160
Neale Rannsad422ed2016-11-02 14:20:04 +00005161
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005162/*
5163 * Test the recursive route route handling for GRE tunnels
5164 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005165static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005166fib_test_label (void)
5167{
5168 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;
5169 const u32 fib_index = 0;
5170 test_main_t *tm;
5171 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005172 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005173
5174 lb_count = pool_elts(load_balance_pool);
5175 tm = &test_main;
5176 im = &ip4_main;
5177
5178 /*
5179 * add interface routes. We'll assume this works. It's more rigorously
5180 * tested elsewhere.
5181 */
5182 fib_prefix_t local0_pfx = {
5183 .fp_len = 24,
5184 .fp_proto = FIB_PROTOCOL_IP4,
5185 .fp_addr = {
5186 .ip4 = {
5187 /* 10.10.10.10 */
5188 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5189 },
5190 },
5191 };
5192
5193 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5194 adj_nbr_db_size());
5195
5196 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5197 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5198
5199 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5200 FIB_SOURCE_INTERFACE,
5201 (FIB_ENTRY_FLAG_CONNECTED |
5202 FIB_ENTRY_FLAG_ATTACHED),
5203 FIB_PROTOCOL_IP4,
5204 NULL,
5205 tm->hw[0]->sw_if_index,
5206 ~0,
5207 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005208 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005209 FIB_ROUTE_PATH_FLAG_NONE);
5210 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5211 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5212 "attached interface route present");
5213
5214 local0_pfx.fp_len = 32;
5215 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5216 FIB_SOURCE_INTERFACE,
5217 (FIB_ENTRY_FLAG_CONNECTED |
5218 FIB_ENTRY_FLAG_LOCAL),
5219 FIB_PROTOCOL_IP4,
5220 NULL,
5221 tm->hw[0]->sw_if_index,
5222 ~0, // invalid fib index
5223 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005224 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005225 FIB_ROUTE_PATH_FLAG_NONE);
5226 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5227
5228 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5229 "local interface route present");
5230
5231 fib_prefix_t local1_pfx = {
5232 .fp_len = 24,
5233 .fp_proto = FIB_PROTOCOL_IP4,
5234 .fp_addr = {
5235 .ip4 = {
5236 /* 10.10.11.10 */
5237 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5238 },
5239 },
5240 };
5241
5242 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5243 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5244
5245 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5246 FIB_SOURCE_INTERFACE,
5247 (FIB_ENTRY_FLAG_CONNECTED |
5248 FIB_ENTRY_FLAG_ATTACHED),
5249 FIB_PROTOCOL_IP4,
5250 NULL,
5251 tm->hw[1]->sw_if_index,
5252 ~0,
5253 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005254 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005255 FIB_ROUTE_PATH_FLAG_NONE);
5256 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5257 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5258 "attached interface route present");
5259
5260 local1_pfx.fp_len = 32;
5261 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5262 FIB_SOURCE_INTERFACE,
5263 (FIB_ENTRY_FLAG_CONNECTED |
5264 FIB_ENTRY_FLAG_LOCAL),
5265 FIB_PROTOCOL_IP4,
5266 NULL,
5267 tm->hw[1]->sw_if_index,
5268 ~0, // invalid fib index
5269 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005270 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005271 FIB_ROUTE_PATH_FLAG_NONE);
5272 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5273
5274 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5275 "local interface route present");
5276
5277 ip46_address_t nh_10_10_10_1 = {
5278 .ip4 = {
5279 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5280 },
5281 };
5282 ip46_address_t nh_10_10_11_1 = {
5283 .ip4 = {
5284 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5285 },
5286 };
5287 ip46_address_t nh_10_10_11_2 = {
5288 .ip4 = {
5289 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5290 },
5291 };
5292
5293 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005294 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005295 &nh_10_10_11_1,
5296 tm->hw[1]->sw_if_index);
5297 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005298 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005299 &nh_10_10_11_2,
5300 tm->hw[1]->sw_if_index);
5301 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005302 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005303 &nh_10_10_10_1,
5304 tm->hw[0]->sw_if_index);
5305 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005306 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005307 &nh_10_10_11_2,
5308 tm->hw[1]->sw_if_index);
5309 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005310 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005311 &nh_10_10_11_1,
5312 tm->hw[1]->sw_if_index);
5313
5314 /*
5315 * Add an etry with one path with a real out-going label
5316 */
5317 fib_prefix_t pfx_1_1_1_1_s_32 = {
5318 .fp_len = 32,
5319 .fp_proto = FIB_PROTOCOL_IP4,
5320 .fp_addr = {
5321 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5322 },
5323 };
5324 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5325 .type = FT_LB_LABEL_O_ADJ,
5326 .label_o_adj = {
5327 .adj = ai_mpls_10_10_10_1,
5328 .label = 99,
5329 .eos = MPLS_EOS,
5330 },
5331 };
5332 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5333 .type = FT_LB_LABEL_O_ADJ,
5334 .label_o_adj = {
5335 .adj = ai_mpls_10_10_10_1,
5336 .label = 99,
5337 .eos = MPLS_NON_EOS,
5338 },
5339 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005340 mpls_label_t *l99 = NULL;
5341 vec_add1(l99, 99);
5342
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005343 fib_table_entry_update_one_path(fib_index,
5344 &pfx_1_1_1_1_s_32,
5345 FIB_SOURCE_API,
5346 FIB_ENTRY_FLAG_NONE,
5347 FIB_PROTOCOL_IP4,
5348 &nh_10_10_10_1,
5349 tm->hw[0]->sw_if_index,
5350 ~0, // invalid fib index
5351 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005352 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005353 FIB_ROUTE_PATH_FLAG_NONE);
5354
5355 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5356 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5357
5358 FIB_TEST(fib_test_validate_entry(fei,
5359 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5360 1,
5361 &l99_eos_o_10_10_10_1),
5362 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5363
5364 /*
5365 * add a path with an implicit NULL label
5366 */
5367 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5368 .type = FT_LB_ADJ,
5369 .adj = {
5370 .adj = ai_v4_10_10_11_1,
5371 },
5372 };
5373 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5374 .type = FT_LB_ADJ,
5375 .adj = {
5376 .adj = ai_mpls_10_10_11_1,
5377 },
5378 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005379 mpls_label_t *l_imp_null = NULL;
5380 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005381
5382 fei = fib_table_entry_path_add(fib_index,
5383 &pfx_1_1_1_1_s_32,
5384 FIB_SOURCE_API,
5385 FIB_ENTRY_FLAG_NONE,
5386 FIB_PROTOCOL_IP4,
5387 &nh_10_10_11_1,
5388 tm->hw[1]->sw_if_index,
5389 ~0, // invalid fib index
5390 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005391 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005392 FIB_ROUTE_PATH_FLAG_NONE);
5393
5394 FIB_TEST(fib_test_validate_entry(fei,
5395 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5396 2,
5397 &l99_eos_o_10_10_10_1,
5398 &a_o_10_10_11_1),
5399 "1.1.1.1/32 LB 2 buckets via: "
5400 "label 99 over 10.10.10.1, "
5401 "adj over 10.10.11.1");
5402
5403 /*
5404 * assign the route a local label
5405 */
5406 fib_table_entry_local_label_add(fib_index,
5407 &pfx_1_1_1_1_s_32,
5408 24001);
5409
5410 fib_prefix_t pfx_24001_eos = {
5411 .fp_proto = FIB_PROTOCOL_MPLS,
5412 .fp_label = 24001,
5413 .fp_eos = MPLS_EOS,
5414 };
5415 fib_prefix_t pfx_24001_neos = {
5416 .fp_proto = FIB_PROTOCOL_MPLS,
5417 .fp_label = 24001,
5418 .fp_eos = MPLS_NON_EOS,
5419 };
5420
5421 /*
5422 * The EOS entry should link to both the paths,
5423 * and use an ip adj for the imp-null
5424 * The NON-EOS entry should link to both the paths,
5425 * and use an mpls adj for the imp-null
5426 */
5427 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5428 &pfx_24001_eos);
5429 FIB_TEST(fib_test_validate_entry(fei,
5430 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5431 2,
5432 &l99_eos_o_10_10_10_1,
5433 &a_o_10_10_11_1),
5434 "24001/eos LB 2 buckets via: "
5435 "label 99 over 10.10.10.1, "
5436 "adj over 10.10.11.1");
5437
5438
5439 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5440 &pfx_24001_neos);
5441 FIB_TEST(fib_test_validate_entry(fei,
5442 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5443 2,
5444 &l99_neos_o_10_10_10_1,
5445 &a_mpls_o_10_10_11_1),
5446 "24001/neos LB 1 bucket via: "
5447 "label 99 over 10.10.10.1 ",
5448 "mpls-adj via 10.10.11.1");
5449
5450 /*
5451 * add an unlabelled path, this is excluded from the neos chains,
5452 */
5453 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5454 .type = FT_LB_ADJ,
5455 .adj = {
5456 .adj = ai_v4_10_10_11_2,
5457 },
5458 };
5459
5460 fei = fib_table_entry_path_add(fib_index,
5461 &pfx_1_1_1_1_s_32,
5462 FIB_SOURCE_API,
5463 FIB_ENTRY_FLAG_NONE,
5464 FIB_PROTOCOL_IP4,
5465 &nh_10_10_11_2,
5466 tm->hw[1]->sw_if_index,
5467 ~0, // invalid fib index
5468 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005469 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005470 FIB_ROUTE_PATH_FLAG_NONE);
5471
5472 FIB_TEST(fib_test_validate_entry(fei,
5473 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5474 16, // 3 choices spread over 16 buckets
5475 &l99_eos_o_10_10_10_1,
5476 &l99_eos_o_10_10_10_1,
5477 &l99_eos_o_10_10_10_1,
5478 &l99_eos_o_10_10_10_1,
5479 &l99_eos_o_10_10_10_1,
5480 &l99_eos_o_10_10_10_1,
5481 &a_o_10_10_11_1,
5482 &a_o_10_10_11_1,
5483 &a_o_10_10_11_1,
5484 &a_o_10_10_11_1,
5485 &a_o_10_10_11_1,
5486 &adj_o_10_10_11_2,
5487 &adj_o_10_10_11_2,
5488 &adj_o_10_10_11_2,
5489 &adj_o_10_10_11_2,
5490 &adj_o_10_10_11_2),
5491 "1.1.1.1/32 LB 16 buckets via: "
5492 "label 99 over 10.10.10.1, "
5493 "adj over 10.10.11.1",
5494 "adj over 10.10.11.2");
5495
5496 /*
5497 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5498 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005499 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005500 fib_entry_contribute_forwarding(fei,
5501 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5502 &non_eos_1_1_1_1);
5503
5504 /*
5505 * n-eos has only the 2 labelled paths
5506 */
5507 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5508 &pfx_24001_neos);
5509
5510 FIB_TEST(fib_test_validate_entry(fei,
5511 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5512 2,
5513 &l99_neos_o_10_10_10_1,
5514 &a_mpls_o_10_10_11_1),
5515 "24001/neos LB 2 buckets via: "
5516 "label 99 over 10.10.10.1, "
5517 "adj-mpls over 10.10.11.2");
5518
5519 /*
5520 * A labelled recursive
5521 */
5522 fib_prefix_t pfx_2_2_2_2_s_32 = {
5523 .fp_len = 32,
5524 .fp_proto = FIB_PROTOCOL_IP4,
5525 .fp_addr = {
5526 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5527 },
5528 };
5529 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5530 .type = FT_LB_LABEL_O_LB,
5531 .label_o_lb = {
5532 .lb = non_eos_1_1_1_1.dpoi_index,
5533 .label = 1600,
5534 .eos = MPLS_EOS,
5535 },
5536 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005537 mpls_label_t *l1600 = NULL;
5538 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005539
5540 fib_table_entry_update_one_path(fib_index,
5541 &pfx_2_2_2_2_s_32,
5542 FIB_SOURCE_API,
5543 FIB_ENTRY_FLAG_NONE,
5544 FIB_PROTOCOL_IP4,
5545 &pfx_1_1_1_1_s_32.fp_addr,
5546 ~0,
5547 fib_index,
5548 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005549 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005550 FIB_ROUTE_PATH_FLAG_NONE);
5551
5552 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5553 FIB_TEST(fib_test_validate_entry(fei,
5554 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5555 1,
5556 &l1600_eos_o_1_1_1_1),
5557 "2.2.2.2.2/32 LB 1 buckets via: "
5558 "label 1600 over 1.1.1.1");
5559
Neale Ranns948e00f2016-10-20 13:39:34 +01005560 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005561 index_t urpfi;
5562
5563 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5564 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5565
5566 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5567 "uRPF check for 2.2.2.2/32 on %d OK",
5568 tm->hw[0]->sw_if_index);
5569 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5570 "uRPF check for 2.2.2.2/32 on %d OK",
5571 tm->hw[1]->sw_if_index);
5572 FIB_TEST(!fib_urpf_check(urpfi, 99),
5573 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5574 99);
5575
5576 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5577 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5578 "Shared uRPF on IP and non-EOS chain");
5579
5580 dpo_reset(&dpo_44);
5581
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005582 /*
5583 * we are holding a lock on the non-eos LB of the via-entry.
5584 * do a PIC-core failover by shutting the link of the via-entry.
5585 *
5586 * shut down the link with the valid label
5587 */
5588 vnet_sw_interface_set_flags(vnet_get_main(),
5589 tm->hw[0]->sw_if_index,
5590 0);
5591
5592 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5593 FIB_TEST(fib_test_validate_entry(fei,
5594 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5595 2,
5596 &a_o_10_10_11_1,
5597 &adj_o_10_10_11_2),
5598 "1.1.1.1/32 LB 2 buckets via: "
5599 "adj over 10.10.11.1, ",
5600 "adj-v4 over 10.10.11.2");
5601
5602 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5603 &pfx_24001_eos);
5604 FIB_TEST(fib_test_validate_entry(fei,
5605 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5606 2,
5607 &a_o_10_10_11_1,
5608 &adj_o_10_10_11_2),
5609 "24001/eos LB 2 buckets via: "
5610 "adj over 10.10.11.1, ",
5611 "adj-v4 over 10.10.11.2");
5612
5613 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5614 &pfx_24001_neos);
5615 FIB_TEST(fib_test_validate_entry(fei,
5616 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5617 1,
5618 &a_mpls_o_10_10_11_1),
5619 "24001/neos LB 1 buckets via: "
5620 "adj-mpls over 10.10.11.2");
5621
5622 /*
5623 * test that the pre-failover load-balance has been in-place
5624 * modified
5625 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005626 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005627 fib_entry_contribute_forwarding(fei,
5628 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5629 &current);
5630
5631 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5632 &current),
5633 "PIC-core LB inplace modified %U %U",
5634 format_dpo_id, &non_eos_1_1_1_1, 0,
5635 format_dpo_id, &current, 0);
5636
5637 dpo_reset(&non_eos_1_1_1_1);
5638 dpo_reset(&current);
5639
5640 /*
5641 * no-shut the link with the valid label
5642 */
5643 vnet_sw_interface_set_flags(vnet_get_main(),
5644 tm->hw[0]->sw_if_index,
5645 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5646
5647 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5648 FIB_TEST(fib_test_validate_entry(fei,
5649 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5650 16, // 3 choices spread over 16 buckets
5651 &l99_eos_o_10_10_10_1,
5652 &l99_eos_o_10_10_10_1,
5653 &l99_eos_o_10_10_10_1,
5654 &l99_eos_o_10_10_10_1,
5655 &l99_eos_o_10_10_10_1,
5656 &l99_eos_o_10_10_10_1,
5657 &a_o_10_10_11_1,
5658 &a_o_10_10_11_1,
5659 &a_o_10_10_11_1,
5660 &a_o_10_10_11_1,
5661 &a_o_10_10_11_1,
5662 &adj_o_10_10_11_2,
5663 &adj_o_10_10_11_2,
5664 &adj_o_10_10_11_2,
5665 &adj_o_10_10_11_2,
5666 &adj_o_10_10_11_2),
5667 "1.1.1.1/32 LB 16 buckets via: "
5668 "label 99 over 10.10.10.1, "
5669 "adj over 10.10.11.1",
5670 "adj-v4 over 10.10.11.2");
5671
5672
5673 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5674 &pfx_24001_eos);
5675 FIB_TEST(fib_test_validate_entry(fei,
5676 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5677 16, // 3 choices spread over 16 buckets
5678 &l99_eos_o_10_10_10_1,
5679 &l99_eos_o_10_10_10_1,
5680 &l99_eos_o_10_10_10_1,
5681 &l99_eos_o_10_10_10_1,
5682 &l99_eos_o_10_10_10_1,
5683 &l99_eos_o_10_10_10_1,
5684 &a_o_10_10_11_1,
5685 &a_o_10_10_11_1,
5686 &a_o_10_10_11_1,
5687 &a_o_10_10_11_1,
5688 &a_o_10_10_11_1,
5689 &adj_o_10_10_11_2,
5690 &adj_o_10_10_11_2,
5691 &adj_o_10_10_11_2,
5692 &adj_o_10_10_11_2,
5693 &adj_o_10_10_11_2),
5694 "24001/eos LB 16 buckets via: "
5695 "label 99 over 10.10.10.1, "
5696 "adj over 10.10.11.1",
5697 "adj-v4 over 10.10.11.2");
5698
5699 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5700 &pfx_24001_neos);
5701 FIB_TEST(fib_test_validate_entry(fei,
5702 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5703 2,
5704 &l99_neos_o_10_10_10_1,
5705 &a_mpls_o_10_10_11_1),
5706 "24001/neos LB 2 buckets via: "
5707 "label 99 over 10.10.10.1, "
5708 "adj-mpls over 10.10.11.2");
5709
5710 /*
5711 * remove the first path with the valid label
5712 */
5713 fib_table_entry_path_remove(fib_index,
5714 &pfx_1_1_1_1_s_32,
5715 FIB_SOURCE_API,
5716 FIB_PROTOCOL_IP4,
5717 &nh_10_10_10_1,
5718 tm->hw[0]->sw_if_index,
5719 ~0, // invalid fib index
5720 1,
5721 FIB_ROUTE_PATH_FLAG_NONE);
5722
5723 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5724 FIB_TEST(fib_test_validate_entry(fei,
5725 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5726 2,
5727 &a_o_10_10_11_1,
5728 &adj_o_10_10_11_2),
5729 "1.1.1.1/32 LB 2 buckets via: "
5730 "adj over 10.10.11.1",
5731 "adj-v4 over 10.10.11.2");
5732
5733 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5734 &pfx_24001_eos);
5735 FIB_TEST(fib_test_validate_entry(fei,
5736 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5737 2,
5738 &a_o_10_10_11_1,
5739 &adj_o_10_10_11_2),
5740 "24001/eos LB 2 buckets via: "
5741 "adj over 10.10.11.1",
5742 "adj-v4 over 10.10.11.2");
5743
5744 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5745 &pfx_24001_neos);
5746
5747 FIB_TEST(fib_test_validate_entry(fei,
5748 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5749 1,
5750 &a_mpls_o_10_10_11_1),
5751 "24001/neos LB 1 buckets via: "
5752 "adj-mpls over 10.10.11.2");
5753
5754 /*
5755 * remove the other path with a valid label
5756 */
5757 fib_test_lb_bucket_t bucket_drop = {
5758 .type = FT_LB_SPECIAL,
5759 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005760 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005761 },
5762 };
5763
5764 fib_table_entry_path_remove(fib_index,
5765 &pfx_1_1_1_1_s_32,
5766 FIB_SOURCE_API,
5767 FIB_PROTOCOL_IP4,
5768 &nh_10_10_11_1,
5769 tm->hw[1]->sw_if_index,
5770 ~0, // invalid fib index
5771 1,
5772 FIB_ROUTE_PATH_FLAG_NONE);
5773
5774 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5775 FIB_TEST(fib_test_validate_entry(fei,
5776 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5777 1,
5778 &adj_o_10_10_11_2),
5779 "1.1.1.1/32 LB 1 buckets via: "
5780 "adj over 10.10.11.2");
5781
5782 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5783 &pfx_24001_eos);
5784 FIB_TEST(fib_test_validate_entry(fei,
5785 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5786 1,
5787 &adj_o_10_10_11_2),
5788 "24001/eos LB 1 buckets via: "
5789 "adj over 10.10.11.2");
5790
5791 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5792 &pfx_24001_neos);
5793 FIB_TEST(fib_test_validate_entry(fei,
5794 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5795 1,
5796 &bucket_drop),
5797 "24001/eos LB 1 buckets via: DROP");
5798
5799 /*
5800 * add back the path with the valid label
5801 */
Neale Rannsad422ed2016-11-02 14:20:04 +00005802 l99 = NULL;
5803 vec_add1(l99, 99);
5804
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005805 fib_table_entry_path_add(fib_index,
5806 &pfx_1_1_1_1_s_32,
5807 FIB_SOURCE_API,
5808 FIB_ENTRY_FLAG_NONE,
5809 FIB_PROTOCOL_IP4,
5810 &nh_10_10_10_1,
5811 tm->hw[0]->sw_if_index,
5812 ~0, // invalid fib index
5813 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005814 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005815 FIB_ROUTE_PATH_FLAG_NONE);
5816
5817 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5818 FIB_TEST(fib_test_validate_entry(fei,
5819 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5820 2,
5821 &l99_eos_o_10_10_10_1,
5822 &adj_o_10_10_11_2),
5823 "1.1.1.1/32 LB 2 buckets via: "
5824 "label 99 over 10.10.10.1, "
5825 "adj over 10.10.11.2");
5826
5827 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5828 &pfx_24001_eos);
5829 FIB_TEST(fib_test_validate_entry(fei,
5830 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5831 2,
5832 &l99_eos_o_10_10_10_1,
5833 &adj_o_10_10_11_2),
5834 "24001/eos LB 2 buckets via: "
5835 "label 99 over 10.10.10.1, "
5836 "adj over 10.10.11.2");
5837
5838 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5839 &pfx_24001_neos);
5840 FIB_TEST(fib_test_validate_entry(fei,
5841 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5842 1,
5843 &l99_neos_o_10_10_10_1),
5844 "24001/neos LB 1 buckets via: "
5845 "label 99 over 10.10.10.1");
5846
5847 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07005848 * change the local label
5849 */
5850 fib_table_entry_local_label_add(fib_index,
5851 &pfx_1_1_1_1_s_32,
5852 25005);
5853
5854 fib_prefix_t pfx_25005_eos = {
5855 .fp_proto = FIB_PROTOCOL_MPLS,
5856 .fp_label = 25005,
5857 .fp_eos = MPLS_EOS,
5858 };
5859 fib_prefix_t pfx_25005_neos = {
5860 .fp_proto = FIB_PROTOCOL_MPLS,
5861 .fp_label = 25005,
5862 .fp_eos = MPLS_NON_EOS,
5863 };
5864
5865 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5866 fib_table_lookup(fib_index, &pfx_24001_eos)),
5867 "24001/eos removed after label change");
5868 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5869 fib_table_lookup(fib_index, &pfx_24001_neos)),
5870 "24001/eos removed after label change");
5871
5872 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5873 &pfx_25005_eos);
5874 FIB_TEST(fib_test_validate_entry(fei,
5875 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5876 2,
5877 &l99_eos_o_10_10_10_1,
5878 &adj_o_10_10_11_2),
5879 "25005/eos LB 2 buckets via: "
5880 "label 99 over 10.10.10.1, "
5881 "adj over 10.10.11.2");
5882
5883 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5884 &pfx_25005_neos);
5885 FIB_TEST(fib_test_validate_entry(fei,
5886 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5887 1,
5888 &l99_neos_o_10_10_10_1),
5889 "25005/neos LB 1 buckets via: "
5890 "label 99 over 10.10.10.1");
5891
5892 /*
5893 * remove the local label.
5894 * the check that the MPLS entries are gone is done by the fact the
5895 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005896 */
5897 fib_table_entry_local_label_remove(fib_index,
5898 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07005899 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005900
5901 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5902 FIB_TEST(fib_test_validate_entry(fei,
5903 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5904 2,
5905 &l99_eos_o_10_10_10_1,
5906 &adj_o_10_10_11_2),
5907 "24001/eos LB 2 buckets via: "
5908 "label 99 over 10.10.10.1, "
5909 "adj over 10.10.11.2");
5910
5911 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5912 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
5913 "No more MPLS FIB entries => table removed");
5914
5915 /*
5916 * add another via-entry for the recursive
5917 */
5918 fib_prefix_t pfx_1_1_1_2_s_32 = {
5919 .fp_len = 32,
5920 .fp_proto = FIB_PROTOCOL_IP4,
5921 .fp_addr = {
5922 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
5923 },
5924 };
5925 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
5926 .type = FT_LB_LABEL_O_ADJ,
5927 .label_o_adj = {
5928 .adj = ai_mpls_10_10_10_1,
5929 .label = 101,
5930 .eos = MPLS_EOS,
5931 },
5932 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005933 mpls_label_t *l101 = NULL;
5934 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005935
5936 fei = fib_table_entry_update_one_path(fib_index,
5937 &pfx_1_1_1_2_s_32,
5938 FIB_SOURCE_API,
5939 FIB_ENTRY_FLAG_NONE,
5940 FIB_PROTOCOL_IP4,
5941 &nh_10_10_10_1,
5942 tm->hw[0]->sw_if_index,
5943 ~0, // invalid fib index
5944 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005945 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005946 FIB_ROUTE_PATH_FLAG_NONE);
5947
5948 FIB_TEST(fib_test_validate_entry(fei,
5949 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5950 1,
5951 &l101_eos_o_10_10_10_1),
5952 "1.1.1.2/32 LB 1 buckets via: "
5953 "label 101 over 10.10.10.1");
5954
Neale Ranns948e00f2016-10-20 13:39:34 +01005955 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005956 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5957 &pfx_1_1_1_1_s_32),
5958 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5959 &non_eos_1_1_1_1);
5960 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5961 &pfx_1_1_1_2_s_32),
5962 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5963 &non_eos_1_1_1_2);
5964
5965 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
5966 .type = FT_LB_LABEL_O_LB,
5967 .label_o_lb = {
5968 .lb = non_eos_1_1_1_2.dpoi_index,
5969 .label = 1601,
5970 .eos = MPLS_EOS,
5971 },
5972 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005973 mpls_label_t *l1601 = NULL;
5974 vec_add1(l1601, 1601);
5975
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005976 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
5977
5978 fei = fib_table_entry_path_add(fib_index,
5979 &pfx_2_2_2_2_s_32,
5980 FIB_SOURCE_API,
5981 FIB_ENTRY_FLAG_NONE,
5982 FIB_PROTOCOL_IP4,
5983 &pfx_1_1_1_2_s_32.fp_addr,
5984 ~0,
5985 fib_index,
5986 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005987 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005988 FIB_ROUTE_PATH_FLAG_NONE);
5989
5990 FIB_TEST(fib_test_validate_entry(fei,
5991 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5992 2,
5993 &l1600_eos_o_1_1_1_1,
5994 &l1601_eos_o_1_1_1_2),
5995 "2.2.2.2/32 LB 2 buckets via: "
5996 "label 1600 via 1.1,1.1, "
5997 "label 16001 via 1.1.1.2");
5998
5999 /*
6000 * update the via-entry so it no longer has an imp-null path.
6001 * the LB for the recursive can use an imp-null
6002 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006003 l_imp_null = NULL;
6004 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6005
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006006 fei = fib_table_entry_update_one_path(fib_index,
6007 &pfx_1_1_1_2_s_32,
6008 FIB_SOURCE_API,
6009 FIB_ENTRY_FLAG_NONE,
6010 FIB_PROTOCOL_IP4,
6011 &nh_10_10_11_1,
6012 tm->hw[1]->sw_if_index,
6013 ~0, // invalid fib index
6014 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006015 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006016 FIB_ROUTE_PATH_FLAG_NONE);
6017
6018 FIB_TEST(fib_test_validate_entry(fei,
6019 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6020 1,
6021 &a_o_10_10_11_1),
6022 "1.1.1.2/32 LB 1 buckets via: "
6023 "adj 10.10.11.1");
6024
6025 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6026 FIB_TEST(fib_test_validate_entry(fei,
6027 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6028 2,
6029 &l1600_eos_o_1_1_1_1,
6030 &l1601_eos_o_1_1_1_2),
6031 "2.2.2.2/32 LB 2 buckets via: "
6032 "label 1600 via 1.1,1.1, "
6033 "label 16001 via 1.1.1.2");
6034
6035 /*
6036 * update the via-entry so it no longer has labelled paths.
6037 * the LB for the recursive should exclue this via form its LB
6038 */
6039 fei = fib_table_entry_update_one_path(fib_index,
6040 &pfx_1_1_1_2_s_32,
6041 FIB_SOURCE_API,
6042 FIB_ENTRY_FLAG_NONE,
6043 FIB_PROTOCOL_IP4,
6044 &nh_10_10_11_1,
6045 tm->hw[1]->sw_if_index,
6046 ~0, // invalid fib index
6047 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006048 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006049 FIB_ROUTE_PATH_FLAG_NONE);
6050
6051 FIB_TEST(fib_test_validate_entry(fei,
6052 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6053 1,
6054 &a_o_10_10_11_1),
6055 "1.1.1.2/32 LB 1 buckets via: "
6056 "adj 10.10.11.1");
6057
6058 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6059 FIB_TEST(fib_test_validate_entry(fei,
6060 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6061 1,
6062 &l1600_eos_o_1_1_1_1),
6063 "2.2.2.2/32 LB 1 buckets via: "
6064 "label 1600 via 1.1,1.1");
6065
6066 dpo_reset(&non_eos_1_1_1_1);
6067 dpo_reset(&non_eos_1_1_1_2);
6068
6069 /*
6070 * Add a recursive with no out-labels. We expect to use the IP of the via
6071 */
6072 fib_prefix_t pfx_2_2_2_3_s_32 = {
6073 .fp_len = 32,
6074 .fp_proto = FIB_PROTOCOL_IP4,
6075 .fp_addr = {
6076 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6077 },
6078 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006079 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006080
6081 fib_table_entry_update_one_path(fib_index,
6082 &pfx_2_2_2_3_s_32,
6083 FIB_SOURCE_API,
6084 FIB_ENTRY_FLAG_NONE,
6085 FIB_PROTOCOL_IP4,
6086 &pfx_1_1_1_1_s_32.fp_addr,
6087 ~0,
6088 fib_index,
6089 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006090 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006091 FIB_ROUTE_PATH_FLAG_NONE);
6092
6093 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6094 &pfx_1_1_1_1_s_32),
6095 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6096 &ip_1_1_1_1);
6097
6098 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6099 .type = FT_LB_O_LB,
6100 .lb = {
6101 .lb = ip_1_1_1_1.dpoi_index,
6102 },
6103 };
6104
6105 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6106 FIB_TEST(fib_test_validate_entry(fei,
6107 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6108 1,
6109 &ip_o_1_1_1_1),
6110 "2.2.2.2.3/32 LB 1 buckets via: "
6111 "ip 1.1.1.1");
6112
6113 /*
6114 * Add a recursive with an imp-null out-label.
6115 * We expect to use the IP of the via
6116 */
6117 fib_prefix_t pfx_2_2_2_4_s_32 = {
6118 .fp_len = 32,
6119 .fp_proto = FIB_PROTOCOL_IP4,
6120 .fp_addr = {
6121 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6122 },
6123 };
6124
6125 fib_table_entry_update_one_path(fib_index,
6126 &pfx_2_2_2_4_s_32,
6127 FIB_SOURCE_API,
6128 FIB_ENTRY_FLAG_NONE,
6129 FIB_PROTOCOL_IP4,
6130 &pfx_1_1_1_1_s_32.fp_addr,
6131 ~0,
6132 fib_index,
6133 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006134 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006135 FIB_ROUTE_PATH_FLAG_NONE);
6136
6137 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6138 FIB_TEST(fib_test_validate_entry(fei,
6139 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6140 1,
6141 &ip_o_1_1_1_1),
6142 "2.2.2.2.4/32 LB 1 buckets via: "
6143 "ip 1.1.1.1");
6144
6145 dpo_reset(&ip_1_1_1_1);
6146
6147 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006148 * Create an entry with a deep label stack
6149 */
6150 fib_prefix_t pfx_2_2_5_5_s_32 = {
6151 .fp_len = 32,
6152 .fp_proto = FIB_PROTOCOL_IP4,
6153 .fp_addr = {
6154 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6155 },
6156 };
6157 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6158 .type = FT_LB_LABEL_STACK_O_ADJ,
6159 .label_stack_o_adj = {
6160 .adj = ai_mpls_10_10_11_1,
6161 .label_stack_size = 8,
6162 .label_stack = {
6163 200, 201, 202, 203, 204, 205, 206, 207
6164 },
6165 .eos = MPLS_EOS,
6166 },
6167 };
6168 mpls_label_t *label_stack = NULL;
6169 vec_validate(label_stack, 7);
6170 for (ii = 0; ii < 8; ii++)
6171 {
6172 label_stack[ii] = ii + 200;
6173 }
6174
6175 fei = fib_table_entry_update_one_path(fib_index,
6176 &pfx_2_2_5_5_s_32,
6177 FIB_SOURCE_API,
6178 FIB_ENTRY_FLAG_NONE,
6179 FIB_PROTOCOL_IP4,
6180 &nh_10_10_11_1,
6181 tm->hw[1]->sw_if_index,
6182 ~0, // invalid fib index
6183 1,
6184 label_stack,
6185 FIB_ROUTE_PATH_FLAG_NONE);
6186
6187 FIB_TEST(fib_test_validate_entry(fei,
6188 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6189 1,
6190 &ls_eos_o_10_10_10_1),
6191 "2.2.5.5/32 LB 1 buckets via: "
6192 "adj 10.10.11.1");
6193 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6194
6195 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006196 * cleanup
6197 */
6198 fib_table_entry_delete(fib_index,
6199 &pfx_1_1_1_2_s_32,
6200 FIB_SOURCE_API);
6201
6202 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6203 FIB_TEST(fib_test_validate_entry(fei,
6204 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6205 1,
6206 &l1600_eos_o_1_1_1_1),
6207 "2.2.2.2/32 LB 1 buckets via: "
6208 "label 1600 via 1.1,1.1");
6209
6210 fib_table_entry_delete(fib_index,
6211 &pfx_1_1_1_1_s_32,
6212 FIB_SOURCE_API);
6213
6214 FIB_TEST(fib_test_validate_entry(fei,
6215 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6216 1,
6217 &bucket_drop),
6218 "2.2.2.2/32 LB 1 buckets via: DROP");
6219
6220 fib_table_entry_delete(fib_index,
6221 &pfx_2_2_2_2_s_32,
6222 FIB_SOURCE_API);
6223 fib_table_entry_delete(fib_index,
6224 &pfx_2_2_2_3_s_32,
6225 FIB_SOURCE_API);
6226 fib_table_entry_delete(fib_index,
6227 &pfx_2_2_2_4_s_32,
6228 FIB_SOURCE_API);
6229
6230 adj_unlock(ai_mpls_10_10_10_1);
6231 adj_unlock(ai_mpls_10_10_11_2);
6232 adj_unlock(ai_v4_10_10_11_1);
6233 adj_unlock(ai_v4_10_10_11_2);
6234 adj_unlock(ai_mpls_10_10_11_1);
6235
6236 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6237 adj_nbr_db_size());
6238
6239 local0_pfx.fp_len = 32;
6240 fib_table_entry_delete(fib_index,
6241 &local0_pfx,
6242 FIB_SOURCE_INTERFACE);
6243 local0_pfx.fp_len = 24;
6244 fib_table_entry_delete(fib_index,
6245 &local0_pfx,
6246 FIB_SOURCE_INTERFACE);
6247 local1_pfx.fp_len = 32;
6248 fib_table_entry_delete(fib_index,
6249 &local1_pfx,
6250 FIB_SOURCE_INTERFACE);
6251 local1_pfx.fp_len = 24;
6252 fib_table_entry_delete(fib_index,
6253 &local1_pfx,
6254 FIB_SOURCE_INTERFACE);
6255
6256 /*
6257 * +1 for the drop LB in the MPLS tables.
6258 */
6259 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6260 "Load-balance resources freed %d of %d",
6261 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006262
6263 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006264}
6265
6266#define N_TEST_CHILDREN 4
6267#define PARENT_INDEX 0
6268
6269typedef struct fib_node_test_t_
6270{
6271 fib_node_t node;
6272 u32 sibling;
6273 u32 index;
6274 fib_node_back_walk_ctx_t *ctxs;
6275 u32 destroyed;
6276} fib_node_test_t;
6277
6278static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6279
6280#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6281
6282#define FOR_EACH_TEST_CHILD(_tc) \
6283 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6284 ii < N_TEST_CHILDREN+1; \
6285 ii++, (_tc) = &fib_test_nodes[ii])
6286
6287static fib_node_t *
6288fib_test_child_get_node (fib_node_index_t index)
6289{
6290 return (&fib_test_nodes[index].node);
6291}
6292
6293static int fib_test_walk_spawns_walks;
6294
6295static fib_node_back_walk_rc_t
6296fib_test_child_back_walk_notify (fib_node_t *node,
6297 fib_node_back_walk_ctx_t *ctx)
6298{
6299 fib_node_test_t *tc = (fib_node_test_t*) node;
6300
6301 vec_add1(tc->ctxs, *ctx);
6302
6303 if (1 == fib_test_walk_spawns_walks)
6304 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6305 if (2 == fib_test_walk_spawns_walks)
6306 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6307 FIB_WALK_PRIORITY_HIGH, ctx);
6308
6309 return (FIB_NODE_BACK_WALK_CONTINUE);
6310}
6311
6312static void
6313fib_test_child_last_lock_gone (fib_node_t *node)
6314{
6315 fib_node_test_t *tc = (fib_node_test_t *)node;
6316
6317 tc->destroyed = 1;
6318}
6319
6320/**
6321 * The FIB walk's graph node virtual function table
6322 */
6323static const fib_node_vft_t fib_test_child_vft = {
6324 .fnv_get = fib_test_child_get_node,
6325 .fnv_last_lock = fib_test_child_last_lock_gone,
6326 .fnv_back_walk = fib_test_child_back_walk_notify,
6327};
6328
6329/*
6330 * the function (that should have been static but isn't so I can do this)
6331 * that processes the walk from the async queue,
6332 */
6333f64 fib_walk_process_queues(vlib_main_t * vm,
6334 const f64 quota);
6335u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6336
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006337static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006338fib_test_walk (void)
6339{
6340 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6341 fib_node_test_t *tc;
6342 vlib_main_t *vm;
6343 u32 ii;
6344
6345 vm = vlib_get_main();
6346 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6347
6348 /*
6349 * init a fake node on which we will add children
6350 */
6351 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6352 FIB_NODE_TYPE_TEST);
6353
6354 FOR_EACH_TEST_CHILD(tc)
6355 {
6356 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6357 fib_node_lock(&tc->node);
6358 tc->ctxs = NULL;
6359 tc->index = ii;
6360 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6361 PARENT_INDEX,
6362 FIB_NODE_TYPE_TEST, ii);
6363 }
6364
6365 /*
6366 * enqueue a walk across the parents children.
6367 */
Neale Ranns450cd302016-11-09 17:49:42 +00006368 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006369
6370 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6371 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6372 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6373 "Parent has %d children pre-walk",
6374 fib_node_list_get_size(PARENT()->fn_children));
6375
6376 /*
6377 * give the walk a large amount of time so it gets to the end
6378 */
6379 fib_walk_process_queues(vm, 1);
6380
6381 FOR_EACH_TEST_CHILD(tc)
6382 {
6383 FIB_TEST(1 == vec_len(tc->ctxs),
6384 "%d child visitsed %d times",
6385 ii, vec_len(tc->ctxs));
6386 vec_free(tc->ctxs);
6387 }
6388 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6389 "Queue is empty post walk");
6390 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6391 "Parent has %d children post walk",
6392 fib_node_list_get_size(PARENT()->fn_children));
6393
6394 /*
6395 * walk again. should be no increase in the number of visits, since
6396 * the walk will have terminated.
6397 */
6398 fib_walk_process_queues(vm, 1);
6399
6400 FOR_EACH_TEST_CHILD(tc)
6401 {
6402 FIB_TEST(0 == vec_len(tc->ctxs),
6403 "%d child visitsed %d times",
6404 ii, vec_len(tc->ctxs));
6405 }
6406
6407 /*
6408 * schedule a low and hig priority walk. expect the high to be performed
6409 * before the low.
6410 * schedule the high prio walk first so that it is further from the head
6411 * of the dependency list. that way it won't merge with the low one.
6412 */
6413 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6414 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6415
6416 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6417 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6418 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6419 FIB_WALK_PRIORITY_LOW, &low_ctx);
6420
6421 fib_walk_process_queues(vm, 1);
6422
6423 FOR_EACH_TEST_CHILD(tc)
6424 {
6425 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6426 "%d child visitsed by high prio walk", ii);
6427 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6428 "%d child visitsed by low prio walk", ii);
6429 vec_free(tc->ctxs);
6430 }
6431 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6432 "Queue is empty post prio walk");
6433 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6434 "Parent has %d children post prio walk",
6435 fib_node_list_get_size(PARENT()->fn_children));
6436
6437 /*
6438 * schedule 2 walks of the same priority that can be megred.
6439 * expect that each child is thus visited only once.
6440 */
6441 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6442 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6443
6444 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6445 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6446 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6447 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6448
6449 fib_walk_process_queues(vm, 1);
6450
6451 FOR_EACH_TEST_CHILD(tc)
6452 {
6453 FIB_TEST(1 == vec_len(tc->ctxs),
6454 "%d child visitsed %d times during merge walk",
6455 ii, vec_len(tc->ctxs));
6456 vec_free(tc->ctxs);
6457 }
6458 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6459 "Queue is empty post merge walk");
6460 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6461 "Parent has %d children post merge walk",
6462 fib_node_list_get_size(PARENT()->fn_children));
6463
6464 /*
6465 * schedule 2 walks of the same priority that cannot be megred.
6466 * expect that each child is thus visited twice and in the order
6467 * in which the walks were scheduled.
6468 */
6469 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6470 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6471
6472 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6473 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6474 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6475 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6476
6477 fib_walk_process_queues(vm, 1);
6478
6479 FOR_EACH_TEST_CHILD(tc)
6480 {
6481 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6482 "%d child visitsed by high prio walk", ii);
6483 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6484 "%d child visitsed by low prio walk", ii);
6485 vec_free(tc->ctxs);
6486 }
6487 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6488 "Queue is empty post no-merge walk");
6489 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6490 "Parent has %d children post no-merge walk",
6491 fib_node_list_get_size(PARENT()->fn_children));
6492
6493 /*
6494 * schedule a walk that makes one one child progress.
6495 * we do this by giving the queue draining process zero
6496 * time quanta. it's a do..while loop, so it does something.
6497 */
Neale Ranns450cd302016-11-09 17:49:42 +00006498 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006499
6500 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6501 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6502 fib_walk_process_queues(vm, 0);
6503
6504 FOR_EACH_TEST_CHILD(tc)
6505 {
6506 if (ii == N_TEST_CHILDREN)
6507 {
6508 FIB_TEST(1 == vec_len(tc->ctxs),
6509 "%d child visitsed %d times in zero quanta walk",
6510 ii, vec_len(tc->ctxs));
6511 }
6512 else
6513 {
6514 FIB_TEST(0 == vec_len(tc->ctxs),
6515 "%d child visitsed %d times in 0 quanta walk",
6516 ii, vec_len(tc->ctxs));
6517 }
6518 }
6519 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6520 "Queue is not empty post zero quanta walk");
6521 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6522 "Parent has %d children post zero qunta walk",
6523 fib_node_list_get_size(PARENT()->fn_children));
6524
6525 /*
6526 * another one step
6527 */
6528 fib_walk_process_queues(vm, 0);
6529
6530 FOR_EACH_TEST_CHILD(tc)
6531 {
6532 if (ii >= N_TEST_CHILDREN-1)
6533 {
6534 FIB_TEST(1 == vec_len(tc->ctxs),
6535 "%d child visitsed %d times in 2nd zero quanta walk",
6536 ii, vec_len(tc->ctxs));
6537 }
6538 else
6539 {
6540 FIB_TEST(0 == vec_len(tc->ctxs),
6541 "%d child visitsed %d times in 2nd 0 quanta walk",
6542 ii, vec_len(tc->ctxs));
6543 }
6544 }
6545 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6546 "Queue is not empty post zero quanta walk");
6547 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6548 "Parent has %d children post zero qunta walk",
6549 fib_node_list_get_size(PARENT()->fn_children));
6550
6551 /*
6552 * schedule another walk that will catch-up and merge.
6553 */
6554 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6555 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6556 fib_walk_process_queues(vm, 1);
6557
6558 FOR_EACH_TEST_CHILD(tc)
6559 {
6560 if (ii >= N_TEST_CHILDREN-1)
6561 {
6562 FIB_TEST(2 == vec_len(tc->ctxs),
6563 "%d child visitsed %d times in 2nd zero quanta merge walk",
6564 ii, vec_len(tc->ctxs));
6565 vec_free(tc->ctxs);
6566 }
6567 else
6568 {
6569 FIB_TEST(1 == vec_len(tc->ctxs),
6570 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6571 ii, vec_len(tc->ctxs));
6572 vec_free(tc->ctxs);
6573 }
6574 }
6575 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6576 "Queue is not empty post 2nd zero quanta merge walk");
6577 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6578 "Parent has %d children post 2nd zero qunta merge walk",
6579 fib_node_list_get_size(PARENT()->fn_children));
6580
6581 /*
6582 * park a async walk in the middle of the list, then have an sync walk catch
6583 * it. same expectations as async catches async.
6584 */
Neale Ranns450cd302016-11-09 17:49:42 +00006585 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006586
6587 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6588 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6589
6590 fib_walk_process_queues(vm, 0);
6591 fib_walk_process_queues(vm, 0);
6592
6593 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6594
6595 FOR_EACH_TEST_CHILD(tc)
6596 {
6597 if (ii >= N_TEST_CHILDREN-1)
6598 {
6599 FIB_TEST(2 == vec_len(tc->ctxs),
6600 "%d child visitsed %d times in sync catches async walk",
6601 ii, vec_len(tc->ctxs));
6602 vec_free(tc->ctxs);
6603 }
6604 else
6605 {
6606 FIB_TEST(1 == vec_len(tc->ctxs),
6607 "%d child visitsed %d times in sync catches async walk",
6608 ii, vec_len(tc->ctxs));
6609 vec_free(tc->ctxs);
6610 }
6611 }
6612 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6613 "Queue is not empty post 2nd zero quanta merge walk");
6614 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6615 "Parent has %d children post 2nd zero qunta merge walk",
6616 fib_node_list_get_size(PARENT()->fn_children));
6617
6618 /*
6619 * make the parent a child of one of its children, thus inducing a routing loop.
6620 */
6621 fib_test_nodes[PARENT_INDEX].sibling =
6622 fib_node_child_add(FIB_NODE_TYPE_TEST,
6623 1, // the first child
6624 FIB_NODE_TYPE_TEST,
6625 PARENT_INDEX);
6626
6627 /*
6628 * execute a sync walk from the parent. each child visited spawns more sync
6629 * walks. we expect the walk to terminate.
6630 */
6631 fib_test_walk_spawns_walks = 1;
6632
6633 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6634
6635 FOR_EACH_TEST_CHILD(tc)
6636 {
6637 /*
6638 * child 1 - which is last in the list - has the loop.
6639 * the other children a re thus visitsed first. the we meet
6640 * child 1. we go round the loop again, visting the other children.
6641 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6642 * again.
6643 */
6644 if (1 == ii)
6645 {
6646 FIB_TEST(1 == vec_len(tc->ctxs),
6647 "child %d visitsed %d times during looped sync walk",
6648 ii, vec_len(tc->ctxs));
6649 }
6650 else
6651 {
6652 FIB_TEST(2 == vec_len(tc->ctxs),
6653 "child %d visitsed %d times during looped sync walk",
6654 ii, vec_len(tc->ctxs));
6655 }
6656 vec_free(tc->ctxs);
6657 }
6658 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6659 "Parent has %d children post sync loop walk",
6660 fib_node_list_get_size(PARENT()->fn_children));
6661
6662 /*
6663 * the walk doesn't reach the max depth because the infra knows that sync
6664 * meets sync implies a loop and bails early.
6665 */
6666 FIB_TEST(high_ctx.fnbw_depth == 9,
6667 "Walk context depth %d post sync loop walk",
6668 high_ctx.fnbw_depth);
6669
6670 /*
6671 * execute an async walk of the graph loop, with each child spawns sync walks
6672 */
6673 high_ctx.fnbw_depth = 0;
6674 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6675 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6676
6677 fib_walk_process_queues(vm, 1);
6678
6679 FOR_EACH_TEST_CHILD(tc)
6680 {
6681 /*
6682 * we don't really care how many times the children are visisted, as long as
6683 * it is more than once.
6684 */
6685 FIB_TEST(1 <= vec_len(tc->ctxs),
6686 "child %d visitsed %d times during looped aync spawns sync walk",
6687 ii, vec_len(tc->ctxs));
6688 vec_free(tc->ctxs);
6689 }
6690
6691 /*
6692 * execute an async walk of the graph loop, with each child spawns async walks
6693 */
6694 fib_test_walk_spawns_walks = 2;
6695 high_ctx.fnbw_depth = 0;
6696 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6697 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6698
6699 fib_walk_process_queues(vm, 1);
6700
6701 FOR_EACH_TEST_CHILD(tc)
6702 {
6703 /*
6704 * we don't really care how many times the children are visisted, as long as
6705 * it is more than once.
6706 */
6707 FIB_TEST(1 <= vec_len(tc->ctxs),
6708 "child %d visitsed %d times during looped async spawns async walk",
6709 ii, vec_len(tc->ctxs));
6710 vec_free(tc->ctxs);
6711 }
6712
6713
6714 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6715 1, // the first child
6716 fib_test_nodes[PARENT_INDEX].sibling);
6717
6718 /*
6719 * cleanup
6720 */
6721 FOR_EACH_TEST_CHILD(tc)
6722 {
6723 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6724 tc->sibling);
6725 fib_node_deinit(&tc->node);
6726 fib_node_unlock(&tc->node);
6727 }
6728 fib_node_deinit(PARENT());
6729
6730 /*
6731 * The parent will be destroyed when the last lock on it goes.
6732 * this test ensures all the walk objects are unlocking it.
6733 */
6734 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
6735 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006736
6737 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006738}
6739
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006740static int
6741lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006742{
6743 const mpls_label_t deag_label = 50;
6744 const u32 lfib_index = 0;
6745 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01006746 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006747 const dpo_id_t *dpo1;
6748 fib_node_index_t lfe;
6749 lookup_dpo_t *lkd;
6750 test_main_t *tm;
6751 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00006752 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006753
6754 tm = &test_main;
6755 lb_count = pool_elts(load_balance_pool);
6756
6757 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6758 adj_nbr_db_size());
6759
6760 /*
6761 * MPLS enable an interface so we get the MPLS table created
6762 */
6763 mpls_sw_interface_enable_disable(&mpls_main,
6764 tm->hw[0]->sw_if_index,
6765 1);
6766
Neale Rannsad422ed2016-11-02 14:20:04 +00006767 ip46_address_t nh_10_10_10_1 = {
6768 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6769 };
6770 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6771 VNET_LINK_MPLS,
6772 &nh_10_10_10_1,
6773 tm->hw[0]->sw_if_index);
6774
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006775 /*
6776 * Test the specials stack properly.
6777 */
6778 fib_prefix_t exp_null_v6_pfx = {
6779 .fp_proto = FIB_PROTOCOL_MPLS,
6780 .fp_eos = MPLS_EOS,
6781 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6782 .fp_payload_proto = DPO_PROTO_IP6,
6783 };
6784 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
6785 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
6786 "%U/%U present",
6787 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6788 format_mpls_eos_bit, MPLS_EOS);
6789 fib_entry_contribute_forwarding(lfe,
6790 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6791 &dpo);
6792 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6793 lkd = lookup_dpo_get(dpo1->dpoi_index);
6794
6795 FIB_TEST((fib_index == lkd->lkd_fib_index),
6796 "%U/%U is deag in %d %U",
6797 format_mpls_unicast_label, deag_label,
6798 format_mpls_eos_bit, MPLS_EOS,
6799 lkd->lkd_fib_index,
6800 format_dpo_id, &dpo, 0);
6801 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6802 "%U/%U is dst deag",
6803 format_mpls_unicast_label, deag_label,
6804 format_mpls_eos_bit, MPLS_EOS);
6805 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
6806 "%U/%U is lookup in interface's table",
6807 format_mpls_unicast_label, deag_label,
6808 format_mpls_eos_bit, MPLS_EOS);
6809 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
6810 "%U/%U is %U dst deag",
6811 format_mpls_unicast_label, deag_label,
6812 format_mpls_eos_bit, MPLS_EOS,
6813 format_dpo_proto, lkd->lkd_proto);
6814
6815
6816 /*
6817 * A route deag route for EOS
6818 */
6819 fib_prefix_t pfx = {
6820 .fp_proto = FIB_PROTOCOL_MPLS,
6821 .fp_eos = MPLS_EOS,
6822 .fp_label = deag_label,
6823 .fp_payload_proto = DPO_PROTO_IP4,
6824 };
6825 lfe = fib_table_entry_path_add(lfib_index,
6826 &pfx,
6827 FIB_SOURCE_CLI,
6828 FIB_ENTRY_FLAG_NONE,
6829 FIB_PROTOCOL_IP4,
6830 &zero_addr,
6831 ~0,
6832 fib_index,
6833 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006834 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006835 FIB_ROUTE_PATH_FLAG_NONE);
6836
6837 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6838 "%U/%U present",
6839 format_mpls_unicast_label, deag_label,
6840 format_mpls_eos_bit, MPLS_EOS);
6841
6842 fib_entry_contribute_forwarding(lfe,
6843 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6844 &dpo);
6845 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6846 lkd = lookup_dpo_get(dpo1->dpoi_index);
6847
6848 FIB_TEST((fib_index == lkd->lkd_fib_index),
6849 "%U/%U is deag in %d %U",
6850 format_mpls_unicast_label, deag_label,
6851 format_mpls_eos_bit, MPLS_EOS,
6852 lkd->lkd_fib_index,
6853 format_dpo_id, &dpo, 0);
6854 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6855 "%U/%U is dst deag",
6856 format_mpls_unicast_label, deag_label,
6857 format_mpls_eos_bit, MPLS_EOS);
6858 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
6859 "%U/%U is %U dst deag",
6860 format_mpls_unicast_label, deag_label,
6861 format_mpls_eos_bit, MPLS_EOS,
6862 format_dpo_proto, lkd->lkd_proto);
6863
6864 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6865
6866 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6867 &pfx)),
6868 "%U/%U not present",
6869 format_mpls_unicast_label, deag_label,
6870 format_mpls_eos_bit, MPLS_EOS);
6871
6872 /*
6873 * A route deag route for non-EOS
6874 */
6875 pfx.fp_eos = MPLS_NON_EOS;
6876 lfe = fib_table_entry_path_add(lfib_index,
6877 &pfx,
6878 FIB_SOURCE_CLI,
6879 FIB_ENTRY_FLAG_NONE,
6880 FIB_PROTOCOL_IP4,
6881 &zero_addr,
6882 ~0,
6883 lfib_index,
6884 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006885 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006886 FIB_ROUTE_PATH_FLAG_NONE);
6887
6888 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6889 "%U/%U present",
6890 format_mpls_unicast_label, deag_label,
6891 format_mpls_eos_bit, MPLS_NON_EOS);
6892
6893 fib_entry_contribute_forwarding(lfe,
6894 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6895 &dpo);
6896 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6897 lkd = lookup_dpo_get(dpo1->dpoi_index);
6898
6899 FIB_TEST((fib_index == lkd->lkd_fib_index),
6900 "%U/%U is deag in %d %U",
6901 format_mpls_unicast_label, deag_label,
6902 format_mpls_eos_bit, MPLS_NON_EOS,
6903 lkd->lkd_fib_index,
6904 format_dpo_id, &dpo, 0);
6905 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6906 "%U/%U is dst deag",
6907 format_mpls_unicast_label, deag_label,
6908 format_mpls_eos_bit, MPLS_NON_EOS);
6909
6910 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
6911 "%U/%U is %U dst deag",
6912 format_mpls_unicast_label, deag_label,
6913 format_mpls_eos_bit, MPLS_NON_EOS,
6914 format_dpo_proto, lkd->lkd_proto);
6915
6916 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6917
6918 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6919 &pfx)),
6920 "%U/%U not present",
6921 format_mpls_unicast_label, deag_label,
6922 format_mpls_eos_bit, MPLS_EOS);
6923
Neale Rannsad422ed2016-11-02 14:20:04 +00006924 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006925
Neale Rannsad422ed2016-11-02 14:20:04 +00006926 /*
6927 * An MPLS x-connect
6928 */
6929 fib_prefix_t pfx_1200 = {
6930 .fp_len = 21,
6931 .fp_proto = FIB_PROTOCOL_MPLS,
6932 .fp_label = 1200,
6933 .fp_eos = MPLS_NON_EOS,
6934 };
6935 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
6936 .type = FT_LB_LABEL_STACK_O_ADJ,
6937 .label_stack_o_adj = {
6938 .adj = ai_mpls_10_10_10_1,
6939 .label_stack_size = 4,
6940 .label_stack = {
6941 200, 300, 400, 500,
6942 },
6943 .eos = MPLS_NON_EOS,
6944 },
6945 };
6946 dpo_id_t neos_1200 = DPO_INVALID;
6947 dpo_id_t ip_1200 = DPO_INVALID;
6948 mpls_label_t *l200 = NULL;
6949 vec_add1(l200, 200);
6950 vec_add1(l200, 300);
6951 vec_add1(l200, 400);
6952 vec_add1(l200, 500);
6953
6954 lfe = fib_table_entry_update_one_path(fib_index,
6955 &pfx_1200,
6956 FIB_SOURCE_API,
6957 FIB_ENTRY_FLAG_NONE,
6958 FIB_PROTOCOL_IP4,
6959 &nh_10_10_10_1,
6960 tm->hw[0]->sw_if_index,
6961 ~0, // invalid fib index
6962 1,
6963 l200,
6964 FIB_ROUTE_PATH_FLAG_NONE);
6965
6966 FIB_TEST(fib_test_validate_entry(lfe,
6967 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6968 1,
6969 &neos_o_10_10_10_1),
6970 "1200/0 LB 1 buckets via: "
6971 "adj 10.10.11.1");
6972
6973 /*
6974 * A recursive route via the MPLS x-connect
6975 */
6976 fib_prefix_t pfx_2_2_2_3_s_32 = {
6977 .fp_len = 32,
6978 .fp_proto = FIB_PROTOCOL_IP4,
6979 .fp_addr = {
6980 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6981 },
6982 };
6983 fib_route_path_t *rpaths = NULL, rpath = {
6984 .frp_proto = FIB_PROTOCOL_MPLS,
6985 .frp_local_label = 1200,
6986 .frp_sw_if_index = ~0, // recurive
6987 .frp_fib_index = 0, // Default MPLS fib
6988 .frp_weight = 1,
6989 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6990 .frp_label_stack = NULL,
6991 };
6992 vec_add1(rpaths, rpath);
6993
6994 fib_table_entry_path_add2(fib_index,
6995 &pfx_2_2_2_3_s_32,
6996 FIB_SOURCE_API,
6997 FIB_ENTRY_FLAG_NONE,
6998 rpaths);
6999
7000 /*
7001 * A labelled recursive route via the MPLS x-connect
7002 */
7003 fib_prefix_t pfx_2_2_2_4_s_32 = {
7004 .fp_len = 32,
7005 .fp_proto = FIB_PROTOCOL_IP4,
7006 .fp_addr = {
7007 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7008 },
7009 };
7010 mpls_label_t *l999 = NULL;
7011 vec_add1(l999, 999);
7012 rpaths[0].frp_label_stack = l999,
7013
7014 fib_table_entry_path_add2(fib_index,
7015 &pfx_2_2_2_4_s_32,
7016 FIB_SOURCE_API,
7017 FIB_ENTRY_FLAG_NONE,
7018 rpaths);
7019
7020 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7021 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7022 &ip_1200);
7023 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7024 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7025 &neos_1200);
7026
7027 fib_test_lb_bucket_t ip_o_1200 = {
7028 .type = FT_LB_O_LB,
7029 .lb = {
7030 .lb = ip_1200.dpoi_index,
7031 },
7032 };
7033 fib_test_lb_bucket_t mpls_o_1200 = {
7034 .type = FT_LB_LABEL_O_LB,
7035 .label_o_lb = {
7036 .lb = neos_1200.dpoi_index,
7037 .label = 999,
7038 .eos = MPLS_EOS,
7039 },
7040 };
7041
7042 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7043 FIB_TEST(fib_test_validate_entry(lfe,
7044 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7045 1,
7046 &ip_o_1200),
7047 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
7048 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7049 FIB_TEST(fib_test_validate_entry(lfe,
7050 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7051 1,
7052 &mpls_o_1200),
7053 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
7054
7055 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
7056 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
7057 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7058
7059 dpo_reset(&neos_1200);
7060 dpo_reset(&ip_1200);
7061
7062 /*
7063 * A recursive via a label that does not exist
7064 */
7065 fib_test_lb_bucket_t bucket_drop = {
7066 .type = FT_LB_SPECIAL,
7067 .special = {
7068 .adj = DPO_PROTO_MPLS,
7069 },
7070 };
7071
7072 rpaths[0].frp_label_stack = NULL;
7073 lfe = fib_table_entry_path_add2(fib_index,
7074 &pfx_2_2_2_4_s_32,
7075 FIB_SOURCE_API,
7076 FIB_ENTRY_FLAG_NONE,
7077 rpaths);
7078
7079 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7080 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7081 &ip_1200);
7082 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7083
7084 FIB_TEST(fib_test_validate_entry(lfe,
7085 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7086 1,
7087 &ip_o_1200),
7088 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
7089 lfe = fib_table_lookup(fib_index, &pfx_1200);
7090 FIB_TEST(fib_test_validate_entry(lfe,
7091 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7092 1,
7093 &bucket_drop),
7094 "2.2.2.4/32 LB 1 buckets via: ip4-DROP");
7095
7096 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7097
7098 dpo_reset(&ip_1200);
7099
7100 /*
7101 * cleanup
7102 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007103 mpls_sw_interface_enable_disable(&mpls_main,
7104 tm->hw[0]->sw_if_index,
7105 0);
7106
Neale Rannsad422ed2016-11-02 14:20:04 +00007107 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007108 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00007109 lb_count, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007110
7111 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007112}
7113
7114static clib_error_t *
7115fib_test (vlib_main_t * vm,
7116 unformat_input_t * input,
7117 vlib_cli_command_t * cmd_arg)
7118{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007119 int res;
7120
7121 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007122 fib_test_mk_intf(4);
7123
7124 if (unformat (input, "ip"))
7125 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007126 res += fib_test_v4();
7127 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007128 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007129 else if (unformat (input, "label"))
7130 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007131 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007132 }
7133 else if (unformat (input, "ae"))
7134 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007135 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007136 }
Neale Rannsad422ed2016-11-02 14:20:04 +00007137 else if (unformat (input, "lfib"))
7138 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007139 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00007140 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007141 else if (unformat (input, "walk"))
7142 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007143 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007144 }
7145 else
7146 {
7147 /*
7148 * These walk UT aren't run as part of the full suite, since the
7149 * fib-walk process must be disabled in order for the tests to work
7150 *
7151 * fib_test_walk();
7152 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007153 res += fib_test_v4();
7154 res += fib_test_v6();
7155 res += fib_test_ae();
7156 res += fib_test_label();
7157 res += lfib_test();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007158 }
7159
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007160 if (res)
7161 {
7162 return clib_error_return(0, "FIB Unit Test Failed");
7163 }
7164 else
7165 {
7166 return (NULL);
7167 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007168}
7169
7170VLIB_CLI_COMMAND (test_fib_command, static) = {
7171 .path = "test fib",
7172 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
7173 .function = fib_test,
7174};
7175
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007176clib_error_t *
7177fib_test_init (vlib_main_t *vm)
7178{
7179 return 0;
7180}
7181
7182VLIB_INIT_FUNCTION (fib_test_init);