blob: 5083db2687205a37023a38320970b47ef1c95d14 [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.
666 * There are also 6 entries, and 6 non-shared path-lists, in the v6 default
667 * table
668 */
669#define NBR (5+5+6)
670 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
671 FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
672 fib_path_list_pool_size());
673 FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
674 fib_entry_pool_size());
675
676 /*
677 * add interface routes.
678 * validate presence of /24 attached and /32 recieve.
679 * test for the presence of the receive address in the glean and local adj
680 */
681 fib_prefix_t local_pfx = {
682 .fp_len = 24,
683 .fp_proto = FIB_PROTOCOL_IP4,
684 .fp_addr = {
685 .ip4 = {
686 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
687 },
688 },
689 };
690
691 fib_table_entry_update_one_path(fib_index, &local_pfx,
692 FIB_SOURCE_INTERFACE,
693 (FIB_ENTRY_FLAG_CONNECTED |
694 FIB_ENTRY_FLAG_ATTACHED),
695 FIB_PROTOCOL_IP4,
696 NULL,
697 tm->hw[0]->sw_if_index,
698 ~0, // invalid fib index
699 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000700 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100701 FIB_ROUTE_PATH_FLAG_NONE);
702 fei = fib_table_lookup(fib_index, &local_pfx);
703 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
704 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
705 fib_entry_get_flags(fei)),
706 "Flags set on attached interface");
707
708 ai = fib_entry_get_adj(fei);
709 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
710 adj = adj_get(ai);
711 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
712 "attached interface adj is glean");
713 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
714 &adj->sub_type.glean.receive_addr)),
715 "attached interface adj is receive ok");
716
717 local_pfx.fp_len = 32;
718 fib_table_entry_update_one_path(fib_index, &local_pfx,
719 FIB_SOURCE_INTERFACE,
720 (FIB_ENTRY_FLAG_CONNECTED |
721 FIB_ENTRY_FLAG_LOCAL),
722 FIB_PROTOCOL_IP4,
723 NULL,
724 tm->hw[0]->sw_if_index,
725 ~0, // invalid fib index
726 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000727 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100728 FIB_ROUTE_PATH_FLAG_NONE);
729 fei = fib_table_lookup(fib_index, &local_pfx);
730 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
731 fib_entry_get_flags(fei)),
732 "Flags set on local interface");
733
734 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
735
736 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100737 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
738 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100739 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
740 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
741 "local interface adj is local");
742 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
743
744 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
745 &rd->rd_addr)),
746 "local interface adj is receive ok");
747
748 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
749 FIB_PROTOCOL_IP4,
750 FIB_SOURCE_INTERFACE)),
751 "2 Interface Source'd prefixes");
752
753 /*
754 * +2 interface routes +2 non-shared path-lists
755 */
756 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
757 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
758 fib_path_list_pool_size());
759 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
760 fib_entry_pool_size());
761
762 /*
763 * Modify the default route to be via an adj not yet known.
764 * this sources the defalut route with the API source, which is
765 * a higher preference to the DEFAULT_ROUTE source
766 */
767 pfx.fp_addr.ip4.as_u32 = 0;
768 pfx.fp_len = 0;
769 fib_table_entry_path_add(fib_index, &pfx,
770 FIB_SOURCE_API,
771 FIB_ENTRY_FLAG_NONE,
772 FIB_PROTOCOL_IP4,
773 &nh_10_10_10_1,
774 tm->hw[0]->sw_if_index,
775 ~0, // invalid fib index
776 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000777 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100778 FIB_ROUTE_PATH_FLAG_NONE);
779 fei = fib_table_lookup(fib_index, &pfx);
780 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
781 "Flags set on API route");
782
783 FIB_TEST((fei == dfrt), "default route same index");
784 ai = fib_entry_get_adj(fei);
785 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
786 adj = adj_get(ai);
787 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
788 "adj is incomplete");
789 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
790 "adj nbr next-hop ok");
791 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
792 FIB_PROTOCOL_IP4,
793 FIB_SOURCE_API)),
794 "1 API Source'd prefixes");
795
796 /*
797 * find the adj in the shared db
798 */
799 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100800 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100801 &nh_10_10_10_1,
802 tm->hw[0]->sw_if_index);
803 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
804 adj_unlock(locked_ai);
805
806 /*
807 * +1 shared path-list
808 */
809 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
810 fib_path_list_db_size());
811 FIB_TEST((NBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
812 fib_path_list_pool_size());
813 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
814 fib_entry_pool_size());
815
816 /*
817 * remove the API source from the default route. We expected
818 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
819 */
820 pfx.fp_addr.ip4.as_u32 = 0;
821 pfx.fp_len = 0;
822 fib_table_entry_path_remove(fib_index, &pfx,
823 FIB_SOURCE_API,
824 FIB_PROTOCOL_IP4,
825 &nh_10_10_10_1,
826 tm->hw[0]->sw_if_index,
827 ~0, // non-recursive path, so no FIB index
828 1,
829 FIB_ROUTE_PATH_FLAG_NONE);
830
831 fei = fib_table_lookup(fib_index, &pfx);
832
833 FIB_TEST((fei == dfrt), "default route same index");
834 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
835 "Default route is DROP");
836
837 /*
838 * -1 shared-path-list
839 */
840 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
841 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
842 fib_path_list_pool_size());
843 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
844 fib_entry_pool_size());
845
846 /*
847 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
848 */
849 fib_prefix_t pfx_10_10_10_1_s_32 = {
850 .fp_len = 32,
851 .fp_proto = FIB_PROTOCOL_IP4,
852 .fp_addr = {
853 /* 10.10.10.1 */
854 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
855 },
856 };
857 fib_prefix_t pfx_10_10_10_2_s_32 = {
858 .fp_len = 32,
859 .fp_proto = FIB_PROTOCOL_IP4,
860 .fp_addr = {
861 /* 10.10.10.2 */
862 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
863 },
864 };
865 fib_prefix_t pfx_11_11_11_11_s_32 = {
866 .fp_len = 32,
867 .fp_proto = FIB_PROTOCOL_IP4,
868 .fp_addr = {
869 /* 11.11.11.11 */
870 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
871 },
872 };
873 u8 eth_addr[] = {
874 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
875 };
Neale Rannsb80c5362016-10-08 13:03:40 +0100876
Neale Ranns3ee44042016-10-03 13:05:48 +0100877 ip46_address_t nh_12_12_12_12 = {
878 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
879 };
880 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100881
882 /*
883 * Add a route via an incomplete ADJ. then complete the ADJ
884 * Expect the route LB is updated to use complete adj type.
885 */
886 fei = fib_table_entry_update_one_path(fib_index,
887 &pfx_11_11_11_11_s_32,
888 FIB_SOURCE_API,
889 FIB_ENTRY_FLAG_ATTACHED,
890 FIB_PROTOCOL_IP4,
891 &pfx_10_10_10_1_s_32.fp_addr,
892 tm->hw[0]->sw_if_index,
893 ~0, // invalid fib index
894 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000895 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100896 FIB_ROUTE_PATH_FLAG_NONE);
897
898 dpo = fib_entry_contribute_ip_forwarding(fei);
899 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
900 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
901 "11.11.11.11/32 via incomplete adj");
902
903 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100904 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100905 &pfx_10_10_10_1_s_32.fp_addr,
906 tm->hw[0]->sw_if_index);
907 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
908 adj = adj_get(ai_01);
909 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
910 "adj is incomplete");
911 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
912 &adj->sub_type.nbr.next_hop)),
913 "adj nbr next-hop ok");
914
Neale Rannsb80c5362016-10-08 13:03:40 +0100915 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
916 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100917 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
918 "adj is complete");
919 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
920 &adj->sub_type.nbr.next_hop)),
921 "adj nbr next-hop ok");
922 ai = fib_entry_get_adj(fei);
923 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
924
925 dpo = fib_entry_contribute_ip_forwarding(fei);
926 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
927 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
928 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +0100929 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
930 tm->hw[0]->sw_if_index),
931 "RPF list for adj-fib contains adj");
932
933 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100934 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +0100935 &nh_12_12_12_12,
936 tm->hw[1]->sw_if_index);
937 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
938 adj = adj_get(ai_12_12_12_12);
939 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
940 "adj is incomplete");
941 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
942 &adj->sub_type.nbr.next_hop)),
943 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +0100944 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
945 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +0100946 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
947 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100948
949 /*
950 * add the adj fib
951 */
952 fei = fib_table_entry_update_one_path(fib_index,
953 &pfx_10_10_10_1_s_32,
954 FIB_SOURCE_ADJ,
955 FIB_ENTRY_FLAG_ATTACHED,
956 FIB_PROTOCOL_IP4,
957 &pfx_10_10_10_1_s_32.fp_addr,
958 tm->hw[0]->sw_if_index,
959 ~0, // invalid fib index
960 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000961 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100962 FIB_ROUTE_PATH_FLAG_NONE);
963 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
964 "Flags set on adj-fib");
965 ai = fib_entry_get_adj(fei);
966 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
967
968 fib_table_entry_path_remove(fib_index,
969 &pfx_11_11_11_11_s_32,
970 FIB_SOURCE_API,
971 FIB_PROTOCOL_IP4,
972 &pfx_10_10_10_1_s_32.fp_addr,
973 tm->hw[0]->sw_if_index,
974 ~0, // invalid fib index
975 1,
976 FIB_ROUTE_PATH_FLAG_NONE);
977
978 eth_addr[5] = 0xb2;
979
980 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100981 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100982 &pfx_10_10_10_2_s_32.fp_addr,
983 tm->hw[0]->sw_if_index);
984 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
985 adj = adj_get(ai_02);
986 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
987 "adj is incomplete");
988 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
989 &adj->sub_type.nbr.next_hop)),
990 "adj nbr next-hop ok");
991
Neale Rannsb80c5362016-10-08 13:03:40 +0100992 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
993 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100994 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
995 "adj is complete");
996 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
997 &adj->sub_type.nbr.next_hop)),
998 "adj nbr next-hop ok");
999 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1000
1001 fib_table_entry_update_one_path(fib_index,
1002 &pfx_10_10_10_2_s_32,
1003 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00001004 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001005 FIB_PROTOCOL_IP4,
1006 &pfx_10_10_10_2_s_32.fp_addr,
1007 tm->hw[0]->sw_if_index,
1008 ~0, // invalid fib index
1009 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001010 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001011 FIB_ROUTE_PATH_FLAG_NONE);
1012
1013 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1014 ai = fib_entry_get_adj(fei);
1015 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1016
1017 /*
1018 * +2 adj-fibs, and their non-shared path-lists
1019 */
1020 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
1021 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
1022 fib_path_list_pool_size());
1023 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
1024 fib_entry_pool_size());
1025
1026 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001027 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001028 */
1029 fib_prefix_t pfx_1_1_1_1_s_32 = {
1030 .fp_len = 32,
1031 .fp_proto = FIB_PROTOCOL_IP4,
1032 .fp_addr = {
1033 /* 1.1.1.1/32 */
1034 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1035 },
1036 };
1037
1038 fib_table_entry_path_add(fib_index,
1039 &pfx_1_1_1_1_s_32,
1040 FIB_SOURCE_API,
1041 FIB_ENTRY_FLAG_NONE,
1042 FIB_PROTOCOL_IP4,
1043 &nh_10_10_10_1,
1044 tm->hw[0]->sw_if_index,
1045 ~0, // invalid fib index
1046 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001047 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001048 FIB_ROUTE_PATH_FLAG_NONE);
1049 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1050 ai = fib_entry_get_adj(fei);
1051 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1052
1053 /*
1054 * +1 entry and a shared path-list
1055 */
1056 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1057 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1058 fib_path_list_pool_size());
1059 FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
1060 fib_entry_pool_size());
1061
1062 /* 1.1.2.0/24 */
1063 fib_prefix_t pfx_1_1_2_0_s_24 = {
1064 .fp_len = 24,
1065 .fp_proto = FIB_PROTOCOL_IP4,
1066 .fp_addr = {
1067 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1068 }
1069 };
1070
1071 fib_table_entry_path_add(fib_index,
1072 &pfx_1_1_2_0_s_24,
1073 FIB_SOURCE_API,
1074 FIB_ENTRY_FLAG_NONE,
1075 FIB_PROTOCOL_IP4,
1076 &nh_10_10_10_1,
1077 tm->hw[0]->sw_if_index,
1078 ~0, // invalid fib index
1079 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001080 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001081 FIB_ROUTE_PATH_FLAG_NONE);
1082 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1083 ai = fib_entry_get_adj(fei);
1084 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1085
1086 /*
1087 * +1 entry only
1088 */
1089 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
1090 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1091 fib_path_list_pool_size());
1092 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1093 fib_entry_pool_size());
1094
1095 /*
1096 * modify 1.1.2.0/24 to use multipath.
1097 */
1098 fib_table_entry_path_add(fib_index,
1099 &pfx_1_1_2_0_s_24,
1100 FIB_SOURCE_API,
1101 FIB_ENTRY_FLAG_NONE,
1102 FIB_PROTOCOL_IP4,
1103 &nh_10_10_10_2,
1104 tm->hw[0]->sw_if_index,
1105 ~0, // invalid fib index
1106 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001107 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001108 FIB_ROUTE_PATH_FLAG_NONE);
1109 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1110 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001111 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1112 1, tm->hw[0]->sw_if_index),
1113 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001114
1115 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1116 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1117 FIB_TEST((ai_01 == dpo1->dpoi_index),
1118 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1119 ai_01, dpo1->dpoi_index);
1120
1121 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1122 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1123 FIB_TEST((ai_02 == dpo1->dpoi_index),
1124 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1125
1126 /*
1127 * +1 shared-pathlist
1128 */
1129 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
1130 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1131 fib_path_list_pool_size());
1132 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1133 fib_entry_pool_size());
1134
1135 /*
1136 * revert the modify
1137 */
1138 fib_table_entry_path_remove(fib_index,
1139 &pfx_1_1_2_0_s_24,
1140 FIB_SOURCE_API,
1141 FIB_PROTOCOL_IP4,
1142 &nh_10_10_10_2,
1143 tm->hw[0]->sw_if_index,
1144 ~0,
1145 1,
1146 FIB_ROUTE_PATH_FLAG_NONE);
1147 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001148 dpo = fib_entry_contribute_ip_forwarding(fei);
1149 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1150 1, tm->hw[0]->sw_if_index),
1151 "RPF list for 1.1.2.0/24 contains one adj");
1152
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001153 ai = fib_entry_get_adj(fei);
1154 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1155
1156 /*
1157 * +1 shared-pathlist
1158 */
1159 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1160 fib_path_list_db_size());
1161 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
1162 fib_path_list_pool_size());
1163 FIB_TEST((NBR+6 == fib_entry_pool_size()), "entry pool size is %d",
1164 fib_entry_pool_size());
1165
1166 /*
1167 * Add 2 recursive routes:
1168 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1169 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1170 */
1171 fib_prefix_t bgp_100_pfx = {
1172 .fp_len = 32,
1173 .fp_proto = FIB_PROTOCOL_IP4,
1174 .fp_addr = {
1175 /* 100.100.100.100/32 */
1176 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1177 },
1178 };
1179 /* via 1.1.1.1 */
1180 ip46_address_t nh_1_1_1_1 = {
1181 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1182 };
1183
Neale Ranns3ee44042016-10-03 13:05:48 +01001184 fei = fib_table_entry_path_add(fib_index,
1185 &bgp_100_pfx,
1186 FIB_SOURCE_API,
1187 FIB_ENTRY_FLAG_NONE,
1188 FIB_PROTOCOL_IP4,
1189 &nh_1_1_1_1,
1190 ~0, // no index provided.
1191 fib_index, // nexthop in same fib as route
1192 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001193 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001194 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001195
Neale Ranns3ee44042016-10-03 13:05:48 +01001196 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1197 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1198 tm->hw[0]->sw_if_index),
1199 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001200
1201 /*
1202 * +1 entry and +1 shared-path-list
1203 */
1204 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1205 fib_path_list_db_size());
1206 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1207 fib_path_list_pool_size());
1208 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
1209 fib_entry_pool_size());
1210
1211 fib_prefix_t bgp_101_pfx = {
1212 .fp_len = 32,
1213 .fp_proto = FIB_PROTOCOL_IP4,
1214 .fp_addr = {
1215 /* 100.100.100.101/32 */
1216 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1217 },
1218 };
1219
1220 fib_table_entry_path_add(fib_index,
1221 &bgp_101_pfx,
1222 FIB_SOURCE_API,
1223 FIB_ENTRY_FLAG_NONE,
1224 FIB_PROTOCOL_IP4,
1225 &nh_1_1_1_1,
1226 ~0, // no index provided.
1227 fib_index, // nexthop in same fib as route
1228 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001229 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001230 FIB_ROUTE_PATH_FLAG_NONE);
1231
Neale Ranns3ee44042016-10-03 13:05:48 +01001232 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1233 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1234 tm->hw[0]->sw_if_index),
1235 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001236
1237 /*
1238 * +1 entry, but the recursive path-list is shared.
1239 */
1240 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1241 fib_path_list_db_size());
1242 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
1243 fib_path_list_pool_size());
1244 FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
1245 fib_entry_pool_size());
1246
1247 /*
1248 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1249 * adjacency through which the route will resovle
1250 */
1251 fib_prefix_t ex_pfx = {
1252 .fp_len = 32,
1253 .fp_proto = FIB_PROTOCOL_IP4,
1254 .fp_addr = {
1255 /* 4.4.4.4/32 */
1256 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1257 },
1258 };
1259
1260 fib_table_entry_special_add(fib_index,
1261 &ex_pfx,
1262 FIB_SOURCE_SPECIAL,
1263 FIB_ENTRY_FLAG_EXCLUSIVE,
1264 locked_ai);
1265 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1266 FIB_TEST((ai == fib_entry_get_adj(fei)),
1267 "Exclusive route links to user adj");
1268
1269 fib_table_entry_special_remove(fib_index,
1270 &ex_pfx,
1271 FIB_SOURCE_SPECIAL);
1272 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1273 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1274 "Exclusive reoute removed");
1275
1276 /*
1277 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1278 * adjacency through which the route will resovle
1279 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001280 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001281
1282 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1283 DPO_PROTO_IP4,
1284 LOOKUP_INPUT_DST_ADDR,
1285 LOOKUP_TABLE_FROM_CONFIG,
1286 &ex_dpo);
1287
1288 fib_table_entry_special_dpo_add(fib_index,
1289 &ex_pfx,
1290 FIB_SOURCE_SPECIAL,
1291 FIB_ENTRY_FLAG_EXCLUSIVE,
1292 &ex_dpo);
1293 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1294 dpo = fib_entry_contribute_ip_forwarding(fei);
1295 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1296 "exclusive remote uses lookup DPO");
1297
Neale Ranns948e00f2016-10-20 13:39:34 +01001298 /*
1299 * update the exclusive to use a different DPO
1300 */
Neale Ranns450cd302016-11-09 17:49:42 +00001301 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001302 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1303 &ex_dpo);
1304 fib_table_entry_special_dpo_update(fib_index,
1305 &ex_pfx,
1306 FIB_SOURCE_SPECIAL,
1307 FIB_ENTRY_FLAG_EXCLUSIVE,
1308 &ex_dpo);
1309 dpo = fib_entry_contribute_ip_forwarding(fei);
1310 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1311 "exclusive remote uses now uses NULL DPO");
1312
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001313 fib_table_entry_special_remove(fib_index,
1314 &ex_pfx,
1315 FIB_SOURCE_SPECIAL);
1316 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1317 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1318 "Exclusive reoute removed");
1319 dpo_reset(&ex_dpo);
1320
1321 /*
1322 * Add a recursive route:
1323 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1324 */
1325 fib_prefix_t bgp_200_pfx = {
1326 .fp_len = 32,
1327 .fp_proto = FIB_PROTOCOL_IP4,
1328 .fp_addr = {
1329 /* 200.200.200.200/32 */
1330 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1331 },
1332 };
1333 /* via 1.1.1.2 */
1334 fib_prefix_t pfx_1_1_1_2_s_32 = {
1335 .fp_len = 32,
1336 .fp_proto = FIB_PROTOCOL_IP4,
1337 .fp_addr = {
1338 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1339 },
1340 };
1341
1342 fib_table_entry_path_add(fib_index,
1343 &bgp_200_pfx,
1344 FIB_SOURCE_API,
1345 FIB_ENTRY_FLAG_NONE,
1346 FIB_PROTOCOL_IP4,
1347 &pfx_1_1_1_2_s_32.fp_addr,
1348 ~0, // no index provided.
1349 fib_index, // nexthop in same fib as route
1350 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001351 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001352 FIB_ROUTE_PATH_FLAG_NONE);
1353
Neale Ranns3ee44042016-10-03 13:05:48 +01001354 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001355
1356 /*
1357 * the adj should be recursive via drop, since the route resolves via
1358 * the default route, which is itself a DROP
1359 */
1360 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1361 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1362 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001363 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1364 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001365
1366 /*
1367 * +2 entry and +1 shared-path-list
1368 */
1369 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1370 fib_path_list_db_size());
1371 FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
1372 fib_path_list_pool_size());
1373 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
1374 fib_entry_pool_size());
1375
1376 /*
1377 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001378 * The paths are sort by NH first. in this case the the path with greater
1379 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001380 */
1381 fib_prefix_t pfx_1_2_3_4_s_32 = {
1382 .fp_len = 32,
1383 .fp_proto = FIB_PROTOCOL_IP4,
1384 .fp_addr = {
1385 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1386 },
1387 };
1388 fib_table_entry_path_add(fib_index,
1389 &pfx_1_2_3_4_s_32,
1390 FIB_SOURCE_API,
1391 FIB_ENTRY_FLAG_NONE,
1392 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001393 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001394 tm->hw[0]->sw_if_index,
1395 ~0,
1396 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001397 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001398 FIB_ROUTE_PATH_FLAG_NONE);
1399 fei = fib_table_entry_path_add(fib_index,
1400 &pfx_1_2_3_4_s_32,
1401 FIB_SOURCE_API,
1402 FIB_ENTRY_FLAG_NONE,
1403 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001404 &nh_12_12_12_12,
1405 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001406 ~0,
1407 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001408 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001409 FIB_ROUTE_PATH_FLAG_NONE);
1410
1411 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1412 dpo = fib_entry_contribute_ip_forwarding(fei);
1413 lb = load_balance_get(dpo->dpoi_index);
1414 FIB_TEST((lb->lb_n_buckets == 4),
1415 "1.2.3.4/32 LB has %d bucket",
1416 lb->lb_n_buckets);
1417
Neale Ranns3ee44042016-10-03 13:05:48 +01001418 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1419 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1420 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1421 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001422
Neale Ranns3ee44042016-10-03 13:05:48 +01001423 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1424 tm->hw[0]->sw_if_index,
1425 tm->hw[1]->sw_if_index),
1426 "RPF list for 1.2.3.4/32 contains both adjs");
1427
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001428
1429 /*
1430 * Unequal Cost load-balance. 4:1 ratio.
1431 * fits in a 16 bucket LB with ratio 13:3
1432 */
1433 fib_prefix_t pfx_1_2_3_5_s_32 = {
1434 .fp_len = 32,
1435 .fp_proto = FIB_PROTOCOL_IP4,
1436 .fp_addr = {
1437 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1438 },
1439 };
1440 fib_table_entry_path_add(fib_index,
1441 &pfx_1_2_3_5_s_32,
1442 FIB_SOURCE_API,
1443 FIB_ENTRY_FLAG_NONE,
1444 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001445 &nh_12_12_12_12,
1446 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001447 ~0,
1448 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001449 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001450 FIB_ROUTE_PATH_FLAG_NONE);
1451 fei = fib_table_entry_path_add(fib_index,
1452 &pfx_1_2_3_5_s_32,
1453 FIB_SOURCE_API,
1454 FIB_ENTRY_FLAG_NONE,
1455 FIB_PROTOCOL_IP4,
1456 &nh_10_10_10_1,
1457 tm->hw[0]->sw_if_index,
1458 ~0,
1459 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001460 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001461 FIB_ROUTE_PATH_FLAG_NONE);
1462
1463 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1464 dpo = fib_entry_contribute_ip_forwarding(fei);
1465 lb = load_balance_get(dpo->dpoi_index);
1466 FIB_TEST((lb->lb_n_buckets == 16),
1467 "1.2.3.5/32 LB has %d bucket",
1468 lb->lb_n_buckets);
1469
1470 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1471 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1472 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1473 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1474 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1475 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1476 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1477 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1478 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1479 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1480 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1481 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1482 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001483 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1484 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1485 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1486
1487 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1488 tm->hw[0]->sw_if_index,
1489 tm->hw[1]->sw_if_index),
1490 "RPF list for 1.2.3.4/32 contains both adjs");
1491
1492 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001493 * Test UCMP with a large weight skew - this produces load-balance objects with large
1494 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1495 * laso testing the LB in placce modify code when number of buckets is large.
1496 */
1497 fib_prefix_t pfx_6_6_6_6_s_32 = {
1498 .fp_len = 32,
1499 .fp_proto = FIB_PROTOCOL_IP4,
1500 .fp_addr = {
1501 /* 1.1.1.1/32 */
1502 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1503 },
1504 };
1505 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
1506 .type = FT_LB_ADJ,
1507 .adj = {
1508 .adj = ai_01,
1509 },
1510 };
1511 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
1512 .type = FT_LB_ADJ,
1513 .adj = {
1514 .adj = ai_02,
1515 },
1516 };
1517 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1518 .type = FT_LB_ADJ,
1519 .adj = {
1520 .adj = ai_12_12_12_12,
1521 },
1522 };
1523 fib_table_entry_update_one_path(fib_index,
1524 &pfx_6_6_6_6_s_32,
1525 FIB_SOURCE_API,
1526 FIB_ENTRY_FLAG_NONE,
1527 FIB_PROTOCOL_IP4,
1528 &nh_10_10_10_1,
1529 tm->hw[0]->sw_if_index,
1530 ~0, // invalid fib index
1531 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001532 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001533 FIB_ROUTE_PATH_FLAG_NONE);
1534
1535 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1536 FIB_TEST(fib_test_validate_entry(fei,
1537 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1538 1,
1539 &ip_6_6_6_6_o_10_10_10_1),
1540 "6.6.6.6/32 via 10.10.10.1");
1541
1542 fib_table_entry_path_add(fib_index,
1543 &pfx_6_6_6_6_s_32,
1544 FIB_SOURCE_API,
1545 FIB_ENTRY_FLAG_NONE,
1546 FIB_PROTOCOL_IP4,
1547 &nh_10_10_10_2,
1548 tm->hw[0]->sw_if_index,
1549 ~0, // invalid fib index
1550 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001551 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001552 FIB_ROUTE_PATH_FLAG_NONE);
1553
1554 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1555 FIB_TEST(fib_test_validate_entry(fei,
1556 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1557 64,
1558 &ip_6_6_6_6_o_10_10_10_2,
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_1),
1622 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1623
1624 fib_table_entry_path_add(fib_index,
1625 &pfx_6_6_6_6_s_32,
1626 FIB_SOURCE_API,
1627 FIB_ENTRY_FLAG_NONE,
1628 FIB_PROTOCOL_IP4,
1629 &nh_12_12_12_12,
1630 tm->hw[1]->sw_if_index,
1631 ~0, // invalid fib index
1632 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001633 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001634 FIB_ROUTE_PATH_FLAG_NONE);
1635
1636 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1637 FIB_TEST(fib_test_validate_entry(fei,
1638 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1639 128,
1640 &ip_6_6_6_6_o_10_10_10_1,
1641 &ip_6_6_6_6_o_10_10_10_2,
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_12_12_12_12,
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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1769
1770 fib_table_entry_path_remove(fib_index,
1771 &pfx_6_6_6_6_s_32,
1772 FIB_SOURCE_API,
1773 FIB_PROTOCOL_IP4,
1774 &nh_12_12_12_12,
1775 tm->hw[1]->sw_if_index,
1776 ~0, // invalid fib index
1777 100,
1778 FIB_ROUTE_PATH_FLAG_NONE);
1779
1780 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1781 FIB_TEST(fib_test_validate_entry(fei,
1782 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1783 64,
1784 &ip_6_6_6_6_o_10_10_10_2,
1785 &ip_6_6_6_6_o_10_10_10_2,
1786 &ip_6_6_6_6_o_10_10_10_2,
1787 &ip_6_6_6_6_o_10_10_10_2,
1788 &ip_6_6_6_6_o_10_10_10_2,
1789 &ip_6_6_6_6_o_10_10_10_2,
1790 &ip_6_6_6_6_o_10_10_10_2,
1791 &ip_6_6_6_6_o_10_10_10_2,
1792 &ip_6_6_6_6_o_10_10_10_2,
1793 &ip_6_6_6_6_o_10_10_10_2,
1794 &ip_6_6_6_6_o_10_10_10_2,
1795 &ip_6_6_6_6_o_10_10_10_2,
1796 &ip_6_6_6_6_o_10_10_10_2,
1797 &ip_6_6_6_6_o_10_10_10_2,
1798 &ip_6_6_6_6_o_10_10_10_2,
1799 &ip_6_6_6_6_o_10_10_10_2,
1800 &ip_6_6_6_6_o_10_10_10_2,
1801 &ip_6_6_6_6_o_10_10_10_2,
1802 &ip_6_6_6_6_o_10_10_10_2,
1803 &ip_6_6_6_6_o_10_10_10_2,
1804 &ip_6_6_6_6_o_10_10_10_2,
1805 &ip_6_6_6_6_o_10_10_10_2,
1806 &ip_6_6_6_6_o_10_10_10_2,
1807 &ip_6_6_6_6_o_10_10_10_2,
1808 &ip_6_6_6_6_o_10_10_10_2,
1809 &ip_6_6_6_6_o_10_10_10_2,
1810 &ip_6_6_6_6_o_10_10_10_2,
1811 &ip_6_6_6_6_o_10_10_10_2,
1812 &ip_6_6_6_6_o_10_10_10_2,
1813 &ip_6_6_6_6_o_10_10_10_2,
1814 &ip_6_6_6_6_o_10_10_10_2,
1815 &ip_6_6_6_6_o_10_10_10_2,
1816 &ip_6_6_6_6_o_10_10_10_2,
1817 &ip_6_6_6_6_o_10_10_10_2,
1818 &ip_6_6_6_6_o_10_10_10_2,
1819 &ip_6_6_6_6_o_10_10_10_2,
1820 &ip_6_6_6_6_o_10_10_10_2,
1821 &ip_6_6_6_6_o_10_10_10_2,
1822 &ip_6_6_6_6_o_10_10_10_2,
1823 &ip_6_6_6_6_o_10_10_10_2,
1824 &ip_6_6_6_6_o_10_10_10_2,
1825 &ip_6_6_6_6_o_10_10_10_2,
1826 &ip_6_6_6_6_o_10_10_10_2,
1827 &ip_6_6_6_6_o_10_10_10_2,
1828 &ip_6_6_6_6_o_10_10_10_2,
1829 &ip_6_6_6_6_o_10_10_10_2,
1830 &ip_6_6_6_6_o_10_10_10_2,
1831 &ip_6_6_6_6_o_10_10_10_2,
1832 &ip_6_6_6_6_o_10_10_10_2,
1833 &ip_6_6_6_6_o_10_10_10_2,
1834 &ip_6_6_6_6_o_10_10_10_2,
1835 &ip_6_6_6_6_o_10_10_10_2,
1836 &ip_6_6_6_6_o_10_10_10_2,
1837 &ip_6_6_6_6_o_10_10_10_2,
1838 &ip_6_6_6_6_o_10_10_10_2,
1839 &ip_6_6_6_6_o_10_10_10_2,
1840 &ip_6_6_6_6_o_10_10_10_2,
1841 &ip_6_6_6_6_o_10_10_10_2,
1842 &ip_6_6_6_6_o_10_10_10_2,
1843 &ip_6_6_6_6_o_10_10_10_2,
1844 &ip_6_6_6_6_o_10_10_10_2,
1845 &ip_6_6_6_6_o_10_10_10_2,
1846 &ip_6_6_6_6_o_10_10_10_2,
1847 &ip_6_6_6_6_o_10_10_10_1),
1848 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1849
1850 fib_table_entry_path_remove(fib_index,
1851 &pfx_6_6_6_6_s_32,
1852 FIB_SOURCE_API,
1853 FIB_PROTOCOL_IP4,
1854 &nh_10_10_10_2,
1855 tm->hw[0]->sw_if_index,
1856 ~0, // invalid fib index
1857 100,
1858 FIB_ROUTE_PATH_FLAG_NONE);
1859
1860 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1861 FIB_TEST(fib_test_validate_entry(fei,
1862 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1863 1,
1864 &ip_6_6_6_6_o_10_10_10_1),
1865 "6.6.6.6/32 via 10.10.10.1");
1866
1867 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1868
1869 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001870 * A recursive via the two unequal cost entries
1871 */
1872 fib_prefix_t bgp_44_s_32 = {
1873 .fp_len = 32,
1874 .fp_proto = FIB_PROTOCOL_IP4,
1875 .fp_addr = {
1876 /* 200.200.200.201/32 */
1877 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1878 },
1879 };
1880 fei = fib_table_entry_path_add(fib_index,
1881 &bgp_44_s_32,
1882 FIB_SOURCE_API,
1883 FIB_ENTRY_FLAG_NONE,
1884 FIB_PROTOCOL_IP4,
1885 &pfx_1_2_3_4_s_32.fp_addr,
1886 ~0,
1887 fib_index,
1888 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001889 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001890 FIB_ROUTE_PATH_FLAG_NONE);
1891 fei = fib_table_entry_path_add(fib_index,
1892 &bgp_44_s_32,
1893 FIB_SOURCE_API,
1894 FIB_ENTRY_FLAG_NONE,
1895 FIB_PROTOCOL_IP4,
1896 &pfx_1_2_3_5_s_32.fp_addr,
1897 ~0,
1898 fib_index,
1899 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001900 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001901 FIB_ROUTE_PATH_FLAG_NONE);
1902
1903 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
1904 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
1905 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1906 tm->hw[0]->sw_if_index,
1907 tm->hw[1]->sw_if_index),
1908 "RPF list for 1.2.3.4/32 contains both adjs");
1909
1910 /*
1911 * test the uRPF check functions
1912 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001913 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01001914 index_t urpfi;
1915
1916 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
1917 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
1918
1919 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
1920 "uRPF check for 68.68.68.68/32 on %d OK",
1921 tm->hw[0]->sw_if_index);
1922 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
1923 "uRPF check for 68.68.68.68/32 on %d OK",
1924 tm->hw[1]->sw_if_index);
1925 FIB_TEST(!fib_urpf_check(urpfi, 99),
1926 "uRPF check for 68.68.68.68/32 on 99 not-OK",
1927 99);
1928 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001929
1930 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01001931 &bgp_44_s_32,
1932 FIB_SOURCE_API);
1933 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001934 &pfx_1_2_3_5_s_32,
1935 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01001936 fib_table_entry_delete(fib_index,
1937 &pfx_1_2_3_4_s_32,
1938 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001939
1940 /*
1941 * Add a recursive route:
1942 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
1943 */
1944 fib_prefix_t bgp_201_pfx = {
1945 .fp_len = 32,
1946 .fp_proto = FIB_PROTOCOL_IP4,
1947 .fp_addr = {
1948 /* 200.200.200.201/32 */
1949 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
1950 },
1951 };
1952 /* via 1.1.1.200 */
1953 fib_prefix_t pfx_1_1_1_200_s_32 = {
1954 .fp_len = 32,
1955 .fp_proto = FIB_PROTOCOL_IP4,
1956 .fp_addr = {
1957 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
1958 },
1959 };
1960
1961 fib_table_entry_path_add(fib_index,
1962 &bgp_201_pfx,
1963 FIB_SOURCE_API,
1964 FIB_ENTRY_FLAG_NONE,
1965 FIB_PROTOCOL_IP4,
1966 &pfx_1_1_1_200_s_32.fp_addr,
1967 ~0, // no index provided.
1968 fib_index, // nexthop in same fib as route
1969 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001970 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001971 FIB_ROUTE_PATH_FLAG_NONE);
1972
Neale Ranns3ee44042016-10-03 13:05:48 +01001973 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001974
1975 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
1976 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1977 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01001978 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1979 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001980
1981 /*
1982 * +2 entry (BGP & RR) and +1 shared-path-list
1983 */
1984 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
1985 fib_path_list_db_size());
1986 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
1987 fib_path_list_pool_size());
1988 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
1989 fib_entry_pool_size());
1990
1991 /*
1992 * insert a route that covers the missing 1.1.1.2/32. we epxect
1993 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
1994 */
1995 fib_prefix_t pfx_1_1_1_0_s_24 = {
1996 .fp_len = 24,
1997 .fp_proto = FIB_PROTOCOL_IP4,
1998 .fp_addr = {
1999 /* 1.1.1.0/24 */
2000 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2001 },
2002 };
2003
2004 fib_table_entry_path_add(fib_index,
2005 &pfx_1_1_1_0_s_24,
2006 FIB_SOURCE_API,
2007 FIB_ENTRY_FLAG_NONE,
2008 FIB_PROTOCOL_IP4,
2009 &nh_10_10_10_1,
2010 tm->hw[0]->sw_if_index,
2011 ~0, // invalid fib index
2012 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002013 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002014 FIB_ROUTE_PATH_FLAG_NONE);
2015 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2016 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2017 ai = fib_entry_get_adj(fei);
2018 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2019 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2020 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2021 ai = fib_entry_get_adj(fei);
2022 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2023 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2024 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2025 ai = fib_entry_get_adj(fei);
2026 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2027
2028 /*
2029 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2030 */
2031 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2032 fib_path_list_db_size());
2033 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2034 fib_path_list_pool_size());
2035 FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2036 fib_entry_pool_size());
2037
2038 /*
2039 * the recursive adj for 200.200.200.200 should be updated.
2040 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002041 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2042 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2043 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2044 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2045 tm->hw[0]->sw_if_index),
2046 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002047
2048 /*
2049 * insert a more specific route than 1.1.1.0/24 that also covers the
2050 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2051 * 200.200.200.200 to resolve through it.
2052 */
2053 fib_prefix_t pfx_1_1_1_0_s_28 = {
2054 .fp_len = 28,
2055 .fp_proto = FIB_PROTOCOL_IP4,
2056 .fp_addr = {
2057 /* 1.1.1.0/24 */
2058 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2059 },
2060 };
2061
2062 fib_table_entry_path_add(fib_index,
2063 &pfx_1_1_1_0_s_28,
2064 FIB_SOURCE_API,
2065 FIB_ENTRY_FLAG_NONE,
2066 FIB_PROTOCOL_IP4,
2067 &nh_10_10_10_2,
2068 tm->hw[0]->sw_if_index,
2069 ~0, // invalid fib index
2070 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002071 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002072 FIB_ROUTE_PATH_FLAG_NONE);
2073 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2074 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2075 ai = fib_entry_get_adj(fei);
2076 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2077
2078 /*
2079 * +1 entry. +1 shared path-list
2080 */
2081 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2082 fib_path_list_db_size());
2083 FIB_TEST((NBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
2084 fib_path_list_pool_size());
2085 FIB_TEST((NBR+14 == fib_entry_pool_size()), "entry pool size is %d",
2086 fib_entry_pool_size());
2087
2088 /*
2089 * the recursive adj for 200.200.200.200 should be updated.
2090 * 200.200.200.201 remains unchanged.
2091 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002092 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2093 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002094
2095 /*
2096 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2097 */
2098 fib_table_entry_path_remove(fib_index,
2099 &pfx_1_1_1_0_s_28,
2100 FIB_SOURCE_API,
2101 FIB_PROTOCOL_IP4,
2102 &nh_10_10_10_2,
2103 tm->hw[0]->sw_if_index,
2104 ~0,
2105 1,
2106 FIB_ROUTE_PATH_FLAG_NONE);
2107 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2108 FIB_NODE_INDEX_INVALID),
2109 "1.1.1.0/28 removed");
2110 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2111 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2112 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002113 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2114 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002115
2116 /*
2117 * -1 entry. -1 shared path-list
2118 */
2119 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2120 fib_path_list_db_size());
2121 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2122 fib_path_list_pool_size());
2123 FIB_TEST((NBR+13 == fib_entry_pool_size()), "entry pool size is %d",
2124 fib_entry_pool_size());
2125
2126 /*
2127 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2128 */
2129 fib_table_entry_path_remove(fib_index,
2130 &pfx_1_1_1_0_s_24,
2131 FIB_SOURCE_API,
2132 FIB_PROTOCOL_IP4,
2133 &nh_10_10_10_1,
2134 tm->hw[0]->sw_if_index,
2135 ~0,
2136 1,
2137 FIB_ROUTE_PATH_FLAG_NONE);
2138 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2139 FIB_NODE_INDEX_INVALID),
2140 "1.1.1.0/24 removed");
2141
2142 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2143 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2144 "1.1.1.2/32 route is DROP");
2145 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2146 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2147 "1.1.1.200/32 route is DROP");
2148
Neale Ranns3ee44042016-10-03 13:05:48 +01002149 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2150 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002151
2152 /*
2153 * -1 entry
2154 */
2155 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2156 fib_path_list_db_size());
2157 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2158 fib_path_list_pool_size());
2159 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2160 fib_entry_pool_size());
2161
2162 /*
2163 * insert the missing 1.1.1.2/32
2164 */
2165 fei = fib_table_entry_path_add(fib_index,
2166 &pfx_1_1_1_2_s_32,
2167 FIB_SOURCE_API,
2168 FIB_ENTRY_FLAG_NONE,
2169 FIB_PROTOCOL_IP4,
2170 &nh_10_10_10_1,
2171 tm->hw[0]->sw_if_index,
2172 ~0, // invalid fib index
2173 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002174 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002175 FIB_ROUTE_PATH_FLAG_NONE);
2176 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2177 ai = fib_entry_get_adj(fei);
2178 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2179
Neale Ranns3ee44042016-10-03 13:05:48 +01002180 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2181 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002182
2183 /*
2184 * no change. 1.1.1.2/32 was already there RR sourced.
2185 */
2186 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2187 fib_path_list_db_size());
2188 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2189 fib_path_list_pool_size());
2190 FIB_TEST((NBR+12 == fib_entry_pool_size()), "entry pool size is %d",
2191 fib_entry_pool_size());
2192
2193 /*
2194 * remove 200.200.200.201/32 which does not have a valid via FIB
2195 */
2196 fib_table_entry_path_remove(fib_index,
2197 &bgp_201_pfx,
2198 FIB_SOURCE_API,
2199 FIB_PROTOCOL_IP4,
2200 &pfx_1_1_1_200_s_32.fp_addr,
2201 ~0, // no index provided.
2202 fib_index,
2203 1,
2204 FIB_ROUTE_PATH_FLAG_NONE);
2205
2206 /*
2207 * -2 entries (BGP and RR). -1 shared path-list;
2208 */
2209 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2210 FIB_NODE_INDEX_INVALID),
2211 "200.200.200.201/32 removed");
2212 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2213 FIB_NODE_INDEX_INVALID),
2214 "1.1.1.200/32 removed");
2215
2216 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2217 fib_path_list_db_size());
2218 FIB_TEST((NBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
2219 fib_path_list_pool_size());
2220 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2221 fib_entry_pool_size());
2222
2223 /*
2224 * remove 200.200.200.200/32 which does have a valid via FIB
2225 */
2226 fib_table_entry_path_remove(fib_index,
2227 &bgp_200_pfx,
2228 FIB_SOURCE_API,
2229 FIB_PROTOCOL_IP4,
2230 &pfx_1_1_1_2_s_32.fp_addr,
2231 ~0, // no index provided.
2232 fib_index,
2233 1,
2234 FIB_ROUTE_PATH_FLAG_NONE);
2235
2236 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2237 FIB_NODE_INDEX_INVALID),
2238 "200.200.200.200/32 removed");
2239 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2240 FIB_NODE_INDEX_INVALID),
2241 "1.1.1.2/32 still present");
2242
2243 /*
2244 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2245 */
2246 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2247 fib_path_list_db_size());
2248 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2249 fib_path_list_pool_size());
2250 FIB_TEST((NBR+9 == fib_entry_pool_size()), "entry pool size is %d",
2251 fib_entry_pool_size());
2252
2253 /*
2254 * A recursive prefix that has a 2 path load-balance.
2255 * It also shares a next-hop with other BGP prefixes and hence
2256 * test the ref counting of RR sourced prefixes and 2 level LB.
2257 */
2258 const fib_prefix_t bgp_102 = {
2259 .fp_len = 32,
2260 .fp_proto = FIB_PROTOCOL_IP4,
2261 .fp_addr = {
2262 /* 100.100.100.101/32 */
2263 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2264 },
2265 };
2266 fib_table_entry_path_add(fib_index,
2267 &bgp_102,
2268 FIB_SOURCE_API,
2269 FIB_ENTRY_FLAG_NONE,
2270 FIB_PROTOCOL_IP4,
2271 &pfx_1_1_1_1_s_32.fp_addr,
2272 ~0, // no index provided.
2273 fib_index, // same as route
2274 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002275 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002276 FIB_ROUTE_PATH_FLAG_NONE);
2277 fib_table_entry_path_add(fib_index,
2278 &bgp_102,
2279 FIB_SOURCE_API,
2280 FIB_ENTRY_FLAG_NONE,
2281 FIB_PROTOCOL_IP4,
2282 &pfx_1_1_1_2_s_32.fp_addr,
2283 ~0, // no index provided.
2284 fib_index, // same as route's FIB
2285 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002286 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002287 FIB_ROUTE_PATH_FLAG_NONE);
2288 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2289 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2290 dpo = fib_entry_contribute_ip_forwarding(fei);
2291
2292 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2293 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2294 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2295 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2296
2297 lb = load_balance_get(dpo->dpoi_index);
2298 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2299 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2300 "First via 10.10.10.1");
2301 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2302 "Second via 10.10.10.1");
2303
2304 fib_table_entry_path_remove(fib_index,
2305 &bgp_102,
2306 FIB_SOURCE_API,
2307 FIB_PROTOCOL_IP4,
2308 &pfx_1_1_1_1_s_32.fp_addr,
2309 ~0, // no index provided.
2310 fib_index, // same as route's FIB
2311 1,
2312 FIB_ROUTE_PATH_FLAG_NONE);
2313 fib_table_entry_path_remove(fib_index,
2314 &bgp_102,
2315 FIB_SOURCE_API,
2316 FIB_PROTOCOL_IP4,
2317 &pfx_1_1_1_2_s_32.fp_addr,
2318 ~0, // no index provided.
2319 fib_index, // same as route's FIB
2320 1,
2321 FIB_ROUTE_PATH_FLAG_NONE);
2322 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2323 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2324
2325 /*
2326 * remove the remaining recursives
2327 */
2328 fib_table_entry_path_remove(fib_index,
2329 &bgp_100_pfx,
2330 FIB_SOURCE_API,
2331 FIB_PROTOCOL_IP4,
2332 &pfx_1_1_1_1_s_32.fp_addr,
2333 ~0, // no index provided.
2334 fib_index, // same as route's FIB
2335 1,
2336 FIB_ROUTE_PATH_FLAG_NONE);
2337 fib_table_entry_path_remove(fib_index,
2338 &bgp_101_pfx,
2339 FIB_SOURCE_API,
2340 FIB_PROTOCOL_IP4,
2341 &pfx_1_1_1_1_s_32.fp_addr,
2342 ~0, // no index provided.
2343 fib_index, // same as route's FIB
2344 1,
2345 FIB_ROUTE_PATH_FLAG_NONE);
2346 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2347 FIB_NODE_INDEX_INVALID),
2348 "100.100.100.100/32 removed");
2349 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2350 FIB_NODE_INDEX_INVALID),
2351 "100.100.100.101/32 removed");
2352
2353 /*
2354 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2355 */
2356 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2357 fib_path_list_db_size());
2358 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2359 fib_path_list_pool_size());
2360 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2361 fib_entry_pool_size());
2362
2363 /*
2364 * Add a recursive route via a connected cover, using an adj-fib that does exist
2365 */
2366 fib_table_entry_path_add(fib_index,
2367 &bgp_200_pfx,
2368 FIB_SOURCE_API,
2369 FIB_ENTRY_FLAG_NONE,
2370 FIB_PROTOCOL_IP4,
2371 &nh_10_10_10_1,
2372 ~0, // no index provided.
2373 fib_index, // Same as route's FIB
2374 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002375 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002376 FIB_ROUTE_PATH_FLAG_NONE);
2377
2378 /*
2379 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2380 */
2381 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2382 fib_path_list_db_size());
2383 FIB_TEST((NBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
2384 fib_path_list_pool_size());
2385 FIB_TEST((NBR+8 == fib_entry_pool_size()), "entry pool size is %d",
2386 fib_entry_pool_size());
2387
2388 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2389 dpo = fib_entry_contribute_ip_forwarding(fei);
2390
2391 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2392 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2393
2394 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2395 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2396
2397 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2398 "Flags set on RR via existing attached");
2399
2400 /*
2401 * Add a recursive route via a connected cover, using and adj-fib that does
2402 * not exist
2403 */
2404 ip46_address_t nh_10_10_10_3 = {
2405 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2406 };
2407 fib_prefix_t pfx_10_10_10_3 = {
2408 .fp_len = 32,
2409 .fp_proto = FIB_PROTOCOL_IP4,
2410 .fp_addr = nh_10_10_10_3,
2411 };
2412
2413 fib_table_entry_path_add(fib_index,
2414 &bgp_201_pfx,
2415 FIB_SOURCE_API,
2416 FIB_ENTRY_FLAG_NONE,
2417 FIB_PROTOCOL_IP4,
2418 &nh_10_10_10_3,
2419 ~0, // no index provided.
2420 fib_index,
2421 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002422 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002423 FIB_ROUTE_PATH_FLAG_NONE);
2424
2425 /*
2426 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2427 * one unshared non-recursive via 10.10.10.3
2428 */
2429 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2430 fib_path_list_db_size());
2431 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2432 fib_path_list_pool_size());
2433 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2434 fib_entry_pool_size());
2435
2436 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002437 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002438 &nh_10_10_10_3,
2439 tm->hw[0]->sw_if_index);
2440
2441 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2442 dpo = fib_entry_contribute_ip_forwarding(fei);
2443 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2444 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2445
2446 ai = fib_entry_get_adj(fei);
2447 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2448 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2449 fib_entry_get_flags(fei)),
2450 "Flags set on RR via non-existing attached");
2451
2452 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2453 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2454
2455 adj_unlock(ai_03);
2456
2457 /*
2458 * remove the recursives
2459 */
2460 fib_table_entry_path_remove(fib_index,
2461 &bgp_200_pfx,
2462 FIB_SOURCE_API,
2463 FIB_PROTOCOL_IP4,
2464 &nh_10_10_10_1,
2465 ~0, // no index provided.
2466 fib_index, // same as route's FIB
2467 1,
2468 FIB_ROUTE_PATH_FLAG_NONE);
2469 fib_table_entry_path_remove(fib_index,
2470 &bgp_201_pfx,
2471 FIB_SOURCE_API,
2472 FIB_PROTOCOL_IP4,
2473 &nh_10_10_10_3,
2474 ~0, // no index provided.
2475 fib_index, // same as route's FIB
2476 1,
2477 FIB_ROUTE_PATH_FLAG_NONE);
2478
2479 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2480 FIB_NODE_INDEX_INVALID),
2481 "200.200.200.201/32 removed");
2482 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2483 FIB_NODE_INDEX_INVALID),
2484 "200.200.200.200/32 removed");
2485 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2486 FIB_NODE_INDEX_INVALID),
2487 "10.10.10.3/32 removed");
2488
2489 /*
2490 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2491 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2492 */
2493 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2494 fib_path_list_db_size());
2495 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2496 fib_path_list_pool_size());
2497 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2498 fib_entry_pool_size());
2499
2500
2501 /*
2502 * RECURSION LOOPS
2503 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2504 */
2505 fib_prefix_t pfx_5_5_5_5_s_32 = {
2506 .fp_len = 32,
2507 .fp_proto = FIB_PROTOCOL_IP4,
2508 .fp_addr = {
2509 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2510 },
2511 };
2512 fib_prefix_t pfx_5_5_5_6_s_32 = {
2513 .fp_len = 32,
2514 .fp_proto = FIB_PROTOCOL_IP4,
2515 .fp_addr = {
2516 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2517 },
2518 };
2519 fib_prefix_t pfx_5_5_5_7_s_32 = {
2520 .fp_len = 32,
2521 .fp_proto = FIB_PROTOCOL_IP4,
2522 .fp_addr = {
2523 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2524 },
2525 };
2526
2527 fib_table_entry_path_add(fib_index,
2528 &pfx_5_5_5_5_s_32,
2529 FIB_SOURCE_API,
2530 FIB_ENTRY_FLAG_NONE,
2531 FIB_PROTOCOL_IP4,
2532 &pfx_5_5_5_6_s_32.fp_addr,
2533 ~0, // no index provided.
2534 fib_index,
2535 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002536 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002537 FIB_ROUTE_PATH_FLAG_NONE);
2538 fib_table_entry_path_add(fib_index,
2539 &pfx_5_5_5_6_s_32,
2540 FIB_SOURCE_API,
2541 FIB_ENTRY_FLAG_NONE,
2542 FIB_PROTOCOL_IP4,
2543 &pfx_5_5_5_7_s_32.fp_addr,
2544 ~0, // no index provided.
2545 fib_index,
2546 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002547 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002548 FIB_ROUTE_PATH_FLAG_NONE);
2549 fib_table_entry_path_add(fib_index,
2550 &pfx_5_5_5_7_s_32,
2551 FIB_SOURCE_API,
2552 FIB_ENTRY_FLAG_NONE,
2553 FIB_PROTOCOL_IP4,
2554 &pfx_5_5_5_5_s_32.fp_addr,
2555 ~0, // no index provided.
2556 fib_index,
2557 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002558 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002559 FIB_ROUTE_PATH_FLAG_NONE);
2560 /*
2561 * +3 entries, +3 shared path-list
2562 */
2563 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2564 fib_path_list_db_size());
2565 FIB_TEST((NBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
2566 fib_path_list_pool_size());
2567 FIB_TEST((NBR+10 == fib_entry_pool_size()), "entry pool size is %d",
2568 fib_entry_pool_size());
2569
2570 /*
2571 * All the entries have only looped paths, so they are all drop
2572 */
2573 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2574 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2575 "LB for 5.5.5.7/32 is via adj for DROP");
2576 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2577 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2578 "LB for 5.5.5.5/32 is via adj for DROP");
2579 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2580 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2581 "LB for 5.5.5.6/32 is via adj for DROP");
2582
2583 /*
2584 * provide 5.5.5.6/32 with alternate path.
2585 * this will allow only 5.5.5.6/32 to forward with this path, the others
2586 * are still drop since the loop is still present.
2587 */
2588 fib_table_entry_path_add(fib_index,
2589 &pfx_5_5_5_6_s_32,
2590 FIB_SOURCE_API,
2591 FIB_ENTRY_FLAG_NONE,
2592 FIB_PROTOCOL_IP4,
2593 &nh_10_10_10_1,
2594 tm->hw[0]->sw_if_index,
2595 ~0,
2596 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002597 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002598 FIB_ROUTE_PATH_FLAG_NONE);
2599
2600
2601 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2602 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2603
2604 lb = load_balance_get(dpo1->dpoi_index);
2605 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2606
2607 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2608 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2609 FIB_TEST((ai_01 == dpo2->dpoi_index),
2610 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2611
2612 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2613 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2614 "LB for 5.5.5.7/32 is via adj for DROP");
2615 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2616 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2617 "LB for 5.5.5.5/32 is via adj for DROP");
2618
2619 /*
2620 * remove the alternate path for 5.5.5.6/32
2621 * back to all drop
2622 */
2623 fib_table_entry_path_remove(fib_index,
2624 &pfx_5_5_5_6_s_32,
2625 FIB_SOURCE_API,
2626 FIB_PROTOCOL_IP4,
2627 &nh_10_10_10_1,
2628 tm->hw[0]->sw_if_index,
2629 ~0,
2630 1,
2631 FIB_ROUTE_PATH_FLAG_NONE);
2632
2633 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2634 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2635 "LB for 5.5.5.7/32 is via adj for DROP");
2636 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2637 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2638 "LB for 5.5.5.5/32 is via adj for DROP");
2639 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2640 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2641 "LB for 5.5.5.6/32 is via adj for DROP");
2642
2643 /*
2644 * break the loop by giving 5.5.5.5/32 a new set of paths
2645 * expect all to forward via this new path.
2646 */
2647 fib_table_entry_update_one_path(fib_index,
2648 &pfx_5_5_5_5_s_32,
2649 FIB_SOURCE_API,
2650 FIB_ENTRY_FLAG_NONE,
2651 FIB_PROTOCOL_IP4,
2652 &nh_10_10_10_1,
2653 tm->hw[0]->sw_if_index,
2654 ~0, // invalid fib index
2655 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002656 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002657 FIB_ROUTE_PATH_FLAG_NONE);
2658
2659 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2660 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2661 lb = load_balance_get(dpo1->dpoi_index);
2662 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2663
2664 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2665 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2666 FIB_TEST((ai_01 == dpo2->dpoi_index),
2667 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2668
2669 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2670 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2671
2672 lb = load_balance_get(dpo2->dpoi_index);
2673 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2674 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2675 "5.5.5.5.7 via 5.5.5.5");
2676
2677 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2678 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2679
2680 lb = load_balance_get(dpo1->dpoi_index);
2681 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2682 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2683 "5.5.5.5.6 via 5.5.5.7");
2684
2685 /*
2686 * revert back to the loop. so we can remove the prefixes with
2687 * the loop intact
2688 */
2689 fib_table_entry_update_one_path(fib_index,
2690 &pfx_5_5_5_5_s_32,
2691 FIB_SOURCE_API,
2692 FIB_ENTRY_FLAG_NONE,
2693 FIB_PROTOCOL_IP4,
2694 &pfx_5_5_5_6_s_32.fp_addr,
2695 ~0, // no index provided.
2696 fib_index,
2697 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002698 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002699 FIB_ROUTE_PATH_FLAG_NONE);
2700
2701 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2702 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2703 "LB for 5.5.5.7/32 is via adj for DROP");
2704 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2705 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2706 "LB for 5.5.5.5/32 is via adj for DROP");
2707 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2708 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2709 "LB for 5.5.5.6/32 is via adj for DROP");
2710
2711 /*
2712 * remove all the 5.5.5.x/32 prefixes
2713 */
2714 fib_table_entry_path_remove(fib_index,
2715 &pfx_5_5_5_5_s_32,
2716 FIB_SOURCE_API,
2717 FIB_PROTOCOL_IP4,
2718 &pfx_5_5_5_6_s_32.fp_addr,
2719 ~0, // no index provided.
2720 fib_index, // same as route's FIB
2721 1,
2722 FIB_ROUTE_PATH_FLAG_NONE);
2723 fib_table_entry_path_remove(fib_index,
2724 &pfx_5_5_5_6_s_32,
2725 FIB_SOURCE_API,
2726 FIB_PROTOCOL_IP4,
2727 &pfx_5_5_5_7_s_32.fp_addr,
2728 ~0, // no index provided.
2729 fib_index, // same as route's FIB
2730 1,
2731 FIB_ROUTE_PATH_FLAG_NONE);
2732 fib_table_entry_path_remove(fib_index,
2733 &pfx_5_5_5_7_s_32,
2734 FIB_SOURCE_API,
2735 FIB_PROTOCOL_IP4,
2736 &pfx_5_5_5_5_s_32.fp_addr,
2737 ~0, // no index provided.
2738 fib_index, // same as route's FIB
2739 1,
2740 FIB_ROUTE_PATH_FLAG_NONE);
2741 fib_table_entry_path_remove(fib_index,
2742 &pfx_5_5_5_6_s_32,
2743 FIB_SOURCE_API,
2744 FIB_PROTOCOL_IP4,
2745 &nh_10_10_10_2,
2746 ~0, // no index provided.
2747 fib_index, // same as route's FIB
2748 1,
2749 FIB_ROUTE_PATH_FLAG_NONE);
2750
2751 /*
2752 * -3 entries, -3 shared path-list
2753 */
2754 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2755 fib_path_list_db_size());
2756 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2757 fib_path_list_pool_size());
2758 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2759 fib_entry_pool_size());
2760
2761 /*
2762 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2763 */
2764 fib_table_entry_path_add(fib_index,
2765 &pfx_5_5_5_6_s_32,
2766 FIB_SOURCE_API,
2767 FIB_ENTRY_FLAG_NONE,
2768 FIB_PROTOCOL_IP4,
2769 &pfx_5_5_5_6_s_32.fp_addr,
2770 ~0, // no index provided.
2771 fib_index,
2772 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002773 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002774 FIB_ROUTE_PATH_FLAG_NONE);
2775 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2776 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2777 "1-level 5.5.5.6/32 loop is via adj for DROP");
2778
2779 fib_table_entry_path_remove(fib_index,
2780 &pfx_5_5_5_6_s_32,
2781 FIB_SOURCE_API,
2782 FIB_PROTOCOL_IP4,
2783 &pfx_5_5_5_6_s_32.fp_addr,
2784 ~0, // no index provided.
2785 fib_index, // same as route's FIB
2786 1,
2787 FIB_ROUTE_PATH_FLAG_NONE);
2788 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2789 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2790 "1-level 5.5.5.6/32 loop is removed");
2791
2792 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002793 * A recursive route whose next-hop is covered by the prefix.
2794 * This would mean the via-fib, which inherits forwarding from its
2795 * cover, thus picks up forwarding from the prfix, which is via the
2796 * via-fib, and we have a loop.
2797 */
2798 fib_prefix_t pfx_23_23_23_0_s_24 = {
2799 .fp_len = 24,
2800 .fp_proto = FIB_PROTOCOL_IP4,
2801 .fp_addr = {
2802 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2803 },
2804 };
2805 fib_prefix_t pfx_23_23_23_23_s_32 = {
2806 .fp_len = 32,
2807 .fp_proto = FIB_PROTOCOL_IP4,
2808 .fp_addr = {
2809 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2810 },
2811 };
2812 fei = fib_table_entry_path_add(fib_index,
2813 &pfx_23_23_23_0_s_24,
2814 FIB_SOURCE_API,
2815 FIB_ENTRY_FLAG_NONE,
2816 FIB_PROTOCOL_IP4,
2817 &pfx_23_23_23_23_s_32.fp_addr,
2818 ~0, // recursive
2819 fib_index,
2820 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002821 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002822 FIB_ROUTE_PATH_FLAG_NONE);
2823 dpo = fib_entry_contribute_ip_forwarding(fei);
2824 FIB_TEST(load_balance_is_drop(dpo),
2825 "23.23.23.0/24 via covered is DROP");
2826 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2827
2828 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002829 * add-remove test. no change.
2830 */
2831 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2832 fib_path_list_db_size());
2833 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
2834 fib_path_list_pool_size());
2835 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
2836 fib_entry_pool_size());
2837
2838 /*
2839 * A recursive route with recursion constraints.
2840 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2841 */
2842 fib_table_entry_path_add(fib_index,
2843 &bgp_200_pfx,
2844 FIB_SOURCE_API,
2845 FIB_ENTRY_FLAG_NONE,
2846 FIB_PROTOCOL_IP4,
2847 &nh_1_1_1_1,
2848 ~0,
2849 fib_index,
2850 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002851 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002852 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2853
2854 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2855 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2856
2857 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2858 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2859
2860 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2861 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2862
2863 /*
2864 * save the load-balance. we expect it to be inplace modified
2865 */
2866 lb = load_balance_get(dpo1->dpoi_index);
2867
2868 /*
2869 * add a covering prefix for the via fib that would otherwise serve
2870 * as the resolving route when the host is removed
2871 */
2872 fib_table_entry_path_add(fib_index,
2873 &pfx_1_1_1_0_s_28,
2874 FIB_SOURCE_API,
2875 FIB_ENTRY_FLAG_NONE,
2876 FIB_PROTOCOL_IP4,
2877 &nh_10_10_10_1,
2878 tm->hw[0]->sw_if_index,
2879 ~0, // invalid fib index
2880 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002881 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002882 FIB_ROUTE_PATH_FLAG_NONE);
2883 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
2884 ai = fib_entry_get_adj(fei);
2885 FIB_TEST((ai == ai_01),
2886 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
2887
2888 /*
2889 * remove the host via FIB - expect the BGP prefix to be drop
2890 */
2891 fib_table_entry_path_remove(fib_index,
2892 &pfx_1_1_1_1_s_32,
2893 FIB_SOURCE_API,
2894 FIB_PROTOCOL_IP4,
2895 &nh_10_10_10_1,
2896 tm->hw[0]->sw_if_index,
2897 ~0, // invalid fib index
2898 1,
2899 FIB_ROUTE_PATH_FLAG_NONE);
2900
2901 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2902 "adj for 200.200.200.200/32 is recursive via adj for DROP");
2903
2904 /*
2905 * add the via-entry host reoute back. expect to resolve again
2906 */
2907 fib_table_entry_path_add(fib_index,
2908 &pfx_1_1_1_1_s_32,
2909 FIB_SOURCE_API,
2910 FIB_ENTRY_FLAG_NONE,
2911 FIB_PROTOCOL_IP4,
2912 &nh_10_10_10_1,
2913 tm->hw[0]->sw_if_index,
2914 ~0, // invalid fib index
2915 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002916 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002917 FIB_ROUTE_PATH_FLAG_NONE);
2918 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2919 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2920
2921 /*
2922 * add another path for the recursive. it will then have 2.
2923 */
2924 fib_prefix_t pfx_1_1_1_3_s_32 = {
2925 .fp_len = 32,
2926 .fp_proto = FIB_PROTOCOL_IP4,
2927 .fp_addr = {
2928 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
2929 },
2930 };
2931 fib_table_entry_path_add(fib_index,
2932 &pfx_1_1_1_3_s_32,
2933 FIB_SOURCE_API,
2934 FIB_ENTRY_FLAG_NONE,
2935 FIB_PROTOCOL_IP4,
2936 &nh_10_10_10_2,
2937 tm->hw[0]->sw_if_index,
2938 ~0, // invalid fib index
2939 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002940 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002941 FIB_ROUTE_PATH_FLAG_NONE);
2942
2943 fib_table_entry_path_add(fib_index,
2944 &bgp_200_pfx,
2945 FIB_SOURCE_API,
2946 FIB_ENTRY_FLAG_NONE,
2947 FIB_PROTOCOL_IP4,
2948 &pfx_1_1_1_3_s_32.fp_addr,
2949 ~0,
2950 fib_index,
2951 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002952 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002953 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2954
2955 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2956 dpo = fib_entry_contribute_ip_forwarding(fei);
2957
2958 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2959 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2960 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
2961 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2962 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
2963 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2964 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
2965 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
2966
2967 /*
2968 * expect the lb-map used by the recursive's load-balance is using both buckets
2969 */
2970 load_balance_map_t *lbm;
2971 index_t lbmi;
2972
2973 lb = load_balance_get(dpo->dpoi_index);
2974 lbmi = lb->lb_map;
2975 load_balance_map_lock(lbmi);
2976 lbm = load_balance_map_get(lbmi);
2977
2978 FIB_TEST(lbm->lbm_buckets[0] == 0,
2979 "LB maps's bucket 0 is %d",
2980 lbm->lbm_buckets[0]);
2981 FIB_TEST(lbm->lbm_buckets[1] == 1,
2982 "LB maps's bucket 1 is %d",
2983 lbm->lbm_buckets[1]);
2984
2985 /*
2986 * withdraw one of the /32 via-entrys.
2987 * that ECMP path will be unresolved and forwarding should continue on the
2988 * other available path. this is an iBGP PIC edge failover.
2989 * Test the forwarding changes without re-fetching the adj from the
2990 * recursive entry. this ensures its the same one that is updated; i.e. an
2991 * inplace-modify.
2992 */
2993 fib_table_entry_path_remove(fib_index,
2994 &pfx_1_1_1_1_s_32,
2995 FIB_SOURCE_API,
2996 FIB_PROTOCOL_IP4,
2997 &nh_10_10_10_1,
2998 tm->hw[0]->sw_if_index,
2999 ~0, // invalid fib index
3000 1,
3001 FIB_ROUTE_PATH_FLAG_NONE);
3002
3003 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3004 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3005 "post PIC 200.200.200.200/32 was inplace modified");
3006
3007 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3008 "post PIC adj for 200.200.200.200/32 is recursive"
3009 " via adj for 1.1.1.3");
3010
3011 /*
3012 * the LB maps that was locked above should have been modified to remove
3013 * the path that was down, and thus its bucket points to a path that is
3014 * still up.
3015 */
3016 FIB_TEST(lbm->lbm_buckets[0] == 1,
3017 "LB maps's bucket 0 is %d",
3018 lbm->lbm_buckets[0]);
3019 FIB_TEST(lbm->lbm_buckets[1] == 1,
3020 "LB maps's bucket 1 is %d",
3021 lbm->lbm_buckets[1]);
3022
3023 load_balance_map_unlock(lb->lb_map);
3024
3025 /*
3026 * add it back. again
3027 */
3028 fib_table_entry_path_add(fib_index,
3029 &pfx_1_1_1_1_s_32,
3030 FIB_SOURCE_API,
3031 FIB_ENTRY_FLAG_NONE,
3032 FIB_PROTOCOL_IP4,
3033 &nh_10_10_10_1,
3034 tm->hw[0]->sw_if_index,
3035 ~0, // invalid fib index
3036 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003037 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003038 FIB_ROUTE_PATH_FLAG_NONE);
3039
3040 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3041 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3042 "via adj for 1.1.1.1");
3043 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3044 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3045 "via adj for 1.1.1.3");
3046
3047 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3048 dpo = fib_entry_contribute_ip_forwarding(fei);
3049 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3050 "post PIC 200.200.200.200/32 was inplace modified");
3051
3052 /*
3053 * add a 3rd path. this makes the LB 16 buckets.
3054 */
3055 fib_table_entry_path_add(fib_index,
3056 &bgp_200_pfx,
3057 FIB_SOURCE_API,
3058 FIB_ENTRY_FLAG_NONE,
3059 FIB_PROTOCOL_IP4,
3060 &pfx_1_1_1_2_s_32.fp_addr,
3061 ~0,
3062 fib_index,
3063 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003064 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003065 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3066
3067 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3068 dpo = fib_entry_contribute_ip_forwarding(fei);
3069 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3070 "200.200.200.200/32 was inplace modified for 3rd path");
3071 FIB_TEST(16 == lb->lb_n_buckets,
3072 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3073
3074 lbmi = lb->lb_map;
3075 load_balance_map_lock(lbmi);
3076 lbm = load_balance_map_get(lbmi);
3077
3078 for (ii = 0; ii < 16; ii++)
3079 {
3080 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3081 "LB Map for 200.200.200.200/32 at %d is %d",
3082 ii, lbm->lbm_buckets[ii]);
3083 }
3084
3085 /*
3086 * trigger PIC by removing the first via-entry
3087 * the first 6 buckets of the map should map to the next 6
3088 */
3089 fib_table_entry_path_remove(fib_index,
3090 &pfx_1_1_1_1_s_32,
3091 FIB_SOURCE_API,
3092 FIB_PROTOCOL_IP4,
3093 &nh_10_10_10_1,
3094 tm->hw[0]->sw_if_index,
3095 ~0,
3096 1,
3097 FIB_ROUTE_PATH_FLAG_NONE);
3098
3099 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3100 dpo = fib_entry_contribute_ip_forwarding(fei);
3101 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3102 "200.200.200.200/32 was inplace modified for 3rd path");
3103 FIB_TEST(2 == lb->lb_n_buckets,
3104 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3105
3106 for (ii = 0; ii < 6; ii++)
3107 {
3108 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3109 "LB Map for 200.200.200.200/32 at %d is %d",
3110 ii, lbm->lbm_buckets[ii]);
3111 }
3112 for (ii = 6; ii < 16; ii++)
3113 {
3114 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3115 "LB Map for 200.200.200.200/32 at %d is %d",
3116 ii, lbm->lbm_buckets[ii]);
3117 }
3118
3119
3120 /*
3121 * tidy up
3122 */
3123 fib_table_entry_path_add(fib_index,
3124 &pfx_1_1_1_1_s_32,
3125 FIB_SOURCE_API,
3126 FIB_ENTRY_FLAG_NONE,
3127 FIB_PROTOCOL_IP4,
3128 &nh_10_10_10_1,
3129 tm->hw[0]->sw_if_index,
3130 ~0,
3131 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003132 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003133 FIB_ROUTE_PATH_FLAG_NONE);
3134
3135 fib_table_entry_path_remove(fib_index,
3136 &bgp_200_pfx,
3137 FIB_SOURCE_API,
3138 FIB_PROTOCOL_IP4,
3139 &pfx_1_1_1_2_s_32.fp_addr,
3140 ~0,
3141 fib_index,
3142 1,
3143 MPLS_LABEL_INVALID);
3144 fib_table_entry_path_remove(fib_index,
3145 &bgp_200_pfx,
3146 FIB_SOURCE_API,
3147 FIB_PROTOCOL_IP4,
3148 &nh_1_1_1_1,
3149 ~0,
3150 fib_index,
3151 1,
3152 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3153 fib_table_entry_path_remove(fib_index,
3154 &bgp_200_pfx,
3155 FIB_SOURCE_API,
3156 FIB_PROTOCOL_IP4,
3157 &pfx_1_1_1_3_s_32.fp_addr,
3158 ~0,
3159 fib_index,
3160 1,
3161 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3162 fib_table_entry_delete(fib_index,
3163 &pfx_1_1_1_3_s_32,
3164 FIB_SOURCE_API);
3165 fib_table_entry_delete(fib_index,
3166 &pfx_1_1_1_0_s_28,
3167 FIB_SOURCE_API);
3168 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3169 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3170 "1.1.1.1/28 removed");
3171 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3172 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3173 "1.1.1.3/32 removed");
3174 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3175 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3176 "200.200.200.200/32 removed");
3177
3178 /*
3179 * add-remove test. no change.
3180 */
3181 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3182 fib_path_list_db_size());
3183 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3184 fib_path_list_pool_size());
3185 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3186 fib_entry_pool_size());
3187
3188 /*
3189 * A route whose paths are built up iteratively and then removed
3190 * all at once
3191 */
3192 fib_prefix_t pfx_4_4_4_4_s_32 = {
3193 .fp_len = 32,
3194 .fp_proto = FIB_PROTOCOL_IP4,
3195 .fp_addr = {
3196 /* 4.4.4.4/32 */
3197 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3198 },
3199 };
3200
3201 fib_table_entry_path_add(fib_index,
3202 &pfx_4_4_4_4_s_32,
3203 FIB_SOURCE_API,
3204 FIB_ENTRY_FLAG_NONE,
3205 FIB_PROTOCOL_IP4,
3206 &nh_10_10_10_1,
3207 tm->hw[0]->sw_if_index,
3208 ~0,
3209 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003210 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003211 FIB_ROUTE_PATH_FLAG_NONE);
3212 fib_table_entry_path_add(fib_index,
3213 &pfx_4_4_4_4_s_32,
3214 FIB_SOURCE_API,
3215 FIB_ENTRY_FLAG_NONE,
3216 FIB_PROTOCOL_IP4,
3217 &nh_10_10_10_2,
3218 tm->hw[0]->sw_if_index,
3219 ~0,
3220 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003221 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003222 FIB_ROUTE_PATH_FLAG_NONE);
3223 fib_table_entry_path_add(fib_index,
3224 &pfx_4_4_4_4_s_32,
3225 FIB_SOURCE_API,
3226 FIB_ENTRY_FLAG_NONE,
3227 FIB_PROTOCOL_IP4,
3228 &nh_10_10_10_3,
3229 tm->hw[0]->sw_if_index,
3230 ~0,
3231 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003232 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003233 FIB_ROUTE_PATH_FLAG_NONE);
3234 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3235 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3236 "4.4.4.4/32 present");
3237
3238 fib_table_entry_delete(fib_index,
3239 &pfx_4_4_4_4_s_32,
3240 FIB_SOURCE_API);
3241 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3242 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3243 "4.4.4.4/32 removed");
3244
3245 /*
3246 * add-remove test. no change.
3247 */
3248 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3249 fib_path_list_db_size());
3250 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3251 fib_path_list_pool_size());
3252 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3253 fib_entry_pool_size());
3254
3255 /*
3256 * A route with multiple paths at once
3257 */
3258 fib_route_path_t *r_paths = NULL;
3259
3260 for (ii = 0; ii < 4; ii++)
3261 {
3262 fib_route_path_t r_path = {
3263 .frp_proto = FIB_PROTOCOL_IP4,
3264 .frp_addr = {
3265 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3266 },
3267 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3268 .frp_weight = 1,
3269 .frp_fib_index = ~0,
3270 };
3271 vec_add1(r_paths, r_path);
3272 }
3273
3274 fib_table_entry_update(fib_index,
3275 &pfx_4_4_4_4_s_32,
3276 FIB_SOURCE_API,
3277 FIB_ENTRY_FLAG_NONE,
3278 r_paths);
3279
3280 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3281 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3282 dpo = fib_entry_contribute_ip_forwarding(fei);
3283
3284 lb = load_balance_get(dpo->dpoi_index);
3285 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3286
3287 fib_table_entry_delete(fib_index,
3288 &pfx_4_4_4_4_s_32,
3289 FIB_SOURCE_API);
3290 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3291 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3292 "4.4.4.4/32 removed");
3293 vec_free(r_paths);
3294
3295 /*
3296 * add-remove test. no change.
3297 */
3298 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3299 fib_path_list_db_size());
3300 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3301 fib_path_list_pool_size());
3302 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3303 fib_entry_pool_size());
3304
3305 /*
3306 * A route deag route
3307 */
3308 fib_table_entry_path_add(fib_index,
3309 &pfx_4_4_4_4_s_32,
3310 FIB_SOURCE_API,
3311 FIB_ENTRY_FLAG_NONE,
3312 FIB_PROTOCOL_IP4,
3313 &zero_addr,
3314 ~0,
3315 fib_index,
3316 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003317 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003318 FIB_ROUTE_PATH_FLAG_NONE);
3319
3320 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3321 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3322
3323 dpo = fib_entry_contribute_ip_forwarding(fei);
3324 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3325 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3326
3327 FIB_TEST((fib_index == lkd->lkd_fib_index),
3328 "4.4.4.4/32 is deag in %d %U",
3329 lkd->lkd_fib_index,
3330 format_dpo_id, dpo, 0);
3331
3332 fib_table_entry_delete(fib_index,
3333 &pfx_4_4_4_4_s_32,
3334 FIB_SOURCE_API);
3335 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3336 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3337 "4.4.4.4/32 removed");
3338 vec_free(r_paths);
3339
3340 /*
3341 * add-remove test. no change.
3342 */
3343 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3344 fib_path_list_db_size());
3345 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3346 fib_path_list_pool_size());
3347 FIB_TEST((NBR+7 == fib_entry_pool_size()), "entry pool size is %d",
3348 fib_entry_pool_size());
3349
3350 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003351 * Duplicate paths:
3352 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3353 */
3354 fib_prefix_t pfx_34_1_1_1_s_32 = {
3355 .fp_len = 32,
3356 .fp_proto = FIB_PROTOCOL_IP4,
3357 .fp_addr = {
3358 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3359 },
3360 };
3361 fib_prefix_t pfx_34_34_1_1_s_32 = {
3362 .fp_len = 32,
3363 .fp_proto = FIB_PROTOCOL_IP4,
3364 .fp_addr = {
3365 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3366 },
3367 };
3368 fei = fib_table_entry_path_add(fib_index,
3369 &pfx_34_1_1_1_s_32,
3370 FIB_SOURCE_API,
3371 FIB_ENTRY_FLAG_NONE,
3372 FIB_PROTOCOL_IP4,
3373 &pfx_34_34_1_1_s_32.fp_addr,
3374 ~0,
3375 fib_index,
3376 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003377 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003378 FIB_ROUTE_PATH_FLAG_NONE);
3379 fei = fib_table_entry_path_add(fib_index,
3380 &pfx_34_1_1_1_s_32,
3381 FIB_SOURCE_API,
3382 FIB_ENTRY_FLAG_NONE,
3383 FIB_PROTOCOL_IP4,
3384 &pfx_34_34_1_1_s_32.fp_addr,
3385 ~0,
3386 fib_index,
3387 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003388 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003389 FIB_ROUTE_PATH_FLAG_NONE);
3390 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3391 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3392
3393 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003394 * CLEANUP
3395 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3396 * all of which are via 10.10.10.1, Itf1
3397 */
3398 fib_table_entry_path_remove(fib_index,
3399 &pfx_1_1_1_2_s_32,
3400 FIB_SOURCE_API,
3401 FIB_PROTOCOL_IP4,
3402 &nh_10_10_10_1,
3403 tm->hw[0]->sw_if_index,
3404 ~0,
3405 1,
3406 FIB_ROUTE_PATH_FLAG_NONE);
3407 fib_table_entry_path_remove(fib_index,
3408 &pfx_1_1_1_1_s_32,
3409 FIB_SOURCE_API,
3410 FIB_PROTOCOL_IP4,
3411 &nh_10_10_10_1,
3412 tm->hw[0]->sw_if_index,
3413 ~0,
3414 1,
3415 FIB_ROUTE_PATH_FLAG_NONE);
3416 fib_table_entry_path_remove(fib_index,
3417 &pfx_1_1_2_0_s_24,
3418 FIB_SOURCE_API,
3419 FIB_PROTOCOL_IP4,
3420 &nh_10_10_10_1,
3421 tm->hw[0]->sw_if_index,
3422 ~0,
3423 1,
3424 FIB_ROUTE_PATH_FLAG_NONE);
3425
3426 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3427 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3428 "1.1.1.1/32 removed");
3429 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3430 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3431 "1.1.1.2/32 removed");
3432 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3433 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3434 "1.1.2.0/24 removed");
3435
3436 /*
3437 * -3 entries and -1 shared path-list
3438 */
3439 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3440 fib_path_list_db_size());
3441 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3442 fib_path_list_pool_size());
3443 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3444 fib_entry_pool_size());
3445
3446 /*
3447 * An attached-host route. Expect to link to the incomplete adj
3448 */
3449 fib_prefix_t pfx_4_1_1_1_s_32 = {
3450 .fp_len = 32,
3451 .fp_proto = FIB_PROTOCOL_IP4,
3452 .fp_addr = {
3453 /* 4.1.1.1/32 */
3454 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3455 },
3456 };
3457 fib_table_entry_path_add(fib_index,
3458 &pfx_4_1_1_1_s_32,
3459 FIB_SOURCE_API,
3460 FIB_ENTRY_FLAG_NONE,
3461 FIB_PROTOCOL_IP4,
3462 &zero_addr,
3463 tm->hw[0]->sw_if_index,
3464 fib_index,
3465 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003466 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003467 FIB_ROUTE_PATH_FLAG_NONE);
3468
3469 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3470 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3471 ai = fib_entry_get_adj(fei);
3472
3473 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003474 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003475 &pfx_4_1_1_1_s_32.fp_addr,
3476 tm->hw[0]->sw_if_index);
3477 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3478 adj_unlock(ai2);
3479
3480 /*
3481 * +1 entry and +1 shared path-list
3482 */
3483 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3484 fib_path_list_db_size());
3485 FIB_TEST((NBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
3486 fib_path_list_pool_size());
3487 FIB_TEST((NBR+5 == fib_entry_pool_size()), "entry pool size is %d",
3488 fib_entry_pool_size());
3489
3490 fib_table_entry_delete(fib_index,
3491 &pfx_4_1_1_1_s_32,
3492 FIB_SOURCE_API);
3493
3494 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3495 fib_path_list_db_size());
3496 FIB_TEST((NBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
3497 fib_path_list_pool_size());
3498 FIB_TEST((NBR+4 == fib_entry_pool_size()), "entry pool size is %d",
3499 fib_entry_pool_size());
3500
3501 /*
3502 * add a v6 prefix via v4 next-hops
3503 */
3504 fib_prefix_t pfx_2001_s_64 = {
3505 .fp_len = 64,
3506 .fp_proto = FIB_PROTOCOL_IP6,
3507 .fp_addr = {
3508 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3509 },
3510 };
3511 fei = fib_table_entry_path_add(0, //default v6 table
3512 &pfx_2001_s_64,
3513 FIB_SOURCE_API,
3514 FIB_ENTRY_FLAG_NONE,
3515 FIB_PROTOCOL_IP4,
3516 &nh_10_10_10_1,
3517 tm->hw[0]->sw_if_index,
3518 fib_index,
3519 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003520 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003521 FIB_ROUTE_PATH_FLAG_NONE);
3522
3523 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3524 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3525 ai = fib_entry_get_adj(fei);
3526 adj = adj_get(ai);
3527 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3528 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003529 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003530 "2001::/64 is link type v6");
3531 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3532 "2001::/64 ADJ-adj is NH proto v4");
3533 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3534
Neale Ranns3ee44042016-10-03 13:05:48 +01003535 /*
3536 * add a uRPF exempt prefix:
3537 * test:
3538 * - it's forwarding is drop
3539 * - it's uRPF list is not empty
3540 * - the uRPF list for the default route (it's cover) is empty
3541 */
3542 fei = fib_table_entry_special_add(fib_index,
3543 &pfx_4_1_1_1_s_32,
3544 FIB_SOURCE_URPF_EXEMPT,
3545 FIB_ENTRY_FLAG_DROP,
3546 ADJ_INDEX_INVALID);
3547 dpo = fib_entry_contribute_ip_forwarding(fei);
3548 FIB_TEST(load_balance_is_drop(dpo),
3549 "uRPF exempt 4.1.1.1/32 DROP");
3550 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3551 "uRPF list for exempt prefix has itf index 0");
3552 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3553 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3554 "uRPF list for 0.0.0.0/0 empty");
3555
3556 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003557
3558 /*
3559 * CLEANUP
3560 * remove adj-fibs:
3561 */
3562 fib_table_entry_delete(fib_index,
3563 &pfx_10_10_10_1_s_32,
3564 FIB_SOURCE_ADJ);
3565 fib_table_entry_delete(fib_index,
3566 &pfx_10_10_10_2_s_32,
3567 FIB_SOURCE_ADJ);
3568 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3569 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3570 "10.10.10.1/32 adj-fib removed");
3571 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3572 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3573 "10.10.10.2/32 adj-fib removed");
3574
3575 /*
3576 * -2 entries and -2 non-shared path-list
3577 */
3578 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3579 fib_path_list_db_size());
3580 FIB_TEST((NBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
3581 fib_path_list_pool_size());
3582 FIB_TEST((NBR+2 == fib_entry_pool_size()), "entry pool size is %d",
3583 fib_entry_pool_size());
3584
3585 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01003586 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003587 * These are the last locks on these adjs. they should thus go away.
3588 */
3589 adj_unlock(ai_02);
3590 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01003591 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003592
3593 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3594 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003595
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003596 /*
3597 * CLEANUP
3598 * remove the interface prefixes
3599 */
3600 local_pfx.fp_len = 32;
3601 fib_table_entry_special_remove(fib_index, &local_pfx,
3602 FIB_SOURCE_INTERFACE);
3603 fei = fib_table_lookup(fib_index, &local_pfx);
3604
3605 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3606 fib_table_lookup_exact_match(fib_index, &local_pfx),
3607 "10.10.10.10/32 adj-fib removed");
3608
3609 local_pfx.fp_len = 24;
3610 fib_table_entry_delete(fib_index, &local_pfx,
3611 FIB_SOURCE_INTERFACE);
3612
3613 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3614 fib_table_lookup_exact_match(fib_index, &local_pfx),
3615 "10.10.10.10/24 adj-fib removed");
3616
3617 /*
3618 * -2 entries and -2 non-shared path-list
3619 */
3620 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3621 fib_path_list_db_size());
3622 FIB_TEST((NBR == fib_path_list_pool_size()), "path list pool size is %d",
3623 fib_path_list_pool_size());
3624 FIB_TEST((NBR == fib_entry_pool_size()), "entry pool size is %d",
3625 fib_entry_pool_size());
3626
3627 /*
3628 * Last but not least, remove the VRF
3629 */
3630 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3631 FIB_PROTOCOL_IP4,
3632 FIB_SOURCE_API)),
3633 "NO API Source'd prefixes");
3634 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3635 FIB_PROTOCOL_IP4,
3636 FIB_SOURCE_RR)),
3637 "NO RR Source'd prefixes");
3638 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3639 FIB_PROTOCOL_IP4,
3640 FIB_SOURCE_INTERFACE)),
3641 "NO INterface Source'd prefixes");
3642
3643 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3644
3645 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3646 fib_path_list_db_size());
3647 FIB_TEST((NBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
3648 fib_path_list_pool_size());
3649 FIB_TEST((NBR-5 == fib_entry_pool_size()), "entry pool size is %d",
3650 fib_entry_pool_size());
Neale Ranns3ee44042016-10-03 13:05:48 +01003651 FIB_TEST((NBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
3652 pool_elts(fib_urpf_list_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003653
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003654 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003655}
3656
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003657static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003658fib_test_v6 (void)
3659{
3660 /*
3661 * In the default table check for the presence and correct forwarding
3662 * of the special entries
3663 */
3664 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
3665 const dpo_id_t *dpo, *dpo_drop;
3666 const ip_adjacency_t *adj;
3667 const receive_dpo_t *rd;
3668 test_main_t *tm;
3669 u32 fib_index;
3670 int ii;
3671
3672 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3673 adj_nbr_db_size());
3674
3675 /* via 2001:0:0:1::2 */
3676 ip46_address_t nh_2001_2 = {
3677 .ip6 = {
3678 .as_u64 = {
3679 [0] = clib_host_to_net_u64(0x2001000000000001),
3680 [1] = clib_host_to_net_u64(0x0000000000000002),
3681 },
3682 },
3683 };
3684
3685 tm = &test_main;
3686
3687 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
3688
3689 /* Find or create FIB table 11 */
3690 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
3691
3692 for (ii = 0; ii < 4; ii++)
3693 {
3694 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
3695 }
3696
3697 fib_prefix_t pfx_0_0 = {
3698 .fp_len = 0,
3699 .fp_proto = FIB_PROTOCOL_IP6,
3700 .fp_addr = {
3701 .ip6 = {
3702 {0, 0},
3703 },
3704 },
3705 };
3706
3707 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
3708 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
3709 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3710 "Default route is DROP");
3711
3712 dpo = fib_entry_contribute_ip_forwarding(dfrt);
3713 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3714 &ip6_main,
3715 1,
3716 &pfx_0_0.fp_addr.ip6)),
3717 "default-route; fwd and non-fwd tables match");
3718
3719 // FIXME - check specials.
3720
3721 /*
3722 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
3723 * each with 6 entries. All entries are special so no path-list sharing.
3724 */
3725#define NPS (5+6+6)
3726 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
3727 FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is %d",
3728 fib_path_list_pool_size());
3729 FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
3730 fib_entry_pool_size());
3731
3732 /*
3733 * add interface routes.
3734 * validate presence of /64 attached and /128 recieve.
3735 * test for the presence of the receive address in the glean and local adj
3736 *
3737 * receive on 2001:0:0:1::1/128
3738 */
3739 fib_prefix_t local_pfx = {
3740 .fp_len = 64,
3741 .fp_proto = FIB_PROTOCOL_IP6,
3742 .fp_addr = {
3743 .ip6 = {
3744 .as_u64 = {
3745 [0] = clib_host_to_net_u64(0x2001000000000001),
3746 [1] = clib_host_to_net_u64(0x0000000000000001),
3747 },
3748 },
3749 }
3750 };
3751
3752 fib_table_entry_update_one_path(fib_index, &local_pfx,
3753 FIB_SOURCE_INTERFACE,
3754 (FIB_ENTRY_FLAG_CONNECTED |
3755 FIB_ENTRY_FLAG_ATTACHED),
3756 FIB_PROTOCOL_IP6,
3757 NULL,
3758 tm->hw[0]->sw_if_index,
3759 ~0,
3760 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003761 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003762 FIB_ROUTE_PATH_FLAG_NONE);
3763 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
3764
3765 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
3766
3767 ai = fib_entry_get_adj(fei);
3768 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
3769 adj = adj_get(ai);
3770 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
3771 "attached interface adj is glean");
3772 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3773 &adj->sub_type.glean.receive_addr)),
3774 "attached interface adj is receive ok");
3775 dpo = fib_entry_contribute_ip_forwarding(fei);
3776 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3777 &ip6_main,
3778 1,
3779 &local_pfx.fp_addr.ip6)),
3780 "attached-route; fwd and non-fwd tables match");
3781
3782 local_pfx.fp_len = 128;
3783 fib_table_entry_update_one_path(fib_index, &local_pfx,
3784 FIB_SOURCE_INTERFACE,
3785 (FIB_ENTRY_FLAG_CONNECTED |
3786 FIB_ENTRY_FLAG_LOCAL),
3787 FIB_PROTOCOL_IP6,
3788 NULL,
3789 tm->hw[0]->sw_if_index,
3790 ~0, // invalid fib index
3791 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003792 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003793 FIB_ROUTE_PATH_FLAG_NONE);
3794 fei = fib_table_lookup(fib_index, &local_pfx);
3795
3796 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
3797
3798 dpo = fib_entry_contribute_ip_forwarding(fei);
3799 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3800 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
3801 "local interface adj is local");
3802 rd = receive_dpo_get(dpo->dpoi_index);
3803
3804 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3805 &rd->rd_addr)),
3806 "local interface adj is receive ok");
3807
3808 dpo = fib_entry_contribute_ip_forwarding(fei);
3809 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3810 &ip6_main,
3811 1,
3812 &local_pfx.fp_addr.ip6)),
3813 "local-route; fwd and non-fwd tables match");
3814
3815 /*
3816 * +2 entries. +2 unshared path-lists
3817 */
3818 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
3819 FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
3820 fib_path_list_pool_size());
3821 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3822 fib_entry_pool_size());
3823
3824 /*
3825 * Modify the default route to be via an adj not yet known.
3826 * this sources the defalut route with the API source, which is
3827 * a higher preference to the DEFAULT_ROUTE source
3828 */
3829 fib_table_entry_path_add(fib_index, &pfx_0_0,
3830 FIB_SOURCE_API,
3831 FIB_ENTRY_FLAG_NONE,
3832 FIB_PROTOCOL_IP6,
3833 &nh_2001_2,
3834 tm->hw[0]->sw_if_index,
3835 ~0,
3836 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003837 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003838 FIB_ROUTE_PATH_FLAG_NONE);
3839 fei = fib_table_lookup(fib_index, &pfx_0_0);
3840
3841 FIB_TEST((fei == dfrt), "default route same index");
3842 ai = fib_entry_get_adj(fei);
3843 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
3844 adj = adj_get(ai);
3845 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3846 "adj is incomplete");
3847 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
3848 "adj nbr next-hop ok");
3849
3850 /*
3851 * find the adj in the shared db
3852 */
3853 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003854 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003855 &nh_2001_2,
3856 tm->hw[0]->sw_if_index);
3857 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
3858 adj_unlock(locked_ai);
3859
3860 /*
3861 * no more entires. +1 shared path-list
3862 */
3863 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3864 fib_path_list_db_size());
3865 FIB_TEST((NPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
3866 fib_path_list_pool_size());
3867 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3868 fib_entry_pool_size());
3869
3870 /*
3871 * remove the API source from the default route. We expected
3872 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
3873 */
3874 fib_table_entry_path_remove(fib_index, &pfx_0_0,
3875 FIB_SOURCE_API,
3876 FIB_PROTOCOL_IP6,
3877 &nh_2001_2,
3878 tm->hw[0]->sw_if_index,
3879 ~0,
3880 1,
3881 FIB_ROUTE_PATH_FLAG_NONE);
3882 fei = fib_table_lookup(fib_index, &pfx_0_0);
3883
3884 FIB_TEST((fei == dfrt), "default route same index");
3885 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3886 "Default route is DROP");
3887
3888 /*
3889 * no more entires. -1 shared path-list
3890 */
3891 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3892 fib_path_list_db_size());
3893 FIB_TEST((NPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
3894 fib_path_list_pool_size());
3895 FIB_TEST((NPS+2 == fib_entry_pool_size()), "entry pool size is %d",
3896 fib_entry_pool_size());
3897
3898 /*
3899 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
3900 */
3901 fib_prefix_t pfx_2001_1_2_s_128 = {
3902 .fp_len = 128,
3903 .fp_proto = FIB_PROTOCOL_IP6,
3904 .fp_addr = {
3905 .ip6 = {
3906 .as_u64 = {
3907 [0] = clib_host_to_net_u64(0x2001000000000001),
3908 [1] = clib_host_to_net_u64(0x0000000000000002),
3909 },
3910 },
3911 }
3912 };
3913 fib_prefix_t pfx_2001_1_3_s_128 = {
3914 .fp_len = 128,
3915 .fp_proto = FIB_PROTOCOL_IP6,
3916 .fp_addr = {
3917 .ip6 = {
3918 .as_u64 = {
3919 [0] = clib_host_to_net_u64(0x2001000000000001),
3920 [1] = clib_host_to_net_u64(0x0000000000000003),
3921 },
3922 },
3923 }
3924 };
3925 u8 eth_addr[] = {
3926 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
3927 };
3928
3929 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003930 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003931 &pfx_2001_1_2_s_128.fp_addr,
3932 tm->hw[0]->sw_if_index);
3933 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
3934 adj = adj_get(ai_01);
3935 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3936 "adj is incomplete");
3937 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
3938 &adj->sub_type.nbr.next_hop)),
3939 "adj nbr next-hop ok");
3940
Neale Rannsb80c5362016-10-08 13:03:40 +01003941 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
3942 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003943 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
3944 "adj is complete");
3945 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
3946 &adj->sub_type.nbr.next_hop)),
3947 "adj nbr next-hop ok");
3948
3949 fib_table_entry_update_one_path(fib_index,
3950 &pfx_2001_1_2_s_128,
3951 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00003952 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003953 FIB_PROTOCOL_IP6,
3954 &pfx_2001_1_2_s_128.fp_addr,
3955 tm->hw[0]->sw_if_index,
3956 ~0,
3957 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003958 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003959 FIB_ROUTE_PATH_FLAG_NONE);
3960
3961 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
3962 ai = fib_entry_get_adj(fei);
3963 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
3964
3965 eth_addr[5] = 0xb2;
3966
3967 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003968 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003969 &pfx_2001_1_3_s_128.fp_addr,
3970 tm->hw[0]->sw_if_index);
3971 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
3972 adj = adj_get(ai_02);
3973 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3974 "adj is incomplete");
3975 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
3976 &adj->sub_type.nbr.next_hop)),
3977 "adj nbr next-hop ok");
3978
Neale Rannsb80c5362016-10-08 13:03:40 +01003979 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
3980 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003981 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
3982 "adj is complete");
3983 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
3984 &adj->sub_type.nbr.next_hop)),
3985 "adj nbr next-hop ok");
3986 FIB_TEST((ai_01 != ai_02), "ADJs are different");
3987
3988 fib_table_entry_update_one_path(fib_index,
3989 &pfx_2001_1_3_s_128,
3990 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00003991 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003992 FIB_PROTOCOL_IP6,
3993 &pfx_2001_1_3_s_128.fp_addr,
3994 tm->hw[0]->sw_if_index,
3995 ~0,
3996 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003997 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003998 FIB_ROUTE_PATH_FLAG_NONE);
3999
4000 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4001 ai = fib_entry_get_adj(fei);
4002 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4003
4004 /*
4005 * +2 entries, +2 unshread path-lists.
4006 */
4007 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4008 fib_path_list_db_size());
4009 FIB_TEST((NPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
4010 fib_path_list_pool_size());
4011 FIB_TEST((NPS+4 == fib_entry_pool_size()), "entry pool size is %d",
4012 fib_entry_pool_size());
4013
4014 /*
4015 * Add a 2 routes via the first ADJ. ensure path-list sharing
4016 */
4017 fib_prefix_t pfx_2001_a_s_64 = {
4018 .fp_len = 64,
4019 .fp_proto = FIB_PROTOCOL_IP6,
4020 .fp_addr = {
4021 .ip6 = {
4022 .as_u64 = {
4023 [0] = clib_host_to_net_u64(0x200100000000000a),
4024 [1] = clib_host_to_net_u64(0x0000000000000000),
4025 },
4026 },
4027 }
4028 };
4029 fib_prefix_t pfx_2001_b_s_64 = {
4030 .fp_len = 64,
4031 .fp_proto = FIB_PROTOCOL_IP6,
4032 .fp_addr = {
4033 .ip6 = {
4034 .as_u64 = {
4035 [0] = clib_host_to_net_u64(0x200100000000000b),
4036 [1] = clib_host_to_net_u64(0x0000000000000000),
4037 },
4038 },
4039 }
4040 };
4041
4042 fib_table_entry_path_add(fib_index,
4043 &pfx_2001_a_s_64,
4044 FIB_SOURCE_API,
4045 FIB_ENTRY_FLAG_NONE,
4046 FIB_PROTOCOL_IP6,
4047 &nh_2001_2,
4048 tm->hw[0]->sw_if_index,
4049 ~0,
4050 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004051 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004052 FIB_ROUTE_PATH_FLAG_NONE);
4053 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4054 ai = fib_entry_get_adj(fei);
4055 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4056 fib_table_entry_path_add(fib_index,
4057 &pfx_2001_b_s_64,
4058 FIB_SOURCE_API,
4059 FIB_ENTRY_FLAG_NONE,
4060 FIB_PROTOCOL_IP6,
4061 &nh_2001_2,
4062 tm->hw[0]->sw_if_index,
4063 ~0,
4064 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004065 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004066 FIB_ROUTE_PATH_FLAG_NONE);
4067 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4068 ai = fib_entry_get_adj(fei);
4069 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4070
4071 /*
4072 * +2 entries, +1 shared path-list.
4073 */
4074 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4075 fib_path_list_db_size());
4076 FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4077 fib_path_list_pool_size());
4078 FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4079 fib_entry_pool_size());
4080
4081 /*
4082 * add a v4 prefix via a v6 next-hop
4083 */
4084 fib_prefix_t pfx_1_1_1_1_s_32 = {
4085 .fp_len = 32,
4086 .fp_proto = FIB_PROTOCOL_IP4,
4087 .fp_addr = {
4088 .ip4.as_u32 = 0x01010101,
4089 },
4090 };
4091 fei = fib_table_entry_path_add(0, // default table
4092 &pfx_1_1_1_1_s_32,
4093 FIB_SOURCE_API,
4094 FIB_ENTRY_FLAG_NONE,
4095 FIB_PROTOCOL_IP6,
4096 &nh_2001_2,
4097 tm->hw[0]->sw_if_index,
4098 ~0,
4099 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004100 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004101 FIB_ROUTE_PATH_FLAG_NONE);
4102 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4103 "1.1.1.1/32 o v6 route present");
4104 ai = fib_entry_get_adj(fei);
4105 adj = adj_get(ai);
4106 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4107 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004108 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004109 "1.1.1.1/32 ADJ-adj is link type v4");
4110 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4111 "1.1.1.1/32 ADJ-adj is NH proto v6");
4112 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4113
4114 /*
4115 * An attached route
4116 */
4117 fib_prefix_t pfx_2001_c_s_64 = {
4118 .fp_len = 64,
4119 .fp_proto = FIB_PROTOCOL_IP6,
4120 .fp_addr = {
4121 .ip6 = {
4122 .as_u64 = {
4123 [0] = clib_host_to_net_u64(0x200100000000000c),
4124 [1] = clib_host_to_net_u64(0x0000000000000000),
4125 },
4126 },
4127 }
4128 };
4129 fib_table_entry_path_add(fib_index,
4130 &pfx_2001_c_s_64,
4131 FIB_SOURCE_CLI,
4132 FIB_ENTRY_FLAG_ATTACHED,
4133 FIB_PROTOCOL_IP6,
4134 NULL,
4135 tm->hw[0]->sw_if_index,
4136 ~0,
4137 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004138 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004139 FIB_ROUTE_PATH_FLAG_NONE);
4140 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4141 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4142 ai = fib_entry_get_adj(fei);
4143 adj = adj_get(ai);
4144 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4145 "2001:0:0:c/64 attached resolves via glean");
4146
4147 fib_table_entry_path_remove(fib_index,
4148 &pfx_2001_c_s_64,
4149 FIB_SOURCE_CLI,
4150 FIB_PROTOCOL_IP6,
4151 NULL,
4152 tm->hw[0]->sw_if_index,
4153 ~0,
4154 1,
4155 FIB_ROUTE_PATH_FLAG_NONE);
4156 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4157 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4158
4159 /*
4160 * Shutdown the interface on which we have a connected and through
4161 * which the routes are reachable.
4162 * This will result in the connected, adj-fibs, and routes linking to drop
4163 * The local/for-us prefix continues to receive.
4164 */
4165 clib_error_t * error;
4166
4167 error = vnet_sw_interface_set_flags(vnet_get_main(),
4168 tm->hw[0]->sw_if_index,
4169 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4170 FIB_TEST((NULL == error), "Interface shutdown OK");
4171
4172 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4173 dpo = fib_entry_contribute_ip_forwarding(fei);
4174 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4175 "2001::b/64 resolves via drop");
4176
4177 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4178 dpo = fib_entry_contribute_ip_forwarding(fei);
4179 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4180 "2001::a/64 resolves via drop");
4181 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4182 dpo = fib_entry_contribute_ip_forwarding(fei);
4183 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4184 "2001:0:0:1::3/64 resolves via drop");
4185 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4186 dpo = fib_entry_contribute_ip_forwarding(fei);
4187 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4188 "2001:0:0:1::2/64 resolves via drop");
4189 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4190 dpo = fib_entry_contribute_ip_forwarding(fei);
4191 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4192 "2001:0:0:1::1/128 not drop");
4193 local_pfx.fp_len = 64;
4194 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4195 dpo = fib_entry_contribute_ip_forwarding(fei);
4196 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4197 "2001:0:0:1/64 resolves via drop");
4198
4199 /*
4200 * no change
4201 */
4202 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4203 fib_path_list_db_size());
4204 FIB_TEST((NPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
4205 fib_path_list_pool_size());
4206 FIB_TEST((NPS+6 == fib_entry_pool_size()), "entry pool size is %d",
4207 fib_entry_pool_size());
4208
4209 /*
4210 * shutdown one of the other interfaces, then add a connected.
4211 * and swap one of the routes to it.
4212 */
4213 error = vnet_sw_interface_set_flags(vnet_get_main(),
4214 tm->hw[1]->sw_if_index,
4215 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4216 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4217
4218 fib_prefix_t connected_pfx = {
4219 .fp_len = 64,
4220 .fp_proto = FIB_PROTOCOL_IP6,
4221 .fp_addr = {
4222 .ip6 = {
4223 /* 2001:0:0:2::1/64 */
4224 .as_u64 = {
4225 [0] = clib_host_to_net_u64(0x2001000000000002),
4226 [1] = clib_host_to_net_u64(0x0000000000000001),
4227 },
4228 },
4229 }
4230 };
4231 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4232 FIB_SOURCE_INTERFACE,
4233 (FIB_ENTRY_FLAG_CONNECTED |
4234 FIB_ENTRY_FLAG_ATTACHED),
4235 FIB_PROTOCOL_IP6,
4236 NULL,
4237 tm->hw[1]->sw_if_index,
4238 ~0,
4239 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004240 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004241 FIB_ROUTE_PATH_FLAG_NONE);
4242 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4243 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4244 dpo = fib_entry_contribute_ip_forwarding(fei);
4245 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4246 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4247 "2001:0:0:2/64 not resolves via drop");
4248
4249 connected_pfx.fp_len = 128;
4250 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4251 FIB_SOURCE_INTERFACE,
4252 (FIB_ENTRY_FLAG_CONNECTED |
4253 FIB_ENTRY_FLAG_LOCAL),
4254 FIB_PROTOCOL_IP6,
4255 NULL,
4256 tm->hw[0]->sw_if_index,
4257 ~0, // invalid fib index
4258 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004259 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004260 FIB_ROUTE_PATH_FLAG_NONE);
4261 fei = fib_table_lookup(fib_index, &connected_pfx);
4262
4263 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4264 dpo = fib_entry_contribute_ip_forwarding(fei);
4265 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4266 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4267 "local interface adj is local");
4268 rd = receive_dpo_get(dpo->dpoi_index);
4269 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4270 &rd->rd_addr)),
4271 "local interface adj is receive ok");
4272
4273 /*
4274 * +2 entries, +2 unshared path-lists
4275 */
4276 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4277 fib_path_list_db_size());
4278 FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4279 fib_path_list_pool_size());
4280 FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4281 fib_entry_pool_size());
4282
4283
4284 /*
4285 * bring the interface back up. we expected the routes to return
4286 * to normal forwarding.
4287 */
4288 error = vnet_sw_interface_set_flags(vnet_get_main(),
4289 tm->hw[0]->sw_if_index,
4290 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4291 FIB_TEST((NULL == error), "Interface bring-up OK");
4292 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4293 ai = fib_entry_get_adj(fei);
4294 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4295 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4296 ai = fib_entry_get_adj(fei);
4297 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4298 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4299 ai = fib_entry_get_adj(fei);
4300 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4301 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4302 ai = fib_entry_get_adj(fei);
4303 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4304 local_pfx.fp_len = 64;
4305 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4306 ai = fib_entry_get_adj(fei);
4307 adj = adj_get(ai);
4308 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4309 "attached interface adj is glean");
4310
4311 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004312 * Same test as above, but this time the HW interface goes down
4313 */
4314 error = vnet_hw_interface_set_flags(vnet_get_main(),
4315 tm->hw_if_indicies[0],
4316 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4317 FIB_TEST((NULL == error), "Interface shutdown OK");
4318
4319 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4320 dpo = fib_entry_contribute_ip_forwarding(fei);
4321 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4322 "2001::b/64 resolves via drop");
4323 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4324 dpo = fib_entry_contribute_ip_forwarding(fei);
4325 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4326 "2001::a/64 resolves via drop");
4327 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4328 dpo = fib_entry_contribute_ip_forwarding(fei);
4329 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4330 "2001:0:0:1::3/128 resolves via drop");
4331 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4332 dpo = fib_entry_contribute_ip_forwarding(fei);
4333 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4334 "2001:0:0:1::2/128 resolves via drop");
4335 local_pfx.fp_len = 128;
4336 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4337 dpo = fib_entry_contribute_ip_forwarding(fei);
4338 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4339 "2001:0:0:1::1/128 not drop");
4340 local_pfx.fp_len = 64;
4341 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4342 dpo = fib_entry_contribute_ip_forwarding(fei);
4343 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4344 "2001:0:0:1/64 resolves via drop");
4345
4346 error = vnet_hw_interface_set_flags(vnet_get_main(),
4347 tm->hw_if_indicies[0],
4348 VNET_HW_INTERFACE_FLAG_LINK_UP);
4349 FIB_TEST((NULL == error), "Interface bring-up OK");
4350 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4351 ai = fib_entry_get_adj(fei);
4352 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4353 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4354 ai = fib_entry_get_adj(fei);
4355 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4356 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4357 ai = fib_entry_get_adj(fei);
4358 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4359 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4360 ai = fib_entry_get_adj(fei);
4361 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4362 local_pfx.fp_len = 64;
4363 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4364 ai = fib_entry_get_adj(fei);
4365 adj = adj_get(ai);
4366 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4367 "attached interface adj is glean");
4368
4369 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004370 * Delete the interface that the routes reolve through.
4371 * Again no routes are removed. They all point to drop.
4372 *
4373 * This is considered an error case. The control plane should
4374 * not remove interfaces through which routes resolve, but
4375 * such things can happen. ALL affected routes will drop.
4376 */
4377 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4378
4379 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4380 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4381 "2001::b/64 resolves via drop");
4382 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4383 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4384 "2001::b/64 resolves via drop");
4385 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4386 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4387 "2001:0:0:1::3/64 resolves via drop");
4388 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4389 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4390 "2001:0:0:1::2/64 resolves via drop");
4391 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4392 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4393 "2001:0:0:1::1/128 is drop");
4394 local_pfx.fp_len = 64;
4395 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4396 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4397 "2001:0:0:1/64 resolves via drop");
4398
4399 /*
4400 * no change
4401 */
4402 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4403 fib_path_list_db_size());
4404 FIB_TEST((NPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
4405 fib_path_list_pool_size());
4406 FIB_TEST((NPS+8 == fib_entry_pool_size()), "entry pool size is %d",
4407 fib_entry_pool_size());
4408
4409 /*
4410 * Add the interface back. routes stay unresolved.
4411 */
4412 error = ethernet_register_interface(vnet_get_main(),
4413 test_interface_device_class.index,
4414 0 /* instance */,
4415 hw_address,
4416 &tm->hw_if_indicies[0],
4417 /* flag change */ 0);
4418
4419 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4420 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4421 "2001::b/64 resolves via drop");
4422 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4423 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4424 "2001::b/64 resolves via drop");
4425 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4426 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4427 "2001:0:0:1::3/64 resolves via drop");
4428 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4429 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4430 "2001:0:0:1::2/64 resolves via drop");
4431 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4432 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4433 "2001:0:0:1::1/128 is drop");
4434 local_pfx.fp_len = 64;
4435 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4436 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4437 "2001:0:0:1/64 resolves via drop");
4438
4439 /*
4440 * CLEANUP ALL the routes
4441 */
4442 fib_table_entry_delete(fib_index,
4443 &pfx_2001_c_s_64,
4444 FIB_SOURCE_API);
4445 fib_table_entry_delete(fib_index,
4446 &pfx_2001_a_s_64,
4447 FIB_SOURCE_API);
4448 fib_table_entry_delete(fib_index,
4449 &pfx_2001_b_s_64,
4450 FIB_SOURCE_API);
4451 fib_table_entry_delete(fib_index,
4452 &pfx_2001_1_3_s_128,
4453 FIB_SOURCE_ADJ);
4454 fib_table_entry_delete(fib_index,
4455 &pfx_2001_1_2_s_128,
4456 FIB_SOURCE_ADJ);
4457 local_pfx.fp_len = 64;
4458 fib_table_entry_delete(fib_index, &local_pfx,
4459 FIB_SOURCE_INTERFACE);
4460 local_pfx.fp_len = 128;
4461 fib_table_entry_special_remove(fib_index, &local_pfx,
4462 FIB_SOURCE_INTERFACE);
4463 connected_pfx.fp_len = 64;
4464 fib_table_entry_delete(fib_index, &connected_pfx,
4465 FIB_SOURCE_INTERFACE);
4466 connected_pfx.fp_len = 128;
4467 fib_table_entry_special_remove(fib_index, &connected_pfx,
4468 FIB_SOURCE_INTERFACE);
4469
4470 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4471 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4472 "2001::a/64 removed");
4473 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4474 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4475 "2001::b/64 removed");
4476 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4477 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4478 "2001:0:0:1::3/128 removed");
4479 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4480 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4481 "2001:0:0:1::3/128 removed");
4482 local_pfx.fp_len = 64;
4483 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4484 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4485 "2001:0:0:1/64 removed");
4486 local_pfx.fp_len = 128;
4487 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4488 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4489 "2001:0:0:1::1/128 removed");
4490 connected_pfx.fp_len = 64;
4491 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4492 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4493 "2001:0:0:2/64 removed");
4494 connected_pfx.fp_len = 128;
4495 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4496 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4497 "2001:0:0:2::1/128 removed");
4498
4499 /*
4500 * -8 entries. -7 path-lists (1 was shared).
4501 */
4502 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4503 fib_path_list_db_size());
4504 FIB_TEST((NPS == fib_path_list_pool_size()), "path list pool size is%d",
4505 fib_path_list_pool_size());
4506 FIB_TEST((NPS == fib_entry_pool_size()), "entry pool size is %d",
4507 fib_entry_pool_size());
4508
4509 /*
4510 * now remove the VRF
4511 */
4512 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4513
4514 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4515 fib_path_list_db_size());
4516 FIB_TEST((NPS-6 == fib_path_list_pool_size()), "path list pool size is%d",
4517 fib_path_list_pool_size());
4518 FIB_TEST((NPS-6 == fib_entry_pool_size()), "entry pool size is %d",
4519 fib_entry_pool_size());
4520
4521 adj_unlock(ai_02);
4522 adj_unlock(ai_01);
4523
4524 /*
4525 * return the interfaces to up state
4526 */
4527 error = vnet_sw_interface_set_flags(vnet_get_main(),
4528 tm->hw[0]->sw_if_index,
4529 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4530 error = vnet_sw_interface_set_flags(vnet_get_main(),
4531 tm->hw[1]->sw_if_index,
4532 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4533
4534 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4535 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004536
4537 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004538}
4539
4540/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004541 * Test Attached Exports
4542 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004543static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004544fib_test_ae (void)
4545{
4546 const dpo_id_t *dpo, *dpo_drop;
4547 const u32 fib_index = 0;
4548 fib_node_index_t fei;
4549 test_main_t *tm;
4550 ip4_main_t *im;
4551
4552 tm = &test_main;
4553 im = &ip4_main;
4554
4555 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4556 adj_nbr_db_size());
4557
4558 /*
4559 * add interface routes. We'll assume this works. It's more rigorously
4560 * tested elsewhere.
4561 */
4562 fib_prefix_t local_pfx = {
4563 .fp_len = 24,
4564 .fp_proto = FIB_PROTOCOL_IP4,
4565 .fp_addr = {
4566 .ip4 = {
4567 /* 10.10.10.10 */
4568 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4569 },
4570 },
4571 };
4572
4573 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4574 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4575
4576 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4577
4578 fib_table_entry_update_one_path(fib_index, &local_pfx,
4579 FIB_SOURCE_INTERFACE,
4580 (FIB_ENTRY_FLAG_CONNECTED |
4581 FIB_ENTRY_FLAG_ATTACHED),
4582 FIB_PROTOCOL_IP4,
4583 NULL,
4584 tm->hw[0]->sw_if_index,
4585 ~0,
4586 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004587 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004588 FIB_ROUTE_PATH_FLAG_NONE);
4589 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4590 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4591 "attached interface route present");
4592
4593 local_pfx.fp_len = 32;
4594 fib_table_entry_update_one_path(fib_index, &local_pfx,
4595 FIB_SOURCE_INTERFACE,
4596 (FIB_ENTRY_FLAG_CONNECTED |
4597 FIB_ENTRY_FLAG_LOCAL),
4598 FIB_PROTOCOL_IP4,
4599 NULL,
4600 tm->hw[0]->sw_if_index,
4601 ~0, // invalid fib index
4602 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004603 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004604 FIB_ROUTE_PATH_FLAG_NONE);
4605 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4606
4607 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4608 "local interface route present");
4609
4610 /*
4611 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4612 */
4613 fib_prefix_t pfx_10_10_10_1_s_32 = {
4614 .fp_len = 32,
4615 .fp_proto = FIB_PROTOCOL_IP4,
4616 .fp_addr = {
4617 /* 10.10.10.1 */
4618 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4619 },
4620 };
4621 fib_node_index_t ai;
4622
4623 fib_table_entry_update_one_path(fib_index,
4624 &pfx_10_10_10_1_s_32,
4625 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004626 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004627 FIB_PROTOCOL_IP4,
4628 &pfx_10_10_10_1_s_32.fp_addr,
4629 tm->hw[0]->sw_if_index,
4630 ~0, // invalid fib index
4631 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004632 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004633 FIB_ROUTE_PATH_FLAG_NONE);
4634
4635 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4636 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4637 ai = fib_entry_get_adj(fei);
4638
4639 /*
4640 * create another FIB table into which routes will be imported
4641 */
4642 u32 import_fib_index1;
4643
4644 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4645
4646 /*
4647 * Add an attached route in the import FIB
4648 */
4649 local_pfx.fp_len = 24;
4650 fib_table_entry_update_one_path(import_fib_index1,
4651 &local_pfx,
4652 FIB_SOURCE_API,
4653 FIB_ENTRY_FLAG_NONE,
4654 FIB_PROTOCOL_IP4,
4655 NULL,
4656 tm->hw[0]->sw_if_index,
4657 ~0, // invalid fib index
4658 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004659 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004660 FIB_ROUTE_PATH_FLAG_NONE);
4661 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4662 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4663
4664 /*
4665 * check for the presence of the adj-fibs in the import table
4666 */
4667 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4668 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4669 FIB_TEST((ai == fib_entry_get_adj(fei)),
4670 "adj-fib1 Import uses same adj as export");
4671
4672 /*
4673 * check for the presence of the local in the import table
4674 */
4675 local_pfx.fp_len = 32;
4676 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4677 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4678
4679 /*
4680 * Add another adj-fin in the export table. Expect this
4681 * to get magically exported;
4682 */
4683 fib_prefix_t pfx_10_10_10_2_s_32 = {
4684 .fp_len = 32,
4685 .fp_proto = FIB_PROTOCOL_IP4,
4686 .fp_addr = {
4687 /* 10.10.10.2 */
4688 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
4689 },
4690 };
4691
4692 fib_table_entry_update_one_path(fib_index,
4693 &pfx_10_10_10_2_s_32,
4694 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004695 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004696 FIB_PROTOCOL_IP4,
4697 &pfx_10_10_10_2_s_32.fp_addr,
4698 tm->hw[0]->sw_if_index,
4699 ~0, // invalid fib index
4700 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004701 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004702 FIB_ROUTE_PATH_FLAG_NONE);
4703 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
4704 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
4705 ai = fib_entry_get_adj(fei);
4706
4707 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4708 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4709 FIB_TEST((ai == fib_entry_get_adj(fei)),
4710 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00004711 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
4712 "ADJ-fib2 imported flags %d",
4713 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004714
4715 /*
4716 * create a 2nd FIB table into which routes will be imported
4717 */
4718 u32 import_fib_index2;
4719
4720 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
4721
4722 /*
4723 * Add an attached route in the import FIB
4724 */
4725 local_pfx.fp_len = 24;
4726 fib_table_entry_update_one_path(import_fib_index2,
4727 &local_pfx,
4728 FIB_SOURCE_API,
4729 FIB_ENTRY_FLAG_NONE,
4730 FIB_PROTOCOL_IP4,
4731 NULL,
4732 tm->hw[0]->sw_if_index,
4733 ~0, // invalid fib index
4734 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004735 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004736 FIB_ROUTE_PATH_FLAG_NONE);
4737 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4738 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4739
4740 /*
4741 * check for the presence of all the adj-fibs and local in the import table
4742 */
4743 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4744 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4745 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4746 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4747 local_pfx.fp_len = 32;
4748 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4749 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4750
4751 /*
4752 * add a 3rd adj-fib. expect it to be exported to both tables.
4753 */
4754 fib_prefix_t pfx_10_10_10_3_s_32 = {
4755 .fp_len = 32,
4756 .fp_proto = FIB_PROTOCOL_IP4,
4757 .fp_addr = {
4758 /* 10.10.10.3 */
4759 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4760 },
4761 };
4762
4763 fib_table_entry_update_one_path(fib_index,
4764 &pfx_10_10_10_3_s_32,
4765 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004766 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004767 FIB_PROTOCOL_IP4,
4768 &pfx_10_10_10_3_s_32.fp_addr,
4769 tm->hw[0]->sw_if_index,
4770 ~0, // invalid fib index
4771 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004772 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004773 FIB_ROUTE_PATH_FLAG_NONE);
4774 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4775 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
4776 ai = fib_entry_get_adj(fei);
4777
4778 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4779 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
4780 FIB_TEST((ai == fib_entry_get_adj(fei)),
4781 "Import uses same adj as export");
4782 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4783 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
4784 FIB_TEST((ai == fib_entry_get_adj(fei)),
4785 "Import uses same adj as export");
4786
4787 /*
4788 * remove the 3rd adj fib. we expect it to be removed from both FIBs
4789 */
4790 fib_table_entry_delete(fib_index,
4791 &pfx_10_10_10_3_s_32,
4792 FIB_SOURCE_ADJ);
4793
4794 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4795 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
4796
4797 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4798 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
4799
4800 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4801 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
4802
4803 /*
4804 * remove the attached route from the 2nd FIB. expect the imported
4805 * entires to be removed
4806 */
4807 local_pfx.fp_len = 24;
4808 fib_table_entry_delete(import_fib_index2,
4809 &local_pfx,
4810 FIB_SOURCE_API);
4811 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4812 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
4813
4814 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4815 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
4816 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4817 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
4818 local_pfx.fp_len = 32;
4819 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4820 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
4821
4822 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4823 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
4824 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4825 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
4826 local_pfx.fp_len = 32;
4827 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4828 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
4829
4830 /*
4831 * modify the route in FIB1 so it is no longer attached. expect the imported
4832 * entires to be removed
4833 */
4834 local_pfx.fp_len = 24;
4835 fib_table_entry_update_one_path(import_fib_index1,
4836 &local_pfx,
4837 FIB_SOURCE_API,
4838 FIB_ENTRY_FLAG_NONE,
4839 FIB_PROTOCOL_IP4,
4840 &pfx_10_10_10_2_s_32.fp_addr,
4841 tm->hw[0]->sw_if_index,
4842 ~0, // invalid fib index
4843 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004844 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004845 FIB_ROUTE_PATH_FLAG_NONE);
4846 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4847 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
4848 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4849 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4850 local_pfx.fp_len = 32;
4851 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4852 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4853
4854 /*
4855 * modify it back to attached. expect the adj-fibs back
4856 */
4857 local_pfx.fp_len = 24;
4858 fib_table_entry_update_one_path(import_fib_index1,
4859 &local_pfx,
4860 FIB_SOURCE_API,
4861 FIB_ENTRY_FLAG_NONE,
4862 FIB_PROTOCOL_IP4,
4863 NULL,
4864 tm->hw[0]->sw_if_index,
4865 ~0, // invalid fib index
4866 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004867 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004868 FIB_ROUTE_PATH_FLAG_NONE);
4869 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4870 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
4871 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4872 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
4873 local_pfx.fp_len = 32;
4874 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4875 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
4876
4877 /*
4878 * add a covering attached next-hop for the interface address, so we have
4879 * a valid adj to find when we check the forwarding tables
4880 */
4881 fib_prefix_t pfx_10_0_0_0_s_8 = {
4882 .fp_len = 8,
4883 .fp_proto = FIB_PROTOCOL_IP4,
4884 .fp_addr = {
4885 /* 10.0.0.0 */
4886 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
4887 },
4888 };
4889
4890 fei = fib_table_entry_update_one_path(fib_index,
4891 &pfx_10_0_0_0_s_8,
4892 FIB_SOURCE_API,
4893 FIB_ENTRY_FLAG_NONE,
4894 FIB_PROTOCOL_IP4,
4895 &pfx_10_10_10_3_s_32.fp_addr,
4896 tm->hw[0]->sw_if_index,
4897 ~0, // invalid fib index
4898 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004899 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004900 FIB_ROUTE_PATH_FLAG_NONE);
4901 dpo = fib_entry_contribute_ip_forwarding(fei);
4902
4903 /*
4904 * remove the route in the export fib. expect the adj-fibs to be removed
4905 */
4906 local_pfx.fp_len = 24;
4907 fib_table_entry_delete(fib_index,
4908 &local_pfx,
4909 FIB_SOURCE_INTERFACE);
4910
4911 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4912 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
4913 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4914 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4915 local_pfx.fp_len = 32;
4916 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4917 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4918
4919 /*
4920 * the adj-fibs in the export VRF are present in the FIB table,
4921 * but not installed in forwarding, since they have no attached cover.
4922 * Consequently a lookup in the MTRIE gives the adj for the covering
4923 * route 10.0.0.0/8.
4924 */
4925 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4926 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
4927
4928 index_t lbi;
4929 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
4930 FIB_TEST(lbi == dpo->dpoi_index,
4931 "10.10.10.1 forwards on \n%U not \n%U",
4932 format_load_balance, lbi, 0,
4933 format_dpo_id, dpo, 0);
4934 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
4935 FIB_TEST(lbi == dpo->dpoi_index,
4936 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
4937 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
4938 FIB_TEST(lbi == dpo->dpoi_index,
4939 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
4940
4941 /*
4942 * add the export prefix back, but not as attached.
4943 * No adj-fibs in export nor import tables
4944 */
4945 local_pfx.fp_len = 24;
4946 fei = fib_table_entry_update_one_path(fib_index,
4947 &local_pfx,
4948 FIB_SOURCE_API,
4949 FIB_ENTRY_FLAG_NONE,
4950 FIB_PROTOCOL_IP4,
4951 &pfx_10_10_10_1_s_32.fp_addr,
4952 tm->hw[0]->sw_if_index,
4953 ~0, // invalid fib index
4954 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004955 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004956 FIB_ROUTE_PATH_FLAG_NONE);
4957 dpo = fib_entry_contribute_ip_forwarding(fei);
4958
4959 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4960 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
4961 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
4962 FIB_TEST(lbi == dpo->dpoi_index,
4963 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
4964 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4965 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
4966 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
4967 FIB_TEST(lbi == dpo->dpoi_index,
4968 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
4969
4970 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4971 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
4972 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4973 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4974 local_pfx.fp_len = 32;
4975 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4976 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4977
4978 /*
4979 * modify the export prefix so it is attached. expect all covereds to return
4980 */
4981 local_pfx.fp_len = 24;
4982 fib_table_entry_update_one_path(fib_index,
4983 &local_pfx,
4984 FIB_SOURCE_API,
4985 FIB_ENTRY_FLAG_NONE,
4986 FIB_PROTOCOL_IP4,
4987 NULL,
4988 tm->hw[0]->sw_if_index,
4989 ~0, // invalid fib index
4990 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004991 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004992 FIB_ROUTE_PATH_FLAG_NONE);
4993
4994 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4995 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
4996 dpo = fib_entry_contribute_ip_forwarding(fei);
4997 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4998 "Adj-fib1 is not drop in export");
4999 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5000 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5001 local_pfx.fp_len = 32;
5002 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5003 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5004 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5005 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5006 dpo = fib_entry_contribute_ip_forwarding(fei);
5007 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5008 "Adj-fib1 is not drop in export");
5009 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5010 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5011 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5012 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5013 local_pfx.fp_len = 32;
5014 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5015 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5016
5017 /*
5018 * modify the export prefix so connected. no change.
5019 */
5020 local_pfx.fp_len = 24;
5021 fib_table_entry_update_one_path(fib_index, &local_pfx,
5022 FIB_SOURCE_INTERFACE,
5023 (FIB_ENTRY_FLAG_CONNECTED |
5024 FIB_ENTRY_FLAG_ATTACHED),
5025 FIB_PROTOCOL_IP4,
5026 NULL,
5027 tm->hw[0]->sw_if_index,
5028 ~0,
5029 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005030 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005031 FIB_ROUTE_PATH_FLAG_NONE);
5032
5033 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5034 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5035 dpo = fib_entry_contribute_ip_forwarding(fei);
5036 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5037 "Adj-fib1 is not drop in export");
5038 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5039 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5040 local_pfx.fp_len = 32;
5041 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5042 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5043 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5044 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5045 dpo = fib_entry_contribute_ip_forwarding(fei);
5046 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5047 "Adj-fib1 is not drop in export");
5048 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5049 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5050 local_pfx.fp_len = 32;
5051 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5052 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5053
5054 /*
5055 * CLEANUP
5056 */
5057 fib_table_entry_delete(fib_index,
5058 &pfx_10_0_0_0_s_8,
5059 FIB_SOURCE_API);
5060 fib_table_entry_delete(fib_index,
5061 &pfx_10_10_10_1_s_32,
5062 FIB_SOURCE_ADJ);
5063 fib_table_entry_delete(fib_index,
5064 &pfx_10_10_10_2_s_32,
5065 FIB_SOURCE_ADJ);
5066 local_pfx.fp_len = 32;
5067 fib_table_entry_delete(fib_index,
5068 &local_pfx,
5069 FIB_SOURCE_INTERFACE);
5070 local_pfx.fp_len = 24;
5071 fib_table_entry_delete(fib_index,
5072 &local_pfx,
5073 FIB_SOURCE_API);
5074 fib_table_entry_delete(fib_index,
5075 &local_pfx,
5076 FIB_SOURCE_INTERFACE);
5077 local_pfx.fp_len = 24;
5078 fib_table_entry_delete(import_fib_index1,
5079 &local_pfx,
5080 FIB_SOURCE_API);
5081
5082 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5083 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5084
5085 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5086 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005087
5088 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005089}
5090
Neale Rannsad422ed2016-11-02 14:20:04 +00005091
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005092/*
5093 * Test the recursive route route handling for GRE tunnels
5094 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005095static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005096fib_test_label (void)
5097{
5098 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;
5099 const u32 fib_index = 0;
5100 test_main_t *tm;
5101 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005102 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005103
5104 lb_count = pool_elts(load_balance_pool);
5105 tm = &test_main;
5106 im = &ip4_main;
5107
5108 /*
5109 * add interface routes. We'll assume this works. It's more rigorously
5110 * tested elsewhere.
5111 */
5112 fib_prefix_t local0_pfx = {
5113 .fp_len = 24,
5114 .fp_proto = FIB_PROTOCOL_IP4,
5115 .fp_addr = {
5116 .ip4 = {
5117 /* 10.10.10.10 */
5118 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5119 },
5120 },
5121 };
5122
5123 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5124 adj_nbr_db_size());
5125
5126 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5127 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5128
5129 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5130 FIB_SOURCE_INTERFACE,
5131 (FIB_ENTRY_FLAG_CONNECTED |
5132 FIB_ENTRY_FLAG_ATTACHED),
5133 FIB_PROTOCOL_IP4,
5134 NULL,
5135 tm->hw[0]->sw_if_index,
5136 ~0,
5137 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005138 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005139 FIB_ROUTE_PATH_FLAG_NONE);
5140 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5141 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5142 "attached interface route present");
5143
5144 local0_pfx.fp_len = 32;
5145 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5146 FIB_SOURCE_INTERFACE,
5147 (FIB_ENTRY_FLAG_CONNECTED |
5148 FIB_ENTRY_FLAG_LOCAL),
5149 FIB_PROTOCOL_IP4,
5150 NULL,
5151 tm->hw[0]->sw_if_index,
5152 ~0, // invalid fib index
5153 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005154 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005155 FIB_ROUTE_PATH_FLAG_NONE);
5156 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5157
5158 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5159 "local interface route present");
5160
5161 fib_prefix_t local1_pfx = {
5162 .fp_len = 24,
5163 .fp_proto = FIB_PROTOCOL_IP4,
5164 .fp_addr = {
5165 .ip4 = {
5166 /* 10.10.11.10 */
5167 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5168 },
5169 },
5170 };
5171
5172 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5173 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5174
5175 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5176 FIB_SOURCE_INTERFACE,
5177 (FIB_ENTRY_FLAG_CONNECTED |
5178 FIB_ENTRY_FLAG_ATTACHED),
5179 FIB_PROTOCOL_IP4,
5180 NULL,
5181 tm->hw[1]->sw_if_index,
5182 ~0,
5183 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005184 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005185 FIB_ROUTE_PATH_FLAG_NONE);
5186 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5187 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5188 "attached interface route present");
5189
5190 local1_pfx.fp_len = 32;
5191 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5192 FIB_SOURCE_INTERFACE,
5193 (FIB_ENTRY_FLAG_CONNECTED |
5194 FIB_ENTRY_FLAG_LOCAL),
5195 FIB_PROTOCOL_IP4,
5196 NULL,
5197 tm->hw[1]->sw_if_index,
5198 ~0, // invalid fib index
5199 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005200 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005201 FIB_ROUTE_PATH_FLAG_NONE);
5202 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5203
5204 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5205 "local interface route present");
5206
5207 ip46_address_t nh_10_10_10_1 = {
5208 .ip4 = {
5209 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5210 },
5211 };
5212 ip46_address_t nh_10_10_11_1 = {
5213 .ip4 = {
5214 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5215 },
5216 };
5217 ip46_address_t nh_10_10_11_2 = {
5218 .ip4 = {
5219 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5220 },
5221 };
5222
5223 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005224 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005225 &nh_10_10_11_1,
5226 tm->hw[1]->sw_if_index);
5227 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005228 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005229 &nh_10_10_11_2,
5230 tm->hw[1]->sw_if_index);
5231 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005232 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005233 &nh_10_10_10_1,
5234 tm->hw[0]->sw_if_index);
5235 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005236 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005237 &nh_10_10_11_2,
5238 tm->hw[1]->sw_if_index);
5239 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005240 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005241 &nh_10_10_11_1,
5242 tm->hw[1]->sw_if_index);
5243
5244 /*
5245 * Add an etry with one path with a real out-going label
5246 */
5247 fib_prefix_t pfx_1_1_1_1_s_32 = {
5248 .fp_len = 32,
5249 .fp_proto = FIB_PROTOCOL_IP4,
5250 .fp_addr = {
5251 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5252 },
5253 };
5254 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5255 .type = FT_LB_LABEL_O_ADJ,
5256 .label_o_adj = {
5257 .adj = ai_mpls_10_10_10_1,
5258 .label = 99,
5259 .eos = MPLS_EOS,
5260 },
5261 };
5262 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5263 .type = FT_LB_LABEL_O_ADJ,
5264 .label_o_adj = {
5265 .adj = ai_mpls_10_10_10_1,
5266 .label = 99,
5267 .eos = MPLS_NON_EOS,
5268 },
5269 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005270 mpls_label_t *l99 = NULL;
5271 vec_add1(l99, 99);
5272
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005273 fib_table_entry_update_one_path(fib_index,
5274 &pfx_1_1_1_1_s_32,
5275 FIB_SOURCE_API,
5276 FIB_ENTRY_FLAG_NONE,
5277 FIB_PROTOCOL_IP4,
5278 &nh_10_10_10_1,
5279 tm->hw[0]->sw_if_index,
5280 ~0, // invalid fib index
5281 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005282 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005283 FIB_ROUTE_PATH_FLAG_NONE);
5284
5285 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5286 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5287
5288 FIB_TEST(fib_test_validate_entry(fei,
5289 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5290 1,
5291 &l99_eos_o_10_10_10_1),
5292 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5293
5294 /*
5295 * add a path with an implicit NULL label
5296 */
5297 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5298 .type = FT_LB_ADJ,
5299 .adj = {
5300 .adj = ai_v4_10_10_11_1,
5301 },
5302 };
5303 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5304 .type = FT_LB_ADJ,
5305 .adj = {
5306 .adj = ai_mpls_10_10_11_1,
5307 },
5308 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005309 mpls_label_t *l_imp_null = NULL;
5310 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005311
5312 fei = fib_table_entry_path_add(fib_index,
5313 &pfx_1_1_1_1_s_32,
5314 FIB_SOURCE_API,
5315 FIB_ENTRY_FLAG_NONE,
5316 FIB_PROTOCOL_IP4,
5317 &nh_10_10_11_1,
5318 tm->hw[1]->sw_if_index,
5319 ~0, // invalid fib index
5320 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005321 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005322 FIB_ROUTE_PATH_FLAG_NONE);
5323
5324 FIB_TEST(fib_test_validate_entry(fei,
5325 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5326 2,
5327 &l99_eos_o_10_10_10_1,
5328 &a_o_10_10_11_1),
5329 "1.1.1.1/32 LB 2 buckets via: "
5330 "label 99 over 10.10.10.1, "
5331 "adj over 10.10.11.1");
5332
5333 /*
5334 * assign the route a local label
5335 */
5336 fib_table_entry_local_label_add(fib_index,
5337 &pfx_1_1_1_1_s_32,
5338 24001);
5339
5340 fib_prefix_t pfx_24001_eos = {
5341 .fp_proto = FIB_PROTOCOL_MPLS,
5342 .fp_label = 24001,
5343 .fp_eos = MPLS_EOS,
5344 };
5345 fib_prefix_t pfx_24001_neos = {
5346 .fp_proto = FIB_PROTOCOL_MPLS,
5347 .fp_label = 24001,
5348 .fp_eos = MPLS_NON_EOS,
5349 };
5350
5351 /*
5352 * The EOS entry should link to both the paths,
5353 * and use an ip adj for the imp-null
5354 * The NON-EOS entry should link to both the paths,
5355 * and use an mpls adj for the imp-null
5356 */
5357 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5358 &pfx_24001_eos);
5359 FIB_TEST(fib_test_validate_entry(fei,
5360 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5361 2,
5362 &l99_eos_o_10_10_10_1,
5363 &a_o_10_10_11_1),
5364 "24001/eos LB 2 buckets via: "
5365 "label 99 over 10.10.10.1, "
5366 "adj over 10.10.11.1");
5367
5368
5369 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5370 &pfx_24001_neos);
5371 FIB_TEST(fib_test_validate_entry(fei,
5372 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5373 2,
5374 &l99_neos_o_10_10_10_1,
5375 &a_mpls_o_10_10_11_1),
5376 "24001/neos LB 1 bucket via: "
5377 "label 99 over 10.10.10.1 ",
5378 "mpls-adj via 10.10.11.1");
5379
5380 /*
5381 * add an unlabelled path, this is excluded from the neos chains,
5382 */
5383 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5384 .type = FT_LB_ADJ,
5385 .adj = {
5386 .adj = ai_v4_10_10_11_2,
5387 },
5388 };
5389
5390 fei = fib_table_entry_path_add(fib_index,
5391 &pfx_1_1_1_1_s_32,
5392 FIB_SOURCE_API,
5393 FIB_ENTRY_FLAG_NONE,
5394 FIB_PROTOCOL_IP4,
5395 &nh_10_10_11_2,
5396 tm->hw[1]->sw_if_index,
5397 ~0, // invalid fib index
5398 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005399 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005400 FIB_ROUTE_PATH_FLAG_NONE);
5401
5402 FIB_TEST(fib_test_validate_entry(fei,
5403 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5404 16, // 3 choices spread over 16 buckets
5405 &l99_eos_o_10_10_10_1,
5406 &l99_eos_o_10_10_10_1,
5407 &l99_eos_o_10_10_10_1,
5408 &l99_eos_o_10_10_10_1,
5409 &l99_eos_o_10_10_10_1,
5410 &l99_eos_o_10_10_10_1,
5411 &a_o_10_10_11_1,
5412 &a_o_10_10_11_1,
5413 &a_o_10_10_11_1,
5414 &a_o_10_10_11_1,
5415 &a_o_10_10_11_1,
5416 &adj_o_10_10_11_2,
5417 &adj_o_10_10_11_2,
5418 &adj_o_10_10_11_2,
5419 &adj_o_10_10_11_2,
5420 &adj_o_10_10_11_2),
5421 "1.1.1.1/32 LB 16 buckets via: "
5422 "label 99 over 10.10.10.1, "
5423 "adj over 10.10.11.1",
5424 "adj over 10.10.11.2");
5425
5426 /*
5427 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5428 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005429 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005430 fib_entry_contribute_forwarding(fei,
5431 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5432 &non_eos_1_1_1_1);
5433
5434 /*
5435 * n-eos has only the 2 labelled paths
5436 */
5437 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5438 &pfx_24001_neos);
5439
5440 FIB_TEST(fib_test_validate_entry(fei,
5441 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5442 2,
5443 &l99_neos_o_10_10_10_1,
5444 &a_mpls_o_10_10_11_1),
5445 "24001/neos LB 2 buckets via: "
5446 "label 99 over 10.10.10.1, "
5447 "adj-mpls over 10.10.11.2");
5448
5449 /*
5450 * A labelled recursive
5451 */
5452 fib_prefix_t pfx_2_2_2_2_s_32 = {
5453 .fp_len = 32,
5454 .fp_proto = FIB_PROTOCOL_IP4,
5455 .fp_addr = {
5456 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5457 },
5458 };
5459 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5460 .type = FT_LB_LABEL_O_LB,
5461 .label_o_lb = {
5462 .lb = non_eos_1_1_1_1.dpoi_index,
5463 .label = 1600,
5464 .eos = MPLS_EOS,
5465 },
5466 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005467 mpls_label_t *l1600 = NULL;
5468 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005469
5470 fib_table_entry_update_one_path(fib_index,
5471 &pfx_2_2_2_2_s_32,
5472 FIB_SOURCE_API,
5473 FIB_ENTRY_FLAG_NONE,
5474 FIB_PROTOCOL_IP4,
5475 &pfx_1_1_1_1_s_32.fp_addr,
5476 ~0,
5477 fib_index,
5478 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005479 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005480 FIB_ROUTE_PATH_FLAG_NONE);
5481
5482 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5483 FIB_TEST(fib_test_validate_entry(fei,
5484 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5485 1,
5486 &l1600_eos_o_1_1_1_1),
5487 "2.2.2.2.2/32 LB 1 buckets via: "
5488 "label 1600 over 1.1.1.1");
5489
Neale Ranns948e00f2016-10-20 13:39:34 +01005490 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005491 index_t urpfi;
5492
5493 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5494 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5495
5496 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5497 "uRPF check for 2.2.2.2/32 on %d OK",
5498 tm->hw[0]->sw_if_index);
5499 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5500 "uRPF check for 2.2.2.2/32 on %d OK",
5501 tm->hw[1]->sw_if_index);
5502 FIB_TEST(!fib_urpf_check(urpfi, 99),
5503 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5504 99);
5505
5506 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5507 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5508 "Shared uRPF on IP and non-EOS chain");
5509
5510 dpo_reset(&dpo_44);
5511
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005512 /*
5513 * we are holding a lock on the non-eos LB of the via-entry.
5514 * do a PIC-core failover by shutting the link of the via-entry.
5515 *
5516 * shut down the link with the valid label
5517 */
5518 vnet_sw_interface_set_flags(vnet_get_main(),
5519 tm->hw[0]->sw_if_index,
5520 0);
5521
5522 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5523 FIB_TEST(fib_test_validate_entry(fei,
5524 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5525 2,
5526 &a_o_10_10_11_1,
5527 &adj_o_10_10_11_2),
5528 "1.1.1.1/32 LB 2 buckets via: "
5529 "adj over 10.10.11.1, ",
5530 "adj-v4 over 10.10.11.2");
5531
5532 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5533 &pfx_24001_eos);
5534 FIB_TEST(fib_test_validate_entry(fei,
5535 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5536 2,
5537 &a_o_10_10_11_1,
5538 &adj_o_10_10_11_2),
5539 "24001/eos LB 2 buckets via: "
5540 "adj over 10.10.11.1, ",
5541 "adj-v4 over 10.10.11.2");
5542
5543 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5544 &pfx_24001_neos);
5545 FIB_TEST(fib_test_validate_entry(fei,
5546 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5547 1,
5548 &a_mpls_o_10_10_11_1),
5549 "24001/neos LB 1 buckets via: "
5550 "adj-mpls over 10.10.11.2");
5551
5552 /*
5553 * test that the pre-failover load-balance has been in-place
5554 * modified
5555 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005556 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005557 fib_entry_contribute_forwarding(fei,
5558 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5559 &current);
5560
5561 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5562 &current),
5563 "PIC-core LB inplace modified %U %U",
5564 format_dpo_id, &non_eos_1_1_1_1, 0,
5565 format_dpo_id, &current, 0);
5566
5567 dpo_reset(&non_eos_1_1_1_1);
5568 dpo_reset(&current);
5569
5570 /*
5571 * no-shut the link with the valid label
5572 */
5573 vnet_sw_interface_set_flags(vnet_get_main(),
5574 tm->hw[0]->sw_if_index,
5575 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5576
5577 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5578 FIB_TEST(fib_test_validate_entry(fei,
5579 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5580 16, // 3 choices spread over 16 buckets
5581 &l99_eos_o_10_10_10_1,
5582 &l99_eos_o_10_10_10_1,
5583 &l99_eos_o_10_10_10_1,
5584 &l99_eos_o_10_10_10_1,
5585 &l99_eos_o_10_10_10_1,
5586 &l99_eos_o_10_10_10_1,
5587 &a_o_10_10_11_1,
5588 &a_o_10_10_11_1,
5589 &a_o_10_10_11_1,
5590 &a_o_10_10_11_1,
5591 &a_o_10_10_11_1,
5592 &adj_o_10_10_11_2,
5593 &adj_o_10_10_11_2,
5594 &adj_o_10_10_11_2,
5595 &adj_o_10_10_11_2,
5596 &adj_o_10_10_11_2),
5597 "1.1.1.1/32 LB 16 buckets via: "
5598 "label 99 over 10.10.10.1, "
5599 "adj over 10.10.11.1",
5600 "adj-v4 over 10.10.11.2");
5601
5602
5603 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5604 &pfx_24001_eos);
5605 FIB_TEST(fib_test_validate_entry(fei,
5606 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5607 16, // 3 choices spread over 16 buckets
5608 &l99_eos_o_10_10_10_1,
5609 &l99_eos_o_10_10_10_1,
5610 &l99_eos_o_10_10_10_1,
5611 &l99_eos_o_10_10_10_1,
5612 &l99_eos_o_10_10_10_1,
5613 &l99_eos_o_10_10_10_1,
5614 &a_o_10_10_11_1,
5615 &a_o_10_10_11_1,
5616 &a_o_10_10_11_1,
5617 &a_o_10_10_11_1,
5618 &a_o_10_10_11_1,
5619 &adj_o_10_10_11_2,
5620 &adj_o_10_10_11_2,
5621 &adj_o_10_10_11_2,
5622 &adj_o_10_10_11_2,
5623 &adj_o_10_10_11_2),
5624 "24001/eos LB 16 buckets via: "
5625 "label 99 over 10.10.10.1, "
5626 "adj over 10.10.11.1",
5627 "adj-v4 over 10.10.11.2");
5628
5629 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5630 &pfx_24001_neos);
5631 FIB_TEST(fib_test_validate_entry(fei,
5632 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5633 2,
5634 &l99_neos_o_10_10_10_1,
5635 &a_mpls_o_10_10_11_1),
5636 "24001/neos LB 2 buckets via: "
5637 "label 99 over 10.10.10.1, "
5638 "adj-mpls over 10.10.11.2");
5639
5640 /*
5641 * remove the first path with the valid label
5642 */
5643 fib_table_entry_path_remove(fib_index,
5644 &pfx_1_1_1_1_s_32,
5645 FIB_SOURCE_API,
5646 FIB_PROTOCOL_IP4,
5647 &nh_10_10_10_1,
5648 tm->hw[0]->sw_if_index,
5649 ~0, // invalid fib index
5650 1,
5651 FIB_ROUTE_PATH_FLAG_NONE);
5652
5653 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5654 FIB_TEST(fib_test_validate_entry(fei,
5655 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5656 2,
5657 &a_o_10_10_11_1,
5658 &adj_o_10_10_11_2),
5659 "1.1.1.1/32 LB 2 buckets via: "
5660 "adj over 10.10.11.1",
5661 "adj-v4 over 10.10.11.2");
5662
5663 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5664 &pfx_24001_eos);
5665 FIB_TEST(fib_test_validate_entry(fei,
5666 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5667 2,
5668 &a_o_10_10_11_1,
5669 &adj_o_10_10_11_2),
5670 "24001/eos LB 2 buckets via: "
5671 "adj over 10.10.11.1",
5672 "adj-v4 over 10.10.11.2");
5673
5674 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5675 &pfx_24001_neos);
5676
5677 FIB_TEST(fib_test_validate_entry(fei,
5678 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5679 1,
5680 &a_mpls_o_10_10_11_1),
5681 "24001/neos LB 1 buckets via: "
5682 "adj-mpls over 10.10.11.2");
5683
5684 /*
5685 * remove the other path with a valid label
5686 */
5687 fib_test_lb_bucket_t bucket_drop = {
5688 .type = FT_LB_SPECIAL,
5689 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005690 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005691 },
5692 };
5693
5694 fib_table_entry_path_remove(fib_index,
5695 &pfx_1_1_1_1_s_32,
5696 FIB_SOURCE_API,
5697 FIB_PROTOCOL_IP4,
5698 &nh_10_10_11_1,
5699 tm->hw[1]->sw_if_index,
5700 ~0, // invalid fib index
5701 1,
5702 FIB_ROUTE_PATH_FLAG_NONE);
5703
5704 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5705 FIB_TEST(fib_test_validate_entry(fei,
5706 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5707 1,
5708 &adj_o_10_10_11_2),
5709 "1.1.1.1/32 LB 1 buckets via: "
5710 "adj over 10.10.11.2");
5711
5712 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5713 &pfx_24001_eos);
5714 FIB_TEST(fib_test_validate_entry(fei,
5715 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5716 1,
5717 &adj_o_10_10_11_2),
5718 "24001/eos LB 1 buckets via: "
5719 "adj over 10.10.11.2");
5720
5721 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5722 &pfx_24001_neos);
5723 FIB_TEST(fib_test_validate_entry(fei,
5724 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5725 1,
5726 &bucket_drop),
5727 "24001/eos LB 1 buckets via: DROP");
5728
5729 /*
5730 * add back the path with the valid label
5731 */
Neale Rannsad422ed2016-11-02 14:20:04 +00005732 l99 = NULL;
5733 vec_add1(l99, 99);
5734
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005735 fib_table_entry_path_add(fib_index,
5736 &pfx_1_1_1_1_s_32,
5737 FIB_SOURCE_API,
5738 FIB_ENTRY_FLAG_NONE,
5739 FIB_PROTOCOL_IP4,
5740 &nh_10_10_10_1,
5741 tm->hw[0]->sw_if_index,
5742 ~0, // invalid fib index
5743 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005744 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005745 FIB_ROUTE_PATH_FLAG_NONE);
5746
5747 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5748 FIB_TEST(fib_test_validate_entry(fei,
5749 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5750 2,
5751 &l99_eos_o_10_10_10_1,
5752 &adj_o_10_10_11_2),
5753 "1.1.1.1/32 LB 2 buckets via: "
5754 "label 99 over 10.10.10.1, "
5755 "adj over 10.10.11.2");
5756
5757 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5758 &pfx_24001_eos);
5759 FIB_TEST(fib_test_validate_entry(fei,
5760 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5761 2,
5762 &l99_eos_o_10_10_10_1,
5763 &adj_o_10_10_11_2),
5764 "24001/eos LB 2 buckets via: "
5765 "label 99 over 10.10.10.1, "
5766 "adj over 10.10.11.2");
5767
5768 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5769 &pfx_24001_neos);
5770 FIB_TEST(fib_test_validate_entry(fei,
5771 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5772 1,
5773 &l99_neos_o_10_10_10_1),
5774 "24001/neos LB 1 buckets via: "
5775 "label 99 over 10.10.10.1");
5776
5777 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07005778 * change the local label
5779 */
5780 fib_table_entry_local_label_add(fib_index,
5781 &pfx_1_1_1_1_s_32,
5782 25005);
5783
5784 fib_prefix_t pfx_25005_eos = {
5785 .fp_proto = FIB_PROTOCOL_MPLS,
5786 .fp_label = 25005,
5787 .fp_eos = MPLS_EOS,
5788 };
5789 fib_prefix_t pfx_25005_neos = {
5790 .fp_proto = FIB_PROTOCOL_MPLS,
5791 .fp_label = 25005,
5792 .fp_eos = MPLS_NON_EOS,
5793 };
5794
5795 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5796 fib_table_lookup(fib_index, &pfx_24001_eos)),
5797 "24001/eos removed after label change");
5798 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5799 fib_table_lookup(fib_index, &pfx_24001_neos)),
5800 "24001/eos removed after label change");
5801
5802 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5803 &pfx_25005_eos);
5804 FIB_TEST(fib_test_validate_entry(fei,
5805 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5806 2,
5807 &l99_eos_o_10_10_10_1,
5808 &adj_o_10_10_11_2),
5809 "25005/eos LB 2 buckets via: "
5810 "label 99 over 10.10.10.1, "
5811 "adj over 10.10.11.2");
5812
5813 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5814 &pfx_25005_neos);
5815 FIB_TEST(fib_test_validate_entry(fei,
5816 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5817 1,
5818 &l99_neos_o_10_10_10_1),
5819 "25005/neos LB 1 buckets via: "
5820 "label 99 over 10.10.10.1");
5821
5822 /*
5823 * remove the local label.
5824 * the check that the MPLS entries are gone is done by the fact the
5825 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005826 */
5827 fib_table_entry_local_label_remove(fib_index,
5828 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07005829 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005830
5831 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5832 FIB_TEST(fib_test_validate_entry(fei,
5833 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5834 2,
5835 &l99_eos_o_10_10_10_1,
5836 &adj_o_10_10_11_2),
5837 "24001/eos LB 2 buckets via: "
5838 "label 99 over 10.10.10.1, "
5839 "adj over 10.10.11.2");
5840
5841 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5842 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
5843 "No more MPLS FIB entries => table removed");
5844
5845 /*
5846 * add another via-entry for the recursive
5847 */
5848 fib_prefix_t pfx_1_1_1_2_s_32 = {
5849 .fp_len = 32,
5850 .fp_proto = FIB_PROTOCOL_IP4,
5851 .fp_addr = {
5852 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
5853 },
5854 };
5855 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
5856 .type = FT_LB_LABEL_O_ADJ,
5857 .label_o_adj = {
5858 .adj = ai_mpls_10_10_10_1,
5859 .label = 101,
5860 .eos = MPLS_EOS,
5861 },
5862 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005863 mpls_label_t *l101 = NULL;
5864 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005865
5866 fei = fib_table_entry_update_one_path(fib_index,
5867 &pfx_1_1_1_2_s_32,
5868 FIB_SOURCE_API,
5869 FIB_ENTRY_FLAG_NONE,
5870 FIB_PROTOCOL_IP4,
5871 &nh_10_10_10_1,
5872 tm->hw[0]->sw_if_index,
5873 ~0, // invalid fib index
5874 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005875 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005876 FIB_ROUTE_PATH_FLAG_NONE);
5877
5878 FIB_TEST(fib_test_validate_entry(fei,
5879 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5880 1,
5881 &l101_eos_o_10_10_10_1),
5882 "1.1.1.2/32 LB 1 buckets via: "
5883 "label 101 over 10.10.10.1");
5884
Neale Ranns948e00f2016-10-20 13:39:34 +01005885 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005886 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5887 &pfx_1_1_1_1_s_32),
5888 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5889 &non_eos_1_1_1_1);
5890 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5891 &pfx_1_1_1_2_s_32),
5892 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5893 &non_eos_1_1_1_2);
5894
5895 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
5896 .type = FT_LB_LABEL_O_LB,
5897 .label_o_lb = {
5898 .lb = non_eos_1_1_1_2.dpoi_index,
5899 .label = 1601,
5900 .eos = MPLS_EOS,
5901 },
5902 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005903 mpls_label_t *l1601 = NULL;
5904 vec_add1(l1601, 1601);
5905
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005906 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
5907
5908 fei = fib_table_entry_path_add(fib_index,
5909 &pfx_2_2_2_2_s_32,
5910 FIB_SOURCE_API,
5911 FIB_ENTRY_FLAG_NONE,
5912 FIB_PROTOCOL_IP4,
5913 &pfx_1_1_1_2_s_32.fp_addr,
5914 ~0,
5915 fib_index,
5916 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005917 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005918 FIB_ROUTE_PATH_FLAG_NONE);
5919
5920 FIB_TEST(fib_test_validate_entry(fei,
5921 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5922 2,
5923 &l1600_eos_o_1_1_1_1,
5924 &l1601_eos_o_1_1_1_2),
5925 "2.2.2.2/32 LB 2 buckets via: "
5926 "label 1600 via 1.1,1.1, "
5927 "label 16001 via 1.1.1.2");
5928
5929 /*
5930 * update the via-entry so it no longer has an imp-null path.
5931 * the LB for the recursive can use an imp-null
5932 */
Neale Rannsad422ed2016-11-02 14:20:04 +00005933 l_imp_null = NULL;
5934 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
5935
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005936 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_11_1,
5942 tm->hw[1]->sw_if_index,
5943 ~0, // invalid fib index
5944 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005945 l_imp_null,
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 &a_o_10_10_11_1),
5952 "1.1.1.2/32 LB 1 buckets via: "
5953 "adj 10.10.11.1");
5954
5955 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5956 FIB_TEST(fib_test_validate_entry(fei,
5957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5958 2,
5959 &l1600_eos_o_1_1_1_1,
5960 &l1601_eos_o_1_1_1_2),
5961 "2.2.2.2/32 LB 2 buckets via: "
5962 "label 1600 via 1.1,1.1, "
5963 "label 16001 via 1.1.1.2");
5964
5965 /*
5966 * update the via-entry so it no longer has labelled paths.
5967 * the LB for the recursive should exclue this via form its LB
5968 */
5969 fei = fib_table_entry_update_one_path(fib_index,
5970 &pfx_1_1_1_2_s_32,
5971 FIB_SOURCE_API,
5972 FIB_ENTRY_FLAG_NONE,
5973 FIB_PROTOCOL_IP4,
5974 &nh_10_10_11_1,
5975 tm->hw[1]->sw_if_index,
5976 ~0, // invalid fib index
5977 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005978 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005979 FIB_ROUTE_PATH_FLAG_NONE);
5980
5981 FIB_TEST(fib_test_validate_entry(fei,
5982 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5983 1,
5984 &a_o_10_10_11_1),
5985 "1.1.1.2/32 LB 1 buckets via: "
5986 "adj 10.10.11.1");
5987
5988 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5989 FIB_TEST(fib_test_validate_entry(fei,
5990 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5991 1,
5992 &l1600_eos_o_1_1_1_1),
5993 "2.2.2.2/32 LB 1 buckets via: "
5994 "label 1600 via 1.1,1.1");
5995
5996 dpo_reset(&non_eos_1_1_1_1);
5997 dpo_reset(&non_eos_1_1_1_2);
5998
5999 /*
6000 * Add a recursive with no out-labels. We expect to use the IP of the via
6001 */
6002 fib_prefix_t pfx_2_2_2_3_s_32 = {
6003 .fp_len = 32,
6004 .fp_proto = FIB_PROTOCOL_IP4,
6005 .fp_addr = {
6006 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6007 },
6008 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006009 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006010
6011 fib_table_entry_update_one_path(fib_index,
6012 &pfx_2_2_2_3_s_32,
6013 FIB_SOURCE_API,
6014 FIB_ENTRY_FLAG_NONE,
6015 FIB_PROTOCOL_IP4,
6016 &pfx_1_1_1_1_s_32.fp_addr,
6017 ~0,
6018 fib_index,
6019 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006020 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006021 FIB_ROUTE_PATH_FLAG_NONE);
6022
6023 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6024 &pfx_1_1_1_1_s_32),
6025 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6026 &ip_1_1_1_1);
6027
6028 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6029 .type = FT_LB_O_LB,
6030 .lb = {
6031 .lb = ip_1_1_1_1.dpoi_index,
6032 },
6033 };
6034
6035 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6036 FIB_TEST(fib_test_validate_entry(fei,
6037 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6038 1,
6039 &ip_o_1_1_1_1),
6040 "2.2.2.2.3/32 LB 1 buckets via: "
6041 "ip 1.1.1.1");
6042
6043 /*
6044 * Add a recursive with an imp-null out-label.
6045 * We expect to use the IP of the via
6046 */
6047 fib_prefix_t pfx_2_2_2_4_s_32 = {
6048 .fp_len = 32,
6049 .fp_proto = FIB_PROTOCOL_IP4,
6050 .fp_addr = {
6051 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6052 },
6053 };
6054
6055 fib_table_entry_update_one_path(fib_index,
6056 &pfx_2_2_2_4_s_32,
6057 FIB_SOURCE_API,
6058 FIB_ENTRY_FLAG_NONE,
6059 FIB_PROTOCOL_IP4,
6060 &pfx_1_1_1_1_s_32.fp_addr,
6061 ~0,
6062 fib_index,
6063 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006064 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006065 FIB_ROUTE_PATH_FLAG_NONE);
6066
6067 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6068 FIB_TEST(fib_test_validate_entry(fei,
6069 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6070 1,
6071 &ip_o_1_1_1_1),
6072 "2.2.2.2.4/32 LB 1 buckets via: "
6073 "ip 1.1.1.1");
6074
6075 dpo_reset(&ip_1_1_1_1);
6076
6077 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006078 * Create an entry with a deep label stack
6079 */
6080 fib_prefix_t pfx_2_2_5_5_s_32 = {
6081 .fp_len = 32,
6082 .fp_proto = FIB_PROTOCOL_IP4,
6083 .fp_addr = {
6084 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6085 },
6086 };
6087 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6088 .type = FT_LB_LABEL_STACK_O_ADJ,
6089 .label_stack_o_adj = {
6090 .adj = ai_mpls_10_10_11_1,
6091 .label_stack_size = 8,
6092 .label_stack = {
6093 200, 201, 202, 203, 204, 205, 206, 207
6094 },
6095 .eos = MPLS_EOS,
6096 },
6097 };
6098 mpls_label_t *label_stack = NULL;
6099 vec_validate(label_stack, 7);
6100 for (ii = 0; ii < 8; ii++)
6101 {
6102 label_stack[ii] = ii + 200;
6103 }
6104
6105 fei = fib_table_entry_update_one_path(fib_index,
6106 &pfx_2_2_5_5_s_32,
6107 FIB_SOURCE_API,
6108 FIB_ENTRY_FLAG_NONE,
6109 FIB_PROTOCOL_IP4,
6110 &nh_10_10_11_1,
6111 tm->hw[1]->sw_if_index,
6112 ~0, // invalid fib index
6113 1,
6114 label_stack,
6115 FIB_ROUTE_PATH_FLAG_NONE);
6116
6117 FIB_TEST(fib_test_validate_entry(fei,
6118 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6119 1,
6120 &ls_eos_o_10_10_10_1),
6121 "2.2.5.5/32 LB 1 buckets via: "
6122 "adj 10.10.11.1");
6123 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6124
6125 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006126 * cleanup
6127 */
6128 fib_table_entry_delete(fib_index,
6129 &pfx_1_1_1_2_s_32,
6130 FIB_SOURCE_API);
6131
6132 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6133 FIB_TEST(fib_test_validate_entry(fei,
6134 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6135 1,
6136 &l1600_eos_o_1_1_1_1),
6137 "2.2.2.2/32 LB 1 buckets via: "
6138 "label 1600 via 1.1,1.1");
6139
6140 fib_table_entry_delete(fib_index,
6141 &pfx_1_1_1_1_s_32,
6142 FIB_SOURCE_API);
6143
6144 FIB_TEST(fib_test_validate_entry(fei,
6145 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6146 1,
6147 &bucket_drop),
6148 "2.2.2.2/32 LB 1 buckets via: DROP");
6149
6150 fib_table_entry_delete(fib_index,
6151 &pfx_2_2_2_2_s_32,
6152 FIB_SOURCE_API);
6153 fib_table_entry_delete(fib_index,
6154 &pfx_2_2_2_3_s_32,
6155 FIB_SOURCE_API);
6156 fib_table_entry_delete(fib_index,
6157 &pfx_2_2_2_4_s_32,
6158 FIB_SOURCE_API);
6159
6160 adj_unlock(ai_mpls_10_10_10_1);
6161 adj_unlock(ai_mpls_10_10_11_2);
6162 adj_unlock(ai_v4_10_10_11_1);
6163 adj_unlock(ai_v4_10_10_11_2);
6164 adj_unlock(ai_mpls_10_10_11_1);
6165
6166 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6167 adj_nbr_db_size());
6168
6169 local0_pfx.fp_len = 32;
6170 fib_table_entry_delete(fib_index,
6171 &local0_pfx,
6172 FIB_SOURCE_INTERFACE);
6173 local0_pfx.fp_len = 24;
6174 fib_table_entry_delete(fib_index,
6175 &local0_pfx,
6176 FIB_SOURCE_INTERFACE);
6177 local1_pfx.fp_len = 32;
6178 fib_table_entry_delete(fib_index,
6179 &local1_pfx,
6180 FIB_SOURCE_INTERFACE);
6181 local1_pfx.fp_len = 24;
6182 fib_table_entry_delete(fib_index,
6183 &local1_pfx,
6184 FIB_SOURCE_INTERFACE);
6185
6186 /*
6187 * +1 for the drop LB in the MPLS tables.
6188 */
6189 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6190 "Load-balance resources freed %d of %d",
6191 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006192
6193 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006194}
6195
6196#define N_TEST_CHILDREN 4
6197#define PARENT_INDEX 0
6198
6199typedef struct fib_node_test_t_
6200{
6201 fib_node_t node;
6202 u32 sibling;
6203 u32 index;
6204 fib_node_back_walk_ctx_t *ctxs;
6205 u32 destroyed;
6206} fib_node_test_t;
6207
6208static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6209
6210#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6211
6212#define FOR_EACH_TEST_CHILD(_tc) \
6213 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6214 ii < N_TEST_CHILDREN+1; \
6215 ii++, (_tc) = &fib_test_nodes[ii])
6216
6217static fib_node_t *
6218fib_test_child_get_node (fib_node_index_t index)
6219{
6220 return (&fib_test_nodes[index].node);
6221}
6222
6223static int fib_test_walk_spawns_walks;
6224
6225static fib_node_back_walk_rc_t
6226fib_test_child_back_walk_notify (fib_node_t *node,
6227 fib_node_back_walk_ctx_t *ctx)
6228{
6229 fib_node_test_t *tc = (fib_node_test_t*) node;
6230
6231 vec_add1(tc->ctxs, *ctx);
6232
6233 if (1 == fib_test_walk_spawns_walks)
6234 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6235 if (2 == fib_test_walk_spawns_walks)
6236 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6237 FIB_WALK_PRIORITY_HIGH, ctx);
6238
6239 return (FIB_NODE_BACK_WALK_CONTINUE);
6240}
6241
6242static void
6243fib_test_child_last_lock_gone (fib_node_t *node)
6244{
6245 fib_node_test_t *tc = (fib_node_test_t *)node;
6246
6247 tc->destroyed = 1;
6248}
6249
6250/**
6251 * The FIB walk's graph node virtual function table
6252 */
6253static const fib_node_vft_t fib_test_child_vft = {
6254 .fnv_get = fib_test_child_get_node,
6255 .fnv_last_lock = fib_test_child_last_lock_gone,
6256 .fnv_back_walk = fib_test_child_back_walk_notify,
6257};
6258
6259/*
6260 * the function (that should have been static but isn't so I can do this)
6261 * that processes the walk from the async queue,
6262 */
6263f64 fib_walk_process_queues(vlib_main_t * vm,
6264 const f64 quota);
6265u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6266
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006267static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006268fib_test_walk (void)
6269{
6270 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6271 fib_node_test_t *tc;
6272 vlib_main_t *vm;
6273 u32 ii;
6274
6275 vm = vlib_get_main();
6276 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6277
6278 /*
6279 * init a fake node on which we will add children
6280 */
6281 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6282 FIB_NODE_TYPE_TEST);
6283
6284 FOR_EACH_TEST_CHILD(tc)
6285 {
6286 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6287 fib_node_lock(&tc->node);
6288 tc->ctxs = NULL;
6289 tc->index = ii;
6290 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6291 PARENT_INDEX,
6292 FIB_NODE_TYPE_TEST, ii);
6293 }
6294
6295 /*
6296 * enqueue a walk across the parents children.
6297 */
Neale Ranns450cd302016-11-09 17:49:42 +00006298 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006299
6300 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6301 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6302 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6303 "Parent has %d children pre-walk",
6304 fib_node_list_get_size(PARENT()->fn_children));
6305
6306 /*
6307 * give the walk a large amount of time so it gets to the end
6308 */
6309 fib_walk_process_queues(vm, 1);
6310
6311 FOR_EACH_TEST_CHILD(tc)
6312 {
6313 FIB_TEST(1 == vec_len(tc->ctxs),
6314 "%d child visitsed %d times",
6315 ii, vec_len(tc->ctxs));
6316 vec_free(tc->ctxs);
6317 }
6318 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6319 "Queue is empty post walk");
6320 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6321 "Parent has %d children post walk",
6322 fib_node_list_get_size(PARENT()->fn_children));
6323
6324 /*
6325 * walk again. should be no increase in the number of visits, since
6326 * the walk will have terminated.
6327 */
6328 fib_walk_process_queues(vm, 1);
6329
6330 FOR_EACH_TEST_CHILD(tc)
6331 {
6332 FIB_TEST(0 == vec_len(tc->ctxs),
6333 "%d child visitsed %d times",
6334 ii, vec_len(tc->ctxs));
6335 }
6336
6337 /*
6338 * schedule a low and hig priority walk. expect the high to be performed
6339 * before the low.
6340 * schedule the high prio walk first so that it is further from the head
6341 * of the dependency list. that way it won't merge with the low one.
6342 */
6343 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6344 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6345
6346 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6347 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6348 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6349 FIB_WALK_PRIORITY_LOW, &low_ctx);
6350
6351 fib_walk_process_queues(vm, 1);
6352
6353 FOR_EACH_TEST_CHILD(tc)
6354 {
6355 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6356 "%d child visitsed by high prio walk", ii);
6357 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6358 "%d child visitsed by low prio walk", ii);
6359 vec_free(tc->ctxs);
6360 }
6361 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6362 "Queue is empty post prio walk");
6363 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6364 "Parent has %d children post prio walk",
6365 fib_node_list_get_size(PARENT()->fn_children));
6366
6367 /*
6368 * schedule 2 walks of the same priority that can be megred.
6369 * expect that each child is thus visited only once.
6370 */
6371 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6372 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6373
6374 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6375 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6376 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6377 FIB_WALK_PRIORITY_HIGH, &low_ctx);
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 during merge walk",
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 merge walk");
6390 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6391 "Parent has %d children post merge walk",
6392 fib_node_list_get_size(PARENT()->fn_children));
6393
6394 /*
6395 * schedule 2 walks of the same priority that cannot be megred.
6396 * expect that each child is thus visited twice and in the order
6397 * in which the walks were scheduled.
6398 */
6399 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6400 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6401
6402 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6403 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6404 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6405 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6406
6407 fib_walk_process_queues(vm, 1);
6408
6409 FOR_EACH_TEST_CHILD(tc)
6410 {
6411 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6412 "%d child visitsed by high prio walk", ii);
6413 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6414 "%d child visitsed by low prio walk", ii);
6415 vec_free(tc->ctxs);
6416 }
6417 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6418 "Queue is empty post no-merge walk");
6419 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6420 "Parent has %d children post no-merge walk",
6421 fib_node_list_get_size(PARENT()->fn_children));
6422
6423 /*
6424 * schedule a walk that makes one one child progress.
6425 * we do this by giving the queue draining process zero
6426 * time quanta. it's a do..while loop, so it does something.
6427 */
Neale Ranns450cd302016-11-09 17:49:42 +00006428 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006429
6430 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6431 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6432 fib_walk_process_queues(vm, 0);
6433
6434 FOR_EACH_TEST_CHILD(tc)
6435 {
6436 if (ii == N_TEST_CHILDREN)
6437 {
6438 FIB_TEST(1 == vec_len(tc->ctxs),
6439 "%d child visitsed %d times in zero quanta walk",
6440 ii, vec_len(tc->ctxs));
6441 }
6442 else
6443 {
6444 FIB_TEST(0 == vec_len(tc->ctxs),
6445 "%d child visitsed %d times in 0 quanta walk",
6446 ii, vec_len(tc->ctxs));
6447 }
6448 }
6449 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6450 "Queue is not empty post zero quanta walk");
6451 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6452 "Parent has %d children post zero qunta walk",
6453 fib_node_list_get_size(PARENT()->fn_children));
6454
6455 /*
6456 * another one step
6457 */
6458 fib_walk_process_queues(vm, 0);
6459
6460 FOR_EACH_TEST_CHILD(tc)
6461 {
6462 if (ii >= N_TEST_CHILDREN-1)
6463 {
6464 FIB_TEST(1 == vec_len(tc->ctxs),
6465 "%d child visitsed %d times in 2nd zero quanta walk",
6466 ii, vec_len(tc->ctxs));
6467 }
6468 else
6469 {
6470 FIB_TEST(0 == vec_len(tc->ctxs),
6471 "%d child visitsed %d times in 2nd 0 quanta walk",
6472 ii, vec_len(tc->ctxs));
6473 }
6474 }
6475 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6476 "Queue is not empty post zero quanta walk");
6477 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6478 "Parent has %d children post zero qunta walk",
6479 fib_node_list_get_size(PARENT()->fn_children));
6480
6481 /*
6482 * schedule another walk that will catch-up and merge.
6483 */
6484 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6485 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6486 fib_walk_process_queues(vm, 1);
6487
6488 FOR_EACH_TEST_CHILD(tc)
6489 {
6490 if (ii >= N_TEST_CHILDREN-1)
6491 {
6492 FIB_TEST(2 == vec_len(tc->ctxs),
6493 "%d child visitsed %d times in 2nd zero quanta merge walk",
6494 ii, vec_len(tc->ctxs));
6495 vec_free(tc->ctxs);
6496 }
6497 else
6498 {
6499 FIB_TEST(1 == vec_len(tc->ctxs),
6500 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6501 ii, vec_len(tc->ctxs));
6502 vec_free(tc->ctxs);
6503 }
6504 }
6505 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6506 "Queue is not empty post 2nd zero quanta merge walk");
6507 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6508 "Parent has %d children post 2nd zero qunta merge walk",
6509 fib_node_list_get_size(PARENT()->fn_children));
6510
6511 /*
6512 * park a async walk in the middle of the list, then have an sync walk catch
6513 * it. same expectations as async catches async.
6514 */
Neale Ranns450cd302016-11-09 17:49:42 +00006515 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006516
6517 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6518 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6519
6520 fib_walk_process_queues(vm, 0);
6521 fib_walk_process_queues(vm, 0);
6522
6523 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6524
6525 FOR_EACH_TEST_CHILD(tc)
6526 {
6527 if (ii >= N_TEST_CHILDREN-1)
6528 {
6529 FIB_TEST(2 == vec_len(tc->ctxs),
6530 "%d child visitsed %d times in sync catches async walk",
6531 ii, vec_len(tc->ctxs));
6532 vec_free(tc->ctxs);
6533 }
6534 else
6535 {
6536 FIB_TEST(1 == vec_len(tc->ctxs),
6537 "%d child visitsed %d times in sync catches async walk",
6538 ii, vec_len(tc->ctxs));
6539 vec_free(tc->ctxs);
6540 }
6541 }
6542 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6543 "Queue is not empty post 2nd zero quanta merge walk");
6544 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6545 "Parent has %d children post 2nd zero qunta merge walk",
6546 fib_node_list_get_size(PARENT()->fn_children));
6547
6548 /*
6549 * make the parent a child of one of its children, thus inducing a routing loop.
6550 */
6551 fib_test_nodes[PARENT_INDEX].sibling =
6552 fib_node_child_add(FIB_NODE_TYPE_TEST,
6553 1, // the first child
6554 FIB_NODE_TYPE_TEST,
6555 PARENT_INDEX);
6556
6557 /*
6558 * execute a sync walk from the parent. each child visited spawns more sync
6559 * walks. we expect the walk to terminate.
6560 */
6561 fib_test_walk_spawns_walks = 1;
6562
6563 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6564
6565 FOR_EACH_TEST_CHILD(tc)
6566 {
6567 /*
6568 * child 1 - which is last in the list - has the loop.
6569 * the other children a re thus visitsed first. the we meet
6570 * child 1. we go round the loop again, visting the other children.
6571 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6572 * again.
6573 */
6574 if (1 == ii)
6575 {
6576 FIB_TEST(1 == vec_len(tc->ctxs),
6577 "child %d visitsed %d times during looped sync walk",
6578 ii, vec_len(tc->ctxs));
6579 }
6580 else
6581 {
6582 FIB_TEST(2 == vec_len(tc->ctxs),
6583 "child %d visitsed %d times during looped sync walk",
6584 ii, vec_len(tc->ctxs));
6585 }
6586 vec_free(tc->ctxs);
6587 }
6588 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6589 "Parent has %d children post sync loop walk",
6590 fib_node_list_get_size(PARENT()->fn_children));
6591
6592 /*
6593 * the walk doesn't reach the max depth because the infra knows that sync
6594 * meets sync implies a loop and bails early.
6595 */
6596 FIB_TEST(high_ctx.fnbw_depth == 9,
6597 "Walk context depth %d post sync loop walk",
6598 high_ctx.fnbw_depth);
6599
6600 /*
6601 * execute an async walk of the graph loop, with each child spawns sync walks
6602 */
6603 high_ctx.fnbw_depth = 0;
6604 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6605 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6606
6607 fib_walk_process_queues(vm, 1);
6608
6609 FOR_EACH_TEST_CHILD(tc)
6610 {
6611 /*
6612 * we don't really care how many times the children are visisted, as long as
6613 * it is more than once.
6614 */
6615 FIB_TEST(1 <= vec_len(tc->ctxs),
6616 "child %d visitsed %d times during looped aync spawns sync walk",
6617 ii, vec_len(tc->ctxs));
6618 vec_free(tc->ctxs);
6619 }
6620
6621 /*
6622 * execute an async walk of the graph loop, with each child spawns async walks
6623 */
6624 fib_test_walk_spawns_walks = 2;
6625 high_ctx.fnbw_depth = 0;
6626 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6627 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6628
6629 fib_walk_process_queues(vm, 1);
6630
6631 FOR_EACH_TEST_CHILD(tc)
6632 {
6633 /*
6634 * we don't really care how many times the children are visisted, as long as
6635 * it is more than once.
6636 */
6637 FIB_TEST(1 <= vec_len(tc->ctxs),
6638 "child %d visitsed %d times during looped async spawns async walk",
6639 ii, vec_len(tc->ctxs));
6640 vec_free(tc->ctxs);
6641 }
6642
6643
6644 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6645 1, // the first child
6646 fib_test_nodes[PARENT_INDEX].sibling);
6647
6648 /*
6649 * cleanup
6650 */
6651 FOR_EACH_TEST_CHILD(tc)
6652 {
6653 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6654 tc->sibling);
6655 fib_node_deinit(&tc->node);
6656 fib_node_unlock(&tc->node);
6657 }
6658 fib_node_deinit(PARENT());
6659
6660 /*
6661 * The parent will be destroyed when the last lock on it goes.
6662 * this test ensures all the walk objects are unlocking it.
6663 */
6664 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
6665 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006666
6667 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006668}
6669
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006670static int
6671lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006672{
6673 const mpls_label_t deag_label = 50;
6674 const u32 lfib_index = 0;
6675 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01006676 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006677 const dpo_id_t *dpo1;
6678 fib_node_index_t lfe;
6679 lookup_dpo_t *lkd;
6680 test_main_t *tm;
6681 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00006682 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006683
6684 tm = &test_main;
6685 lb_count = pool_elts(load_balance_pool);
6686
6687 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6688 adj_nbr_db_size());
6689
6690 /*
6691 * MPLS enable an interface so we get the MPLS table created
6692 */
6693 mpls_sw_interface_enable_disable(&mpls_main,
6694 tm->hw[0]->sw_if_index,
6695 1);
6696
Neale Rannsad422ed2016-11-02 14:20:04 +00006697 ip46_address_t nh_10_10_10_1 = {
6698 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6699 };
6700 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6701 VNET_LINK_MPLS,
6702 &nh_10_10_10_1,
6703 tm->hw[0]->sw_if_index);
6704
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006705 /*
6706 * Test the specials stack properly.
6707 */
6708 fib_prefix_t exp_null_v6_pfx = {
6709 .fp_proto = FIB_PROTOCOL_MPLS,
6710 .fp_eos = MPLS_EOS,
6711 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6712 .fp_payload_proto = DPO_PROTO_IP6,
6713 };
6714 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
6715 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
6716 "%U/%U present",
6717 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6718 format_mpls_eos_bit, MPLS_EOS);
6719 fib_entry_contribute_forwarding(lfe,
6720 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6721 &dpo);
6722 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6723 lkd = lookup_dpo_get(dpo1->dpoi_index);
6724
6725 FIB_TEST((fib_index == lkd->lkd_fib_index),
6726 "%U/%U is deag in %d %U",
6727 format_mpls_unicast_label, deag_label,
6728 format_mpls_eos_bit, MPLS_EOS,
6729 lkd->lkd_fib_index,
6730 format_dpo_id, &dpo, 0);
6731 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6732 "%U/%U is dst deag",
6733 format_mpls_unicast_label, deag_label,
6734 format_mpls_eos_bit, MPLS_EOS);
6735 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
6736 "%U/%U is lookup in interface's table",
6737 format_mpls_unicast_label, deag_label,
6738 format_mpls_eos_bit, MPLS_EOS);
6739 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
6740 "%U/%U is %U dst deag",
6741 format_mpls_unicast_label, deag_label,
6742 format_mpls_eos_bit, MPLS_EOS,
6743 format_dpo_proto, lkd->lkd_proto);
6744
6745
6746 /*
6747 * A route deag route for EOS
6748 */
6749 fib_prefix_t pfx = {
6750 .fp_proto = FIB_PROTOCOL_MPLS,
6751 .fp_eos = MPLS_EOS,
6752 .fp_label = deag_label,
6753 .fp_payload_proto = DPO_PROTO_IP4,
6754 };
6755 lfe = fib_table_entry_path_add(lfib_index,
6756 &pfx,
6757 FIB_SOURCE_CLI,
6758 FIB_ENTRY_FLAG_NONE,
6759 FIB_PROTOCOL_IP4,
6760 &zero_addr,
6761 ~0,
6762 fib_index,
6763 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006764 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006765 FIB_ROUTE_PATH_FLAG_NONE);
6766
6767 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6768 "%U/%U present",
6769 format_mpls_unicast_label, deag_label,
6770 format_mpls_eos_bit, MPLS_EOS);
6771
6772 fib_entry_contribute_forwarding(lfe,
6773 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6774 &dpo);
6775 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6776 lkd = lookup_dpo_get(dpo1->dpoi_index);
6777
6778 FIB_TEST((fib_index == lkd->lkd_fib_index),
6779 "%U/%U is deag in %d %U",
6780 format_mpls_unicast_label, deag_label,
6781 format_mpls_eos_bit, MPLS_EOS,
6782 lkd->lkd_fib_index,
6783 format_dpo_id, &dpo, 0);
6784 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6785 "%U/%U is dst deag",
6786 format_mpls_unicast_label, deag_label,
6787 format_mpls_eos_bit, MPLS_EOS);
6788 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
6789 "%U/%U is %U dst deag",
6790 format_mpls_unicast_label, deag_label,
6791 format_mpls_eos_bit, MPLS_EOS,
6792 format_dpo_proto, lkd->lkd_proto);
6793
6794 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6795
6796 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6797 &pfx)),
6798 "%U/%U not present",
6799 format_mpls_unicast_label, deag_label,
6800 format_mpls_eos_bit, MPLS_EOS);
6801
6802 /*
6803 * A route deag route for non-EOS
6804 */
6805 pfx.fp_eos = MPLS_NON_EOS;
6806 lfe = fib_table_entry_path_add(lfib_index,
6807 &pfx,
6808 FIB_SOURCE_CLI,
6809 FIB_ENTRY_FLAG_NONE,
6810 FIB_PROTOCOL_IP4,
6811 &zero_addr,
6812 ~0,
6813 lfib_index,
6814 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006815 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006816 FIB_ROUTE_PATH_FLAG_NONE);
6817
6818 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6819 "%U/%U present",
6820 format_mpls_unicast_label, deag_label,
6821 format_mpls_eos_bit, MPLS_NON_EOS);
6822
6823 fib_entry_contribute_forwarding(lfe,
6824 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6825 &dpo);
6826 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6827 lkd = lookup_dpo_get(dpo1->dpoi_index);
6828
6829 FIB_TEST((fib_index == lkd->lkd_fib_index),
6830 "%U/%U is deag in %d %U",
6831 format_mpls_unicast_label, deag_label,
6832 format_mpls_eos_bit, MPLS_NON_EOS,
6833 lkd->lkd_fib_index,
6834 format_dpo_id, &dpo, 0);
6835 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6836 "%U/%U is dst deag",
6837 format_mpls_unicast_label, deag_label,
6838 format_mpls_eos_bit, MPLS_NON_EOS);
6839
6840 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
6841 "%U/%U is %U dst deag",
6842 format_mpls_unicast_label, deag_label,
6843 format_mpls_eos_bit, MPLS_NON_EOS,
6844 format_dpo_proto, lkd->lkd_proto);
6845
6846 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6847
6848 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6849 &pfx)),
6850 "%U/%U not present",
6851 format_mpls_unicast_label, deag_label,
6852 format_mpls_eos_bit, MPLS_EOS);
6853
Neale Rannsad422ed2016-11-02 14:20:04 +00006854 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006855
Neale Rannsad422ed2016-11-02 14:20:04 +00006856 /*
6857 * An MPLS x-connect
6858 */
6859 fib_prefix_t pfx_1200 = {
6860 .fp_len = 21,
6861 .fp_proto = FIB_PROTOCOL_MPLS,
6862 .fp_label = 1200,
6863 .fp_eos = MPLS_NON_EOS,
6864 };
6865 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
6866 .type = FT_LB_LABEL_STACK_O_ADJ,
6867 .label_stack_o_adj = {
6868 .adj = ai_mpls_10_10_10_1,
6869 .label_stack_size = 4,
6870 .label_stack = {
6871 200, 300, 400, 500,
6872 },
6873 .eos = MPLS_NON_EOS,
6874 },
6875 };
6876 dpo_id_t neos_1200 = DPO_INVALID;
6877 dpo_id_t ip_1200 = DPO_INVALID;
6878 mpls_label_t *l200 = NULL;
6879 vec_add1(l200, 200);
6880 vec_add1(l200, 300);
6881 vec_add1(l200, 400);
6882 vec_add1(l200, 500);
6883
6884 lfe = fib_table_entry_update_one_path(fib_index,
6885 &pfx_1200,
6886 FIB_SOURCE_API,
6887 FIB_ENTRY_FLAG_NONE,
6888 FIB_PROTOCOL_IP4,
6889 &nh_10_10_10_1,
6890 tm->hw[0]->sw_if_index,
6891 ~0, // invalid fib index
6892 1,
6893 l200,
6894 FIB_ROUTE_PATH_FLAG_NONE);
6895
6896 FIB_TEST(fib_test_validate_entry(lfe,
6897 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6898 1,
6899 &neos_o_10_10_10_1),
6900 "1200/0 LB 1 buckets via: "
6901 "adj 10.10.11.1");
6902
6903 /*
6904 * A recursive route via the MPLS x-connect
6905 */
6906 fib_prefix_t pfx_2_2_2_3_s_32 = {
6907 .fp_len = 32,
6908 .fp_proto = FIB_PROTOCOL_IP4,
6909 .fp_addr = {
6910 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6911 },
6912 };
6913 fib_route_path_t *rpaths = NULL, rpath = {
6914 .frp_proto = FIB_PROTOCOL_MPLS,
6915 .frp_local_label = 1200,
6916 .frp_sw_if_index = ~0, // recurive
6917 .frp_fib_index = 0, // Default MPLS fib
6918 .frp_weight = 1,
6919 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6920 .frp_label_stack = NULL,
6921 };
6922 vec_add1(rpaths, rpath);
6923
6924 fib_table_entry_path_add2(fib_index,
6925 &pfx_2_2_2_3_s_32,
6926 FIB_SOURCE_API,
6927 FIB_ENTRY_FLAG_NONE,
6928 rpaths);
6929
6930 /*
6931 * A labelled recursive route via the MPLS x-connect
6932 */
6933 fib_prefix_t pfx_2_2_2_4_s_32 = {
6934 .fp_len = 32,
6935 .fp_proto = FIB_PROTOCOL_IP4,
6936 .fp_addr = {
6937 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6938 },
6939 };
6940 mpls_label_t *l999 = NULL;
6941 vec_add1(l999, 999);
6942 rpaths[0].frp_label_stack = l999,
6943
6944 fib_table_entry_path_add2(fib_index,
6945 &pfx_2_2_2_4_s_32,
6946 FIB_SOURCE_API,
6947 FIB_ENTRY_FLAG_NONE,
6948 rpaths);
6949
6950 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
6951 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6952 &ip_1200);
6953 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
6954 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6955 &neos_1200);
6956
6957 fib_test_lb_bucket_t ip_o_1200 = {
6958 .type = FT_LB_O_LB,
6959 .lb = {
6960 .lb = ip_1200.dpoi_index,
6961 },
6962 };
6963 fib_test_lb_bucket_t mpls_o_1200 = {
6964 .type = FT_LB_LABEL_O_LB,
6965 .label_o_lb = {
6966 .lb = neos_1200.dpoi_index,
6967 .label = 999,
6968 .eos = MPLS_EOS,
6969 },
6970 };
6971
6972 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6973 FIB_TEST(fib_test_validate_entry(lfe,
6974 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6975 1,
6976 &ip_o_1200),
6977 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
6978 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6979 FIB_TEST(fib_test_validate_entry(lfe,
6980 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6981 1,
6982 &mpls_o_1200),
6983 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
6984
6985 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
6986 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
6987 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
6988
6989 dpo_reset(&neos_1200);
6990 dpo_reset(&ip_1200);
6991
6992 /*
6993 * A recursive via a label that does not exist
6994 */
6995 fib_test_lb_bucket_t bucket_drop = {
6996 .type = FT_LB_SPECIAL,
6997 .special = {
6998 .adj = DPO_PROTO_MPLS,
6999 },
7000 };
7001
7002 rpaths[0].frp_label_stack = NULL;
7003 lfe = fib_table_entry_path_add2(fib_index,
7004 &pfx_2_2_2_4_s_32,
7005 FIB_SOURCE_API,
7006 FIB_ENTRY_FLAG_NONE,
7007 rpaths);
7008
7009 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7010 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7011 &ip_1200);
7012 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7013
7014 FIB_TEST(fib_test_validate_entry(lfe,
7015 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7016 1,
7017 &ip_o_1200),
7018 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
7019 lfe = fib_table_lookup(fib_index, &pfx_1200);
7020 FIB_TEST(fib_test_validate_entry(lfe,
7021 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7022 1,
7023 &bucket_drop),
7024 "2.2.2.4/32 LB 1 buckets via: ip4-DROP");
7025
7026 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7027
7028 dpo_reset(&ip_1200);
7029
7030 /*
7031 * cleanup
7032 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007033 mpls_sw_interface_enable_disable(&mpls_main,
7034 tm->hw[0]->sw_if_index,
7035 0);
7036
Neale Rannsad422ed2016-11-02 14:20:04 +00007037 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007038 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00007039 lb_count, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007040
7041 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007042}
7043
7044static clib_error_t *
7045fib_test (vlib_main_t * vm,
7046 unformat_input_t * input,
7047 vlib_cli_command_t * cmd_arg)
7048{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007049 int res;
7050
7051 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007052 fib_test_mk_intf(4);
7053
7054 if (unformat (input, "ip"))
7055 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007056 res += fib_test_v4();
7057 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007058 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007059 else if (unformat (input, "label"))
7060 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007061 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007062 }
7063 else if (unformat (input, "ae"))
7064 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007065 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007066 }
Neale Rannsad422ed2016-11-02 14:20:04 +00007067 else if (unformat (input, "lfib"))
7068 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007069 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00007070 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007071 else if (unformat (input, "walk"))
7072 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007073 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007074 }
7075 else
7076 {
7077 /*
7078 * These walk UT aren't run as part of the full suite, since the
7079 * fib-walk process must be disabled in order for the tests to work
7080 *
7081 * fib_test_walk();
7082 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007083 res += fib_test_v4();
7084 res += fib_test_v6();
7085 res += fib_test_ae();
7086 res += fib_test_label();
7087 res += lfib_test();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007088 }
7089
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007090 if (res)
7091 {
7092 return clib_error_return(0, "FIB Unit Test Failed");
7093 }
7094 else
7095 {
7096 return (NULL);
7097 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007098}
7099
7100VLIB_CLI_COMMAND (test_fib_command, static) = {
7101 .path = "test fib",
7102 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
7103 .function = fib_test,
7104};
7105
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007106clib_error_t *
7107fib_test_init (vlib_main_t *vm)
7108{
7109 return 0;
7110}
7111
7112VLIB_INIT_FUNCTION (fib_test_init);