blob: 06aeda62354a8db8e226bee11d56317defe7fcd0 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/fib/ip6_fib.h>
17#include <vnet/fib/ip4_fib.h>
18#include <vnet/fib/mpls_fib.h>
19#include <vnet/adj/adj.h>
20#include <vnet/dpo/load_balance.h>
21#include <vnet/dpo/load_balance_map.h>
22#include <vnet/dpo/mpls_label_dpo.h>
23#include <vnet/dpo/lookup_dpo.h>
24#include <vnet/dpo/drop_dpo.h>
25#include <vnet/dpo/receive_dpo.h>
Neale Ranns948e00f2016-10-20 13:39:34 +010026#include <vnet/dpo/ip_null_dpo.h>
Neale Ranns88fc83e2017-04-05 08:11:14 -070027#include <vnet/bfd/bfd_main.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080028#include <vnet/dpo/interface_dpo.h>
29#include <vnet/dpo/replicate_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010030
31#include <vnet/mpls/mpls.h>
32
33#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000034#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035#include <vnet/fib/fib_walk.h>
36#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010037#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010038
Neale Ranns88fc83e2017-04-05 08:11:14 -070039/*
40 * Add debugs for passing tests
41 */
42static int fib_test_do_debug;
43
Neale Ranns0bfe5d82016-08-25 15:29:12 +010044#define FIB_TEST_I(_cond, _comment, _args...) \
45({ \
46 int _evald = (_cond); \
47 if (!(_evald)) { \
48 fformat(stderr, "FAIL:%d: " _comment "\n", \
49 __LINE__, ##_args); \
50 } else { \
Neale Ranns88fc83e2017-04-05 08:11:14 -070051 if (fib_test_do_debug) \
52 fformat(stderr, "PASS:%d: " _comment "\n", \
53 __LINE__, ##_args); \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010054 } \
55 _evald; \
56})
57#define FIB_TEST(_cond, _comment, _args...) \
58{ \
59 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000060 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010061 ASSERT(!("FAIL: " _comment)); \
62 } \
63}
64
65/**
66 * A 'i'm not fussed is this is not efficient' store of test data
67 */
68typedef struct test_main_t_ {
69 /**
70 * HW if indicies
71 */
72 u32 hw_if_indicies[4];
73 /**
74 * HW interfaces
75 */
76 vnet_hw_interface_t * hw[4];
77
78} test_main_t;
79static test_main_t test_main;
80
81/* fake ethernet device class, distinct from "fake-ethX" */
82static u8 * format_test_interface_name (u8 * s, va_list * args)
83{
84 u32 dev_instance = va_arg (*args, u32);
85 return format (s, "test-eth%d", dev_instance);
86}
87
88static uword dummy_interface_tx (vlib_main_t * vm,
89 vlib_node_runtime_t * node,
90 vlib_frame_t * frame)
91{
92 clib_warning ("you shouldn't be here, leaking buffers...");
93 return frame->n_vectors;
94}
95
Neale Ranns8b37b872016-11-21 12:25:22 +000096static clib_error_t *
97test_interface_admin_up_down (vnet_main_t * vnm,
98 u32 hw_if_index,
99 u32 flags)
100{
101 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
102 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
103 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
104 return 0;
105}
106
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100107VNET_DEVICE_CLASS (test_interface_device_class,static) = {
108 .name = "Test interface",
109 .format_device_name = format_test_interface_name,
110 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000111 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100112};
113
114static u8 *hw_address;
115
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000116static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100117fib_test_mk_intf (u32 ninterfaces)
118{
119 clib_error_t * error = NULL;
120 test_main_t *tm = &test_main;
121 u8 byte;
122 u32 i;
123
124 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
125
126 for (i=0; i<6; i++)
127 {
128 byte = 0xd0+i;
129 vec_add1(hw_address, byte);
130 }
131
132 for (i = 0; i < ninterfaces; i++)
133 {
134 hw_address[5] = i;
135
136 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000137 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100138 i /* instance */,
139 hw_address,
140 &tm->hw_if_indicies[i],
141 /* flag change */ 0);
142
143 FIB_TEST((NULL == error), "ADD interface %d", i);
144
Neale Ranns8b37b872016-11-21 12:25:22 +0000145 error = vnet_hw_interface_set_flags(vnet_get_main(),
146 tm->hw_if_indicies[i],
147 VNET_HW_INTERFACE_FLAG_LINK_UP);
148 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100149 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000150 vec_validate (ip4_main.fib_index_by_sw_if_index,
151 tm->hw[i]->sw_if_index);
152 vec_validate (ip6_main.fib_index_by_sw_if_index,
153 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100154 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
155 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000156
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100157 error = vnet_sw_interface_set_flags(vnet_get_main(),
158 tm->hw[i]->sw_if_index,
159 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
160 FIB_TEST((NULL == error), "UP interface %d", i);
161 }
162 /*
163 * re-eval after the inevitable realloc
164 */
165 for (i = 0; i < ninterfaces; i++)
166 {
167 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
168 tm->hw_if_indicies[i]);
169 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000170
171 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100172}
173
Neale Ranns3ee44042016-10-03 13:05:48 +0100174#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100175{ \
176 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
177 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
178 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
179 fib_table_lookup(fib_index, (_via_prefix))); \
180 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100181 load_balance_get_bucket(_rec_dpo->dpoi_index, \
182 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100183 "%U is recursive via %U", \
184 format_fib_prefix, (_rec_prefix), \
185 format_fib_prefix, _via_prefix); \
186}
187
188#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
189{ \
190 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
191 fib_table_lookup_exact_match(fib_index, (_prefix))); \
192 const dpo_id_t *_dpo1 = \
193 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
194 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
195 format_dpo_type, _dpo1->dpoi_type); \
196 FIB_TEST((_ai == _dpo1->dpoi_index), \
197 "%U bucket %d resolves via %U", \
198 format_fib_prefix, (_prefix), \
199 _bucket, \
200 format_dpo_id, _dpo1, 0); \
201}
202
Neale Ranns3ee44042016-10-03 13:05:48 +0100203#define FIB_TEST_RPF(_cond, _comment, _args...) \
204{ \
205 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
206 return (0); \
207 } \
208}
209
210static int
211fib_test_urpf_is_equal (fib_node_index_t fei,
212 fib_forward_chain_type_t fct,
213 u32 num, ...)
214{
Neale Ranns948e00f2016-10-20 13:39:34 +0100215 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100216 fib_urpf_list_t *urpf;
217 index_t ui;
218 va_list ap;
219 int ii;
220
221 va_start(ap, num);
222
223 fib_entry_contribute_forwarding(fei, fct, &dpo);
224 ui = load_balance_get_urpf(dpo.dpoi_index);
225
226 urpf = fib_urpf_list_get(ui);
227
228 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
229 "RPF:%U len %d == %d",
230 format_fib_urpf_list, ui,
231 num, vec_len(urpf->furpf_itfs));
232 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
233 "RPF:%U check-size %d == %d",
234 format_fib_urpf_list, ui,
235 num, vec_len(urpf->furpf_itfs));
236
237 for (ii = 0; ii < num; ii++)
238 {
239 adj_index_t ai = va_arg(ap, adj_index_t);
240
241 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
242 "RPF:%d item:%d - %d == %d",
243 ui, ii, ai, urpf->furpf_itfs[ii]);
244 FIB_TEST_RPF(fib_urpf_check(ui, ai),
245 "RPF:%d %d found",
246 ui, ai);
247 }
248
249 dpo_reset(&dpo);
250
Neale Ranns5899fde2016-10-12 13:51:05 +0100251 va_end(ap);
252
Neale Ranns3ee44042016-10-03 13:05:48 +0100253 return (1);
254}
255
Neale Rannsb80c5362016-10-08 13:03:40 +0100256static u8*
257fib_test_build_rewrite (u8 *eth_addr)
258{
259 u8* rewrite = NULL;
260
261 vec_validate(rewrite, 13);
262
263 memcpy(rewrite, eth_addr, 6);
264 memcpy(rewrite+6, eth_addr, 6);
265
266 return (rewrite);
267}
268
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000269typedef enum fib_test_lb_bucket_type_t_ {
270 FT_LB_LABEL_O_ADJ,
Neale Rannsad422ed2016-11-02 14:20:04 +0000271 FT_LB_LABEL_STACK_O_ADJ,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000272 FT_LB_LABEL_O_LB,
273 FT_LB_O_LB,
274 FT_LB_SPECIAL,
275 FT_LB_ADJ,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800276 FT_LB_INTF,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000277} fib_test_lb_bucket_type_t;
278
279typedef struct fib_test_lb_bucket_t_ {
280 fib_test_lb_bucket_type_t type;
281
282 union
283 {
284 struct
285 {
286 mpls_eos_bit_t eos;
287 mpls_label_t label;
288 u8 ttl;
289 adj_index_t adj;
290 } label_o_adj;
291 struct
292 {
293 mpls_eos_bit_t eos;
Neale Rannsad422ed2016-11-02 14:20:04 +0000294 mpls_label_t label_stack[8];
295 u8 label_stack_size;
296 u8 ttl;
297 adj_index_t adj;
298 } label_stack_o_adj;
299 struct
300 {
301 mpls_eos_bit_t eos;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000302 mpls_label_t label;
303 u8 ttl;
304 index_t lb;
305 } label_o_lb;
306 struct
307 {
308 index_t adj;
309 } adj;
310 struct
311 {
312 index_t lb;
313 } lb;
314 struct
315 {
316 index_t adj;
317 } special;
318 };
319} fib_test_lb_bucket_t;
320
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800321typedef enum fib_test_rep_bucket_type_t_ {
322 FT_REP_LABEL_O_ADJ,
323 FT_REP_DISP_MFIB_LOOKUP,
324 FT_REP_INTF,
325} fib_test_rep_bucket_type_t;
326
327typedef struct fib_test_rep_bucket_t_ {
328 fib_test_rep_bucket_type_t type;
329
330 union
331 {
332 struct
333 {
334 mpls_eos_bit_t eos;
335 mpls_label_t label;
336 u8 ttl;
337 adj_index_t adj;
338 } label_o_adj;
339 struct
340 {
341 adj_index_t adj;
342 } adj;
343 };
344} fib_test_rep_bucket_t;
345
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000346#define FIB_TEST_LB(_cond, _comment, _args...) \
347{ \
348 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
349 return (0); \
350 } \
351}
352
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800353int
354fib_test_validate_rep_v (const replicate_t *rep,
355 u16 n_buckets,
356 va_list ap)
357{
358 const fib_test_rep_bucket_t *exp;
359 const dpo_id_t *dpo;
360 int bucket;
361
362 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
363 "n_buckets = %d", rep->rep_n_buckets);
364
365 for (bucket = 0; bucket < n_buckets; bucket++)
366 {
367 exp = va_arg(ap, fib_test_rep_bucket_t*);
368
369 dpo = replicate_get_bucket_i(rep, bucket);
370
371 switch (exp->type)
372 {
373 case FT_REP_LABEL_O_ADJ:
374 {
375 const mpls_label_dpo_t *mld;
376 mpls_label_t hdr;
377 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
378 "bucket %d stacks on %U",
379 bucket,
380 format_dpo_type, dpo->dpoi_type);
381
382 mld = mpls_label_dpo_get(dpo->dpoi_index);
383 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
384
385 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
386 exp->label_o_adj.label),
387 "bucket %d stacks on label %d",
388 bucket,
389 exp->label_o_adj.label);
390
391 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
392 exp->label_o_adj.eos),
393 "bucket %d stacks on label %d %U",
394 bucket,
395 exp->label_o_adj.label,
396 format_mpls_eos_bit, exp->label_o_adj.eos);
397
398 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
399 "bucket %d label stacks on %U",
400 bucket,
401 format_dpo_type, mld->mld_dpo.dpoi_type);
402
403 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
404 "bucket %d label stacks on adj %d",
405 bucket,
406 exp->label_o_adj.adj);
407 }
408 break;
409 case FT_REP_INTF:
410 FIB_TEST_LB((DPO_INTERFACE == dpo->dpoi_type),
411 "bucket %d stacks on %U",
412 bucket,
413 format_dpo_type, dpo->dpoi_type);
414
415 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
416 "bucket %d stacks on adj %d",
417 bucket,
418 exp->adj.adj);
419 break;
420 case FT_REP_DISP_MFIB_LOOKUP:
421// ASSERT(0);
422 break;
423 }
424 }
425
426 return (!0);
427}
428
429int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000430fib_test_validate_lb_v (const load_balance_t *lb,
431 u16 n_buckets,
432 va_list ap)
433{
434 const dpo_id_t *dpo;
435 int bucket;
436
437 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
438
439 for (bucket = 0; bucket < n_buckets; bucket++)
440 {
441 const fib_test_lb_bucket_t *exp;
442
443 exp = va_arg(ap, fib_test_lb_bucket_t*);
444 dpo = load_balance_get_bucket_i(lb, bucket);
445
446 switch (exp->type)
447 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000448 case FT_LB_LABEL_STACK_O_ADJ:
449 {
450 const mpls_label_dpo_t *mld;
451 mpls_label_t hdr;
452 u32 ii;
453
454 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
455 "bucket %d stacks on %U",
456 bucket,
457 format_dpo_type, dpo->dpoi_type);
458
459 mld = mpls_label_dpo_get(dpo->dpoi_index);
460
461 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
462 "label stack size",
463 mld->mld_n_labels);
464
465 for (ii = 0; ii < mld->mld_n_labels; ii++)
466 {
467 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
468 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
469 exp->label_stack_o_adj.label_stack[ii]),
470 "bucket %d stacks on label %d",
471 bucket,
472 exp->label_stack_o_adj.label_stack[ii]);
473
474 if (ii == mld->mld_n_labels-1)
475 {
476 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
477 exp->label_o_adj.eos),
478 "bucket %d stacks on label %d %U!=%U",
479 bucket,
480 exp->label_stack_o_adj.label_stack[ii],
481 format_mpls_eos_bit, exp->label_o_adj.eos,
482 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
483 }
484 else
485 {
486 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
487 "bucket %d stacks on label %d %U",
488 bucket,
489 exp->label_stack_o_adj.label_stack[ii],
490 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
491 }
492 }
493
494 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
495 "bucket %d label stacks on %U",
496 bucket,
497 format_dpo_type, mld->mld_dpo.dpoi_type);
498
499 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
500 "bucket %d label stacks on adj %d",
501 bucket,
502 exp->label_stack_o_adj.adj);
503 }
504 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000505 case FT_LB_LABEL_O_ADJ:
506 {
507 const mpls_label_dpo_t *mld;
508 mpls_label_t hdr;
509 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
510 "bucket %d stacks on %U",
511 bucket,
512 format_dpo_type, dpo->dpoi_type);
513
514 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000515 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000516
517 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
518 exp->label_o_adj.label),
519 "bucket %d stacks on label %d",
520 bucket,
521 exp->label_o_adj.label);
522
523 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
524 exp->label_o_adj.eos),
525 "bucket %d stacks on label %d %U",
526 bucket,
527 exp->label_o_adj.label,
528 format_mpls_eos_bit, exp->label_o_adj.eos);
529
530 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
531 "bucket %d label stacks on %U",
532 bucket,
533 format_dpo_type, mld->mld_dpo.dpoi_type);
534
535 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
536 "bucket %d label stacks on adj %d",
537 bucket,
538 exp->label_o_adj.adj);
539 }
540 break;
541 case FT_LB_LABEL_O_LB:
542 {
543 const mpls_label_dpo_t *mld;
544 mpls_label_t hdr;
545
546 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
547 "bucket %d stacks on %U",
548 bucket,
549 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000550
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000551 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000552 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000553
Neale Rannsad422ed2016-11-02 14:20:04 +0000554 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
555 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000556 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
557 exp->label_o_lb.label),
558 "bucket %d stacks on label %d",
559 bucket,
560 exp->label_o_lb.label);
561
562 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
563 exp->label_o_lb.eos),
564 "bucket %d stacks on label %d %U",
565 bucket,
566 exp->label_o_lb.label,
567 format_mpls_eos_bit, exp->label_o_lb.eos);
568
569 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
570 "bucket %d label stacks on %U",
571 bucket,
572 format_dpo_type, mld->mld_dpo.dpoi_type);
573
574 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
575 "bucket %d label stacks on LB %d",
576 bucket,
577 exp->label_o_lb.lb);
578 }
579 break;
580 case FT_LB_ADJ:
581 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
582 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
583 "bucket %d stacks on %U",
584 bucket,
585 format_dpo_type, dpo->dpoi_type);
586 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
587 "bucket %d stacks on adj %d",
588 bucket,
589 exp->adj.adj);
590 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800591 case FT_LB_INTF:
592 FIB_TEST_I((DPO_INTERFACE == dpo->dpoi_type),
593 "bucket %d stacks on %U",
594 bucket,
595 format_dpo_type, dpo->dpoi_type);
596 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
597 "bucket %d stacks on adj %d",
598 bucket,
599 exp->adj.adj);
600 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000601 case FT_LB_O_LB:
602 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
603 "bucket %d stacks on %U",
604 bucket,
605 format_dpo_type, dpo->dpoi_type);
606 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
607 "bucket %d stacks on lb %d",
608 bucket,
609 exp->lb.lb);
610 break;
611 case FT_LB_SPECIAL:
612 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
613 "bucket %d stacks on %U",
614 bucket,
615 format_dpo_type, dpo->dpoi_type);
616 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
617 "bucket %d stacks on drop %d",
618 bucket,
619 exp->special.adj);
620 break;
621 }
622 }
623 return (!0);
624}
625
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800626int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000627fib_test_validate_entry (fib_node_index_t fei,
628 fib_forward_chain_type_t fct,
629 u16 n_buckets,
630 ...)
631{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000632 dpo_id_t dpo = DPO_INVALID;
633 fib_prefix_t pfx;
634 index_t fw_lbi;
635 u32 fib_index;
636 va_list ap;
637 int res;
638
639 va_start(ap, n_buckets);
640
641 fib_entry_get_prefix(fei, &pfx);
642 fib_index = fib_entry_get_fib_index(fei);
643 fib_entry_contribute_forwarding(fei, fct, &dpo);
644
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800645 if (DPO_REPLICATE == dpo.dpoi_type)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000646 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800647 const replicate_t *rep;
648
649 rep = replicate_get(dpo.dpoi_index);
650 res = fib_test_validate_rep_v(rep, n_buckets, ap);
651 }
652 else
653 {
654 const load_balance_t *lb;
655
656 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
657 "Entry links to %U",
658 format_dpo_type, dpo.dpoi_type);
659
660 lb = load_balance_get(dpo.dpoi_index);
661 res = fib_test_validate_lb_v(lb, n_buckets, ap);
662
663 /*
664 * ensure that the LB contributed by the entry is the
665 * same as the LB in the forwarding tables
666 */
667 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Rannsad422ed2016-11-02 14:20:04 +0000668 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800669 switch (pfx.fp_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000670 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800671 case FIB_PROTOCOL_IP4:
672 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
Neale Rannsad422ed2016-11-02 14:20:04 +0000673 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800674 case FIB_PROTOCOL_IP6:
675 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
676 break;
677 case FIB_PROTOCOL_MPLS:
678 {
679 mpls_unicast_header_t hdr = {
680 .label_exp_s_ttl = 0,
681 };
682
683 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
684 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
685 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
686
687 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
688 break;
689 }
690 default:
691 fw_lbi = 0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000692 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800693 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
694 "Contributed LB = FW LB: %U\n %U",
695 format_load_balance, fw_lbi, 0,
696 format_load_balance, dpo.dpoi_index, 0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000697 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000698 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000699
700 dpo_reset(&dpo);
701
702 va_end(ap);
703
704 return (res);
705}
706
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000707static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100708fib_test_v4 (void)
709{
710 /*
711 * In the default table check for the presence and correct forwarding
712 * of the special entries
713 */
714 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
715 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
716 const ip_adjacency_t *adj;
717 const load_balance_t *lb;
718 test_main_t *tm;
719 u32 fib_index;
Neale Ranns994dab42017-04-18 12:56:45 -0700720 int lb_count;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100721 int ii;
722
723 /* via 10.10.10.1 */
724 ip46_address_t nh_10_10_10_1 = {
725 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
726 };
727 /* via 10.10.10.2 */
728 ip46_address_t nh_10_10_10_2 = {
729 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
730 };
731
Neale Rannsf12a83f2017-04-18 09:09:40 -0700732 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
733 pool_elts(load_balance_map_pool));
734
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100735 tm = &test_main;
736
Neale Ranns994dab42017-04-18 12:56:45 -0700737 /* record the nubmer of load-balances in use before we start */
738 lb_count = pool_elts(load_balance_pool);
739
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100740 /* Find or create FIB table 11 */
741 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
742
743 for (ii = 0; ii < 4; ii++)
744 {
745 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
746 }
747
748 fib_prefix_t pfx_0_0_0_0_s_0 = {
749 .fp_len = 0,
750 .fp_proto = FIB_PROTOCOL_IP4,
751 .fp_addr = {
752 .ip4 = {
753 {0}
754 },
755 },
756 };
757
758 fib_prefix_t pfx = {
759 .fp_len = 0,
760 .fp_proto = FIB_PROTOCOL_IP4,
761 .fp_addr = {
762 .ip4 = {
763 {0}
764 },
765 },
766 };
767
768 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
769
770 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
771 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
772 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
773 "Default route is DROP");
774
775 pfx.fp_len = 32;
776 fei = fib_table_lookup(fib_index, &pfx);
777 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
778 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
779 "all 0s route is DROP");
780
781 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
782 pfx.fp_len = 32;
783 fei = fib_table_lookup(fib_index, &pfx);
784 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
785 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
786 "all 1s route is DROP");
787
788 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
789 pfx.fp_len = 8;
790 fei = fib_table_lookup(fib_index, &pfx);
791 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
792 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
793 "all-mcast route is DROP");
794
795 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
796 pfx.fp_len = 8;
797 fei = fib_table_lookup(fib_index, &pfx);
798 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
799 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
800 "class-e route is DROP");
801
802 /*
803 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
804 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000805 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
806 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100807 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000808#define ENBR (5+5+2)
809#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100810 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000811 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100812 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000813 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100814 fib_entry_pool_size());
815
816 /*
817 * add interface routes.
818 * validate presence of /24 attached and /32 recieve.
819 * test for the presence of the receive address in the glean and local adj
820 */
821 fib_prefix_t local_pfx = {
822 .fp_len = 24,
823 .fp_proto = FIB_PROTOCOL_IP4,
824 .fp_addr = {
825 .ip4 = {
826 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
827 },
828 },
829 };
830
831 fib_table_entry_update_one_path(fib_index, &local_pfx,
832 FIB_SOURCE_INTERFACE,
833 (FIB_ENTRY_FLAG_CONNECTED |
834 FIB_ENTRY_FLAG_ATTACHED),
835 FIB_PROTOCOL_IP4,
836 NULL,
837 tm->hw[0]->sw_if_index,
838 ~0, // invalid fib index
839 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000840 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100841 FIB_ROUTE_PATH_FLAG_NONE);
842 fei = fib_table_lookup(fib_index, &local_pfx);
843 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
844 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
845 fib_entry_get_flags(fei)),
846 "Flags set on attached interface");
847
848 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -0700849 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
850 "attached interface route adj present %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100851 adj = adj_get(ai);
852 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
853 "attached interface adj is glean");
854 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
855 &adj->sub_type.glean.receive_addr)),
856 "attached interface adj is receive ok");
857
858 local_pfx.fp_len = 32;
859 fib_table_entry_update_one_path(fib_index, &local_pfx,
860 FIB_SOURCE_INTERFACE,
861 (FIB_ENTRY_FLAG_CONNECTED |
862 FIB_ENTRY_FLAG_LOCAL),
863 FIB_PROTOCOL_IP4,
864 NULL,
865 tm->hw[0]->sw_if_index,
866 ~0, // invalid fib index
867 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000868 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100869 FIB_ROUTE_PATH_FLAG_NONE);
870 fei = fib_table_lookup(fib_index, &local_pfx);
871 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
872 fib_entry_get_flags(fei)),
873 "Flags set on local interface");
874
875 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
876
877 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100878 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
879 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100880 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
881 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
882 "local interface adj is local");
883 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
884
885 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
886 &rd->rd_addr)),
887 "local interface adj is receive ok");
888
889 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
890 FIB_PROTOCOL_IP4,
891 FIB_SOURCE_INTERFACE)),
892 "2 Interface Source'd prefixes");
893
894 /*
895 * +2 interface routes +2 non-shared path-lists
896 */
897 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000898 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100899 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000900 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100901 fib_entry_pool_size());
902
903 /*
904 * Modify the default route to be via an adj not yet known.
905 * this sources the defalut route with the API source, which is
906 * a higher preference to the DEFAULT_ROUTE source
907 */
908 pfx.fp_addr.ip4.as_u32 = 0;
909 pfx.fp_len = 0;
910 fib_table_entry_path_add(fib_index, &pfx,
911 FIB_SOURCE_API,
912 FIB_ENTRY_FLAG_NONE,
913 FIB_PROTOCOL_IP4,
914 &nh_10_10_10_1,
915 tm->hw[0]->sw_if_index,
916 ~0, // invalid fib index
917 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000918 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100919 FIB_ROUTE_PATH_FLAG_NONE);
920 fei = fib_table_lookup(fib_index, &pfx);
921 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
922 "Flags set on API route");
923
924 FIB_TEST((fei == dfrt), "default route same index");
925 ai = fib_entry_get_adj(fei);
926 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
927 adj = adj_get(ai);
928 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
929 "adj is incomplete");
930 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
931 "adj nbr next-hop ok");
932 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
933 FIB_PROTOCOL_IP4,
934 FIB_SOURCE_API)),
935 "1 API Source'd prefixes");
936
937 /*
938 * find the adj in the shared db
939 */
940 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100941 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100942 &nh_10_10_10_1,
943 tm->hw[0]->sw_if_index);
944 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
945 adj_unlock(locked_ai);
946
947 /*
948 * +1 shared path-list
949 */
950 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
951 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000952 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100953 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000954 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100955 fib_entry_pool_size());
956
957 /*
958 * remove the API source from the default route. We expected
959 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
960 */
961 pfx.fp_addr.ip4.as_u32 = 0;
962 pfx.fp_len = 0;
963 fib_table_entry_path_remove(fib_index, &pfx,
964 FIB_SOURCE_API,
965 FIB_PROTOCOL_IP4,
966 &nh_10_10_10_1,
967 tm->hw[0]->sw_if_index,
968 ~0, // non-recursive path, so no FIB index
969 1,
970 FIB_ROUTE_PATH_FLAG_NONE);
971
972 fei = fib_table_lookup(fib_index, &pfx);
973
974 FIB_TEST((fei == dfrt), "default route same index");
975 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
976 "Default route is DROP");
977
978 /*
979 * -1 shared-path-list
980 */
981 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000982 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100983 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000984 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100985 fib_entry_pool_size());
986
987 /*
988 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
989 */
990 fib_prefix_t pfx_10_10_10_1_s_32 = {
991 .fp_len = 32,
992 .fp_proto = FIB_PROTOCOL_IP4,
993 .fp_addr = {
994 /* 10.10.10.1 */
995 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
996 },
997 };
998 fib_prefix_t pfx_10_10_10_2_s_32 = {
999 .fp_len = 32,
1000 .fp_proto = FIB_PROTOCOL_IP4,
1001 .fp_addr = {
1002 /* 10.10.10.2 */
1003 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
1004 },
1005 };
1006 fib_prefix_t pfx_11_11_11_11_s_32 = {
1007 .fp_len = 32,
1008 .fp_proto = FIB_PROTOCOL_IP4,
1009 .fp_addr = {
1010 /* 11.11.11.11 */
1011 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
1012 },
1013 };
1014 u8 eth_addr[] = {
1015 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
1016 };
Neale Rannsb80c5362016-10-08 13:03:40 +01001017
Neale Ranns3ee44042016-10-03 13:05:48 +01001018 ip46_address_t nh_12_12_12_12 = {
1019 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
1020 };
1021 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001022
1023 /*
1024 * Add a route via an incomplete ADJ. then complete the ADJ
1025 * Expect the route LB is updated to use complete adj type.
1026 */
1027 fei = fib_table_entry_update_one_path(fib_index,
1028 &pfx_11_11_11_11_s_32,
1029 FIB_SOURCE_API,
1030 FIB_ENTRY_FLAG_ATTACHED,
1031 FIB_PROTOCOL_IP4,
1032 &pfx_10_10_10_1_s_32.fp_addr,
1033 tm->hw[0]->sw_if_index,
1034 ~0, // invalid fib index
1035 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001036 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001037 FIB_ROUTE_PATH_FLAG_NONE);
1038
1039 dpo = fib_entry_contribute_ip_forwarding(fei);
1040 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1041 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1042 "11.11.11.11/32 via incomplete adj");
1043
1044 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001045 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001046 &pfx_10_10_10_1_s_32.fp_addr,
1047 tm->hw[0]->sw_if_index);
1048 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1049 adj = adj_get(ai_01);
1050 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1051 "adj is incomplete");
1052 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1053 &adj->sub_type.nbr.next_hop)),
1054 "adj nbr next-hop ok");
1055
Neale Rannsb80c5362016-10-08 13:03:40 +01001056 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1057 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001058 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1059 "adj is complete");
1060 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1061 &adj->sub_type.nbr.next_hop)),
1062 "adj nbr next-hop ok");
1063 ai = fib_entry_get_adj(fei);
1064 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1065
1066 dpo = fib_entry_contribute_ip_forwarding(fei);
1067 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1068 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1069 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001070 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1071 tm->hw[0]->sw_if_index),
1072 "RPF list for adj-fib contains adj");
1073
1074 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001075 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001076 &nh_12_12_12_12,
1077 tm->hw[1]->sw_if_index);
1078 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1079 adj = adj_get(ai_12_12_12_12);
1080 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1081 "adj is incomplete");
1082 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1083 &adj->sub_type.nbr.next_hop)),
1084 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001085 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1086 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001087 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1088 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001089
1090 /*
1091 * add the adj fib
1092 */
Neale Ranns81424992017-05-18 03:03:22 -07001093 fei = fib_table_entry_path_add(fib_index,
1094 &pfx_10_10_10_1_s_32,
1095 FIB_SOURCE_ADJ,
1096 FIB_ENTRY_FLAG_ATTACHED,
1097 FIB_PROTOCOL_IP4,
1098 &pfx_10_10_10_1_s_32.fp_addr,
1099 tm->hw[0]->sw_if_index,
1100 ~0, // invalid fib index
1101 1,
1102 NULL,
1103 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001104 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1105 "Flags set on adj-fib");
1106 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -07001107 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001108
1109 fib_table_entry_path_remove(fib_index,
1110 &pfx_11_11_11_11_s_32,
1111 FIB_SOURCE_API,
1112 FIB_PROTOCOL_IP4,
1113 &pfx_10_10_10_1_s_32.fp_addr,
1114 tm->hw[0]->sw_if_index,
1115 ~0, // invalid fib index
1116 1,
1117 FIB_ROUTE_PATH_FLAG_NONE);
1118
1119 eth_addr[5] = 0xb2;
1120
1121 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001122 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001123 &pfx_10_10_10_2_s_32.fp_addr,
1124 tm->hw[0]->sw_if_index);
1125 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1126 adj = adj_get(ai_02);
1127 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1128 "adj is incomplete");
1129 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1130 &adj->sub_type.nbr.next_hop)),
1131 "adj nbr next-hop ok");
1132
Neale Rannsb80c5362016-10-08 13:03:40 +01001133 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1134 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001135 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1136 "adj is complete");
1137 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1138 &adj->sub_type.nbr.next_hop)),
1139 "adj nbr next-hop ok");
1140 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1141
Neale Ranns81424992017-05-18 03:03:22 -07001142 fib_table_entry_path_add(fib_index,
1143 &pfx_10_10_10_2_s_32,
1144 FIB_SOURCE_ADJ,
1145 FIB_ENTRY_FLAG_ATTACHED,
1146 FIB_PROTOCOL_IP4,
1147 &pfx_10_10_10_2_s_32.fp_addr,
1148 tm->hw[0]->sw_if_index,
1149 ~0, // invalid fib index
1150 1,
1151 NULL,
1152 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001153
1154 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1155 ai = fib_entry_get_adj(fei);
1156 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1157
1158 /*
1159 * +2 adj-fibs, and their non-shared path-lists
1160 */
1161 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001162 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001163 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001164 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001165 fib_entry_pool_size());
1166
1167 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001168 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001169 */
1170 fib_prefix_t pfx_1_1_1_1_s_32 = {
1171 .fp_len = 32,
1172 .fp_proto = FIB_PROTOCOL_IP4,
1173 .fp_addr = {
1174 /* 1.1.1.1/32 */
1175 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1176 },
1177 };
1178
1179 fib_table_entry_path_add(fib_index,
1180 &pfx_1_1_1_1_s_32,
1181 FIB_SOURCE_API,
1182 FIB_ENTRY_FLAG_NONE,
1183 FIB_PROTOCOL_IP4,
1184 &nh_10_10_10_1,
1185 tm->hw[0]->sw_if_index,
1186 ~0, // invalid fib index
1187 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001188 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001189 FIB_ROUTE_PATH_FLAG_NONE);
1190 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1191 ai = fib_entry_get_adj(fei);
1192 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1193
1194 /*
1195 * +1 entry and a shared path-list
1196 */
1197 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001198 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001199 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001200 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001201 fib_entry_pool_size());
1202
1203 /* 1.1.2.0/24 */
1204 fib_prefix_t pfx_1_1_2_0_s_24 = {
1205 .fp_len = 24,
1206 .fp_proto = FIB_PROTOCOL_IP4,
1207 .fp_addr = {
1208 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1209 }
1210 };
1211
1212 fib_table_entry_path_add(fib_index,
1213 &pfx_1_1_2_0_s_24,
1214 FIB_SOURCE_API,
1215 FIB_ENTRY_FLAG_NONE,
1216 FIB_PROTOCOL_IP4,
1217 &nh_10_10_10_1,
1218 tm->hw[0]->sw_if_index,
1219 ~0, // invalid fib index
1220 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001221 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001222 FIB_ROUTE_PATH_FLAG_NONE);
1223 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1224 ai = fib_entry_get_adj(fei);
1225 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1226
1227 /*
1228 * +1 entry only
1229 */
1230 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001231 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001232 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001233 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001234 fib_entry_pool_size());
1235
1236 /*
1237 * modify 1.1.2.0/24 to use multipath.
1238 */
1239 fib_table_entry_path_add(fib_index,
1240 &pfx_1_1_2_0_s_24,
1241 FIB_SOURCE_API,
1242 FIB_ENTRY_FLAG_NONE,
1243 FIB_PROTOCOL_IP4,
1244 &nh_10_10_10_2,
1245 tm->hw[0]->sw_if_index,
1246 ~0, // invalid fib index
1247 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001248 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001249 FIB_ROUTE_PATH_FLAG_NONE);
1250 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1251 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001252 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1253 1, tm->hw[0]->sw_if_index),
1254 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001255
1256 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1257 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1258 FIB_TEST((ai_01 == dpo1->dpoi_index),
1259 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1260 ai_01, dpo1->dpoi_index);
1261
1262 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1263 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1264 FIB_TEST((ai_02 == dpo1->dpoi_index),
1265 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1266
1267 /*
1268 * +1 shared-pathlist
1269 */
1270 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001271 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001272 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001273 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001274 fib_entry_pool_size());
1275
1276 /*
1277 * revert the modify
1278 */
1279 fib_table_entry_path_remove(fib_index,
1280 &pfx_1_1_2_0_s_24,
1281 FIB_SOURCE_API,
1282 FIB_PROTOCOL_IP4,
1283 &nh_10_10_10_2,
1284 tm->hw[0]->sw_if_index,
1285 ~0,
1286 1,
1287 FIB_ROUTE_PATH_FLAG_NONE);
1288 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001289 dpo = fib_entry_contribute_ip_forwarding(fei);
1290 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1291 1, tm->hw[0]->sw_if_index),
1292 "RPF list for 1.1.2.0/24 contains one adj");
1293
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001294 ai = fib_entry_get_adj(fei);
1295 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1296
1297 /*
1298 * +1 shared-pathlist
1299 */
1300 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1301 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001302 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001303 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001304 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001305 fib_entry_pool_size());
1306
1307 /*
1308 * Add 2 recursive routes:
1309 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1310 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1311 */
1312 fib_prefix_t bgp_100_pfx = {
1313 .fp_len = 32,
1314 .fp_proto = FIB_PROTOCOL_IP4,
1315 .fp_addr = {
1316 /* 100.100.100.100/32 */
1317 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1318 },
1319 };
1320 /* via 1.1.1.1 */
1321 ip46_address_t nh_1_1_1_1 = {
1322 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1323 };
1324
Neale Ranns3ee44042016-10-03 13:05:48 +01001325 fei = fib_table_entry_path_add(fib_index,
1326 &bgp_100_pfx,
1327 FIB_SOURCE_API,
1328 FIB_ENTRY_FLAG_NONE,
1329 FIB_PROTOCOL_IP4,
1330 &nh_1_1_1_1,
1331 ~0, // no index provided.
1332 fib_index, // nexthop in same fib as route
1333 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001334 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001335 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001336
Neale Ranns3ee44042016-10-03 13:05:48 +01001337 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1338 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1339 tm->hw[0]->sw_if_index),
1340 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001341
1342 /*
1343 * +1 entry and +1 shared-path-list
1344 */
1345 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1346 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001347 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001348 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001349 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001350 fib_entry_pool_size());
1351
1352 fib_prefix_t bgp_101_pfx = {
1353 .fp_len = 32,
1354 .fp_proto = FIB_PROTOCOL_IP4,
1355 .fp_addr = {
1356 /* 100.100.100.101/32 */
1357 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1358 },
1359 };
1360
1361 fib_table_entry_path_add(fib_index,
1362 &bgp_101_pfx,
1363 FIB_SOURCE_API,
1364 FIB_ENTRY_FLAG_NONE,
1365 FIB_PROTOCOL_IP4,
1366 &nh_1_1_1_1,
1367 ~0, // no index provided.
1368 fib_index, // nexthop in same fib as route
1369 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001370 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001371 FIB_ROUTE_PATH_FLAG_NONE);
1372
Neale Ranns3ee44042016-10-03 13:05:48 +01001373 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1374 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1375 tm->hw[0]->sw_if_index),
1376 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001377
1378 /*
1379 * +1 entry, but the recursive path-list is shared.
1380 */
1381 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1382 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001383 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001384 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001385 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001386 fib_entry_pool_size());
1387
1388 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001389 * An special route; one where the user (me) provides the
1390 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001391 */
1392 fib_prefix_t ex_pfx = {
1393 .fp_len = 32,
1394 .fp_proto = FIB_PROTOCOL_IP4,
1395 .fp_addr = {
1396 /* 4.4.4.4/32 */
1397 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1398 },
1399 };
1400
1401 fib_table_entry_special_add(fib_index,
1402 &ex_pfx,
1403 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001404 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001405 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001406 dpo = fib_entry_contribute_ip_forwarding(fei);
1407 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1408 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1409 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001410
1411 fib_table_entry_special_remove(fib_index,
1412 &ex_pfx,
1413 FIB_SOURCE_SPECIAL);
1414 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1415 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1416 "Exclusive reoute removed");
1417
1418 /*
1419 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1420 * adjacency through which the route will resovle
1421 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001422 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001423
1424 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1425 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001426 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001427 LOOKUP_INPUT_DST_ADDR,
1428 LOOKUP_TABLE_FROM_CONFIG,
1429 &ex_dpo);
1430
1431 fib_table_entry_special_dpo_add(fib_index,
1432 &ex_pfx,
1433 FIB_SOURCE_SPECIAL,
1434 FIB_ENTRY_FLAG_EXCLUSIVE,
1435 &ex_dpo);
1436 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1437 dpo = fib_entry_contribute_ip_forwarding(fei);
1438 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1439 "exclusive remote uses lookup DPO");
1440
Neale Ranns948e00f2016-10-20 13:39:34 +01001441 /*
1442 * update the exclusive to use a different DPO
1443 */
Neale Ranns450cd302016-11-09 17:49:42 +00001444 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001445 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1446 &ex_dpo);
1447 fib_table_entry_special_dpo_update(fib_index,
1448 &ex_pfx,
1449 FIB_SOURCE_SPECIAL,
1450 FIB_ENTRY_FLAG_EXCLUSIVE,
1451 &ex_dpo);
1452 dpo = fib_entry_contribute_ip_forwarding(fei);
1453 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1454 "exclusive remote uses now uses NULL DPO");
1455
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001456 fib_table_entry_special_remove(fib_index,
1457 &ex_pfx,
1458 FIB_SOURCE_SPECIAL);
1459 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1460 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1461 "Exclusive reoute removed");
1462 dpo_reset(&ex_dpo);
1463
1464 /*
1465 * Add a recursive route:
1466 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1467 */
1468 fib_prefix_t bgp_200_pfx = {
1469 .fp_len = 32,
1470 .fp_proto = FIB_PROTOCOL_IP4,
1471 .fp_addr = {
1472 /* 200.200.200.200/32 */
1473 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1474 },
1475 };
1476 /* via 1.1.1.2 */
1477 fib_prefix_t pfx_1_1_1_2_s_32 = {
1478 .fp_len = 32,
1479 .fp_proto = FIB_PROTOCOL_IP4,
1480 .fp_addr = {
1481 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1482 },
1483 };
1484
1485 fib_table_entry_path_add(fib_index,
1486 &bgp_200_pfx,
1487 FIB_SOURCE_API,
1488 FIB_ENTRY_FLAG_NONE,
1489 FIB_PROTOCOL_IP4,
1490 &pfx_1_1_1_2_s_32.fp_addr,
1491 ~0, // no index provided.
1492 fib_index, // nexthop in same fib as route
1493 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001494 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001495 FIB_ROUTE_PATH_FLAG_NONE);
1496
Neale Ranns3ee44042016-10-03 13:05:48 +01001497 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001498
1499 /*
1500 * the adj should be recursive via drop, since the route resolves via
1501 * the default route, which is itself a DROP
1502 */
1503 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1504 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1505 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001506 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1507 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001508
1509 /*
1510 * +2 entry and +1 shared-path-list
1511 */
1512 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1513 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001514 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001515 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001516 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001517 fib_entry_pool_size());
1518
1519 /*
1520 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001521 * The paths are sort by NH first. in this case the the path with greater
1522 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001523 */
1524 fib_prefix_t pfx_1_2_3_4_s_32 = {
1525 .fp_len = 32,
1526 .fp_proto = FIB_PROTOCOL_IP4,
1527 .fp_addr = {
1528 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1529 },
1530 };
1531 fib_table_entry_path_add(fib_index,
1532 &pfx_1_2_3_4_s_32,
1533 FIB_SOURCE_API,
1534 FIB_ENTRY_FLAG_NONE,
1535 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001536 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001537 tm->hw[0]->sw_if_index,
1538 ~0,
1539 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001540 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001541 FIB_ROUTE_PATH_FLAG_NONE);
1542 fei = fib_table_entry_path_add(fib_index,
1543 &pfx_1_2_3_4_s_32,
1544 FIB_SOURCE_API,
1545 FIB_ENTRY_FLAG_NONE,
1546 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001547 &nh_12_12_12_12,
1548 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001549 ~0,
1550 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001551 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001552 FIB_ROUTE_PATH_FLAG_NONE);
1553
1554 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1555 dpo = fib_entry_contribute_ip_forwarding(fei);
1556 lb = load_balance_get(dpo->dpoi_index);
1557 FIB_TEST((lb->lb_n_buckets == 4),
1558 "1.2.3.4/32 LB has %d bucket",
1559 lb->lb_n_buckets);
1560
Neale Ranns3ee44042016-10-03 13:05:48 +01001561 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1562 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1563 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1564 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001565
Neale Ranns3ee44042016-10-03 13:05:48 +01001566 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1567 tm->hw[0]->sw_if_index,
1568 tm->hw[1]->sw_if_index),
1569 "RPF list for 1.2.3.4/32 contains both adjs");
1570
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001571
1572 /*
1573 * Unequal Cost load-balance. 4:1 ratio.
1574 * fits in a 16 bucket LB with ratio 13:3
1575 */
1576 fib_prefix_t pfx_1_2_3_5_s_32 = {
1577 .fp_len = 32,
1578 .fp_proto = FIB_PROTOCOL_IP4,
1579 .fp_addr = {
1580 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1581 },
1582 };
1583 fib_table_entry_path_add(fib_index,
1584 &pfx_1_2_3_5_s_32,
1585 FIB_SOURCE_API,
1586 FIB_ENTRY_FLAG_NONE,
1587 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001588 &nh_12_12_12_12,
1589 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001590 ~0,
1591 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001592 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001593 FIB_ROUTE_PATH_FLAG_NONE);
1594 fei = fib_table_entry_path_add(fib_index,
1595 &pfx_1_2_3_5_s_32,
1596 FIB_SOURCE_API,
1597 FIB_ENTRY_FLAG_NONE,
1598 FIB_PROTOCOL_IP4,
1599 &nh_10_10_10_1,
1600 tm->hw[0]->sw_if_index,
1601 ~0,
1602 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001603 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001604 FIB_ROUTE_PATH_FLAG_NONE);
1605
1606 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1607 dpo = fib_entry_contribute_ip_forwarding(fei);
1608 lb = load_balance_get(dpo->dpoi_index);
1609 FIB_TEST((lb->lb_n_buckets == 16),
1610 "1.2.3.5/32 LB has %d bucket",
1611 lb->lb_n_buckets);
1612
1613 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1614 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1615 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1616 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1617 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1618 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1619 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1620 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1621 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1622 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1623 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1624 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1625 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001626 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1627 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1628 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1629
1630 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1631 tm->hw[0]->sw_if_index,
1632 tm->hw[1]->sw_if_index),
1633 "RPF list for 1.2.3.4/32 contains both adjs");
1634
1635 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001636 * Test UCMP with a large weight skew - this produces load-balance objects with large
1637 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1638 * laso testing the LB in placce modify code when number of buckets is large.
1639 */
1640 fib_prefix_t pfx_6_6_6_6_s_32 = {
1641 .fp_len = 32,
1642 .fp_proto = FIB_PROTOCOL_IP4,
1643 .fp_addr = {
1644 /* 1.1.1.1/32 */
1645 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1646 },
1647 };
Neale Ranns81424992017-05-18 03:03:22 -07001648 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001649 .type = FT_LB_ADJ,
1650 .adj = {
1651 .adj = ai_01,
1652 },
1653 };
Neale Ranns81424992017-05-18 03:03:22 -07001654 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001655 .type = FT_LB_ADJ,
1656 .adj = {
1657 .adj = ai_02,
1658 },
1659 };
1660 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1661 .type = FT_LB_ADJ,
1662 .adj = {
1663 .adj = ai_12_12_12_12,
1664 },
1665 };
1666 fib_table_entry_update_one_path(fib_index,
1667 &pfx_6_6_6_6_s_32,
1668 FIB_SOURCE_API,
1669 FIB_ENTRY_FLAG_NONE,
1670 FIB_PROTOCOL_IP4,
1671 &nh_10_10_10_1,
1672 tm->hw[0]->sw_if_index,
1673 ~0, // invalid fib index
1674 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001675 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001676 FIB_ROUTE_PATH_FLAG_NONE);
1677
1678 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1679 FIB_TEST(fib_test_validate_entry(fei,
1680 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1681 1,
Neale Ranns81424992017-05-18 03:03:22 -07001682 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001683 "6.6.6.6/32 via 10.10.10.1");
1684
1685 fib_table_entry_path_add(fib_index,
1686 &pfx_6_6_6_6_s_32,
1687 FIB_SOURCE_API,
1688 FIB_ENTRY_FLAG_NONE,
1689 FIB_PROTOCOL_IP4,
1690 &nh_10_10_10_2,
1691 tm->hw[0]->sw_if_index,
1692 ~0, // invalid fib index
1693 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001694 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001695 FIB_ROUTE_PATH_FLAG_NONE);
1696
1697 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1698 FIB_TEST(fib_test_validate_entry(fei,
1699 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1700 64,
Neale Ranns81424992017-05-18 03:03:22 -07001701 &ip_o_10_10_10_2,
1702 &ip_o_10_10_10_2,
1703 &ip_o_10_10_10_2,
1704 &ip_o_10_10_10_2,
1705 &ip_o_10_10_10_2,
1706 &ip_o_10_10_10_2,
1707 &ip_o_10_10_10_2,
1708 &ip_o_10_10_10_2,
1709 &ip_o_10_10_10_2,
1710 &ip_o_10_10_10_2,
1711 &ip_o_10_10_10_2,
1712 &ip_o_10_10_10_2,
1713 &ip_o_10_10_10_2,
1714 &ip_o_10_10_10_2,
1715 &ip_o_10_10_10_2,
1716 &ip_o_10_10_10_2,
1717 &ip_o_10_10_10_2,
1718 &ip_o_10_10_10_2,
1719 &ip_o_10_10_10_2,
1720 &ip_o_10_10_10_2,
1721 &ip_o_10_10_10_2,
1722 &ip_o_10_10_10_2,
1723 &ip_o_10_10_10_2,
1724 &ip_o_10_10_10_2,
1725 &ip_o_10_10_10_2,
1726 &ip_o_10_10_10_2,
1727 &ip_o_10_10_10_2,
1728 &ip_o_10_10_10_2,
1729 &ip_o_10_10_10_2,
1730 &ip_o_10_10_10_2,
1731 &ip_o_10_10_10_2,
1732 &ip_o_10_10_10_2,
1733 &ip_o_10_10_10_2,
1734 &ip_o_10_10_10_2,
1735 &ip_o_10_10_10_2,
1736 &ip_o_10_10_10_2,
1737 &ip_o_10_10_10_2,
1738 &ip_o_10_10_10_2,
1739 &ip_o_10_10_10_2,
1740 &ip_o_10_10_10_2,
1741 &ip_o_10_10_10_2,
1742 &ip_o_10_10_10_2,
1743 &ip_o_10_10_10_2,
1744 &ip_o_10_10_10_2,
1745 &ip_o_10_10_10_2,
1746 &ip_o_10_10_10_2,
1747 &ip_o_10_10_10_2,
1748 &ip_o_10_10_10_2,
1749 &ip_o_10_10_10_2,
1750 &ip_o_10_10_10_2,
1751 &ip_o_10_10_10_2,
1752 &ip_o_10_10_10_2,
1753 &ip_o_10_10_10_2,
1754 &ip_o_10_10_10_2,
1755 &ip_o_10_10_10_2,
1756 &ip_o_10_10_10_2,
1757 &ip_o_10_10_10_2,
1758 &ip_o_10_10_10_2,
1759 &ip_o_10_10_10_2,
1760 &ip_o_10_10_10_2,
1761 &ip_o_10_10_10_2,
1762 &ip_o_10_10_10_2,
1763 &ip_o_10_10_10_2,
1764 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001765 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1766
1767 fib_table_entry_path_add(fib_index,
1768 &pfx_6_6_6_6_s_32,
1769 FIB_SOURCE_API,
1770 FIB_ENTRY_FLAG_NONE,
1771 FIB_PROTOCOL_IP4,
1772 &nh_12_12_12_12,
1773 tm->hw[1]->sw_if_index,
1774 ~0, // invalid fib index
1775 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001776 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001777 FIB_ROUTE_PATH_FLAG_NONE);
1778
1779 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1780 FIB_TEST(fib_test_validate_entry(fei,
1781 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1782 128,
Neale Ranns81424992017-05-18 03:03:22 -07001783 &ip_o_10_10_10_1,
1784 &ip_o_10_10_10_2,
1785 &ip_o_10_10_10_2,
1786 &ip_o_10_10_10_2,
1787 &ip_o_10_10_10_2,
1788 &ip_o_10_10_10_2,
1789 &ip_o_10_10_10_2,
1790 &ip_o_10_10_10_2,
1791 &ip_o_10_10_10_2,
1792 &ip_o_10_10_10_2,
1793 &ip_o_10_10_10_2,
1794 &ip_o_10_10_10_2,
1795 &ip_o_10_10_10_2,
1796 &ip_o_10_10_10_2,
1797 &ip_o_10_10_10_2,
1798 &ip_o_10_10_10_2,
1799 &ip_o_10_10_10_2,
1800 &ip_o_10_10_10_2,
1801 &ip_o_10_10_10_2,
1802 &ip_o_10_10_10_2,
1803 &ip_o_10_10_10_2,
1804 &ip_o_10_10_10_2,
1805 &ip_o_10_10_10_2,
1806 &ip_o_10_10_10_2,
1807 &ip_o_10_10_10_2,
1808 &ip_o_10_10_10_2,
1809 &ip_o_10_10_10_2,
1810 &ip_o_10_10_10_2,
1811 &ip_o_10_10_10_2,
1812 &ip_o_10_10_10_2,
1813 &ip_o_10_10_10_2,
1814 &ip_o_10_10_10_2,
1815 &ip_o_10_10_10_2,
1816 &ip_o_10_10_10_2,
1817 &ip_o_10_10_10_2,
1818 &ip_o_10_10_10_2,
1819 &ip_o_10_10_10_2,
1820 &ip_o_10_10_10_2,
1821 &ip_o_10_10_10_2,
1822 &ip_o_10_10_10_2,
1823 &ip_o_10_10_10_2,
1824 &ip_o_10_10_10_2,
1825 &ip_o_10_10_10_2,
1826 &ip_o_10_10_10_2,
1827 &ip_o_10_10_10_2,
1828 &ip_o_10_10_10_2,
1829 &ip_o_10_10_10_2,
1830 &ip_o_10_10_10_2,
1831 &ip_o_10_10_10_2,
1832 &ip_o_10_10_10_2,
1833 &ip_o_10_10_10_2,
1834 &ip_o_10_10_10_2,
1835 &ip_o_10_10_10_2,
1836 &ip_o_10_10_10_2,
1837 &ip_o_10_10_10_2,
1838 &ip_o_10_10_10_2,
1839 &ip_o_10_10_10_2,
1840 &ip_o_10_10_10_2,
1841 &ip_o_10_10_10_2,
1842 &ip_o_10_10_10_2,
1843 &ip_o_10_10_10_2,
1844 &ip_o_10_10_10_2,
1845 &ip_o_10_10_10_2,
1846 &ip_o_10_10_10_2,
1847 &ip_o_10_10_10_2,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001848 &ip_6_6_6_6_o_12_12_12_12,
1849 &ip_6_6_6_6_o_12_12_12_12,
1850 &ip_6_6_6_6_o_12_12_12_12,
1851 &ip_6_6_6_6_o_12_12_12_12,
1852 &ip_6_6_6_6_o_12_12_12_12,
1853 &ip_6_6_6_6_o_12_12_12_12,
1854 &ip_6_6_6_6_o_12_12_12_12,
1855 &ip_6_6_6_6_o_12_12_12_12,
1856 &ip_6_6_6_6_o_12_12_12_12,
1857 &ip_6_6_6_6_o_12_12_12_12,
1858 &ip_6_6_6_6_o_12_12_12_12,
1859 &ip_6_6_6_6_o_12_12_12_12,
1860 &ip_6_6_6_6_o_12_12_12_12,
1861 &ip_6_6_6_6_o_12_12_12_12,
1862 &ip_6_6_6_6_o_12_12_12_12,
1863 &ip_6_6_6_6_o_12_12_12_12,
1864 &ip_6_6_6_6_o_12_12_12_12,
1865 &ip_6_6_6_6_o_12_12_12_12,
1866 &ip_6_6_6_6_o_12_12_12_12,
1867 &ip_6_6_6_6_o_12_12_12_12,
1868 &ip_6_6_6_6_o_12_12_12_12,
1869 &ip_6_6_6_6_o_12_12_12_12,
1870 &ip_6_6_6_6_o_12_12_12_12,
1871 &ip_6_6_6_6_o_12_12_12_12,
1872 &ip_6_6_6_6_o_12_12_12_12,
1873 &ip_6_6_6_6_o_12_12_12_12,
1874 &ip_6_6_6_6_o_12_12_12_12,
1875 &ip_6_6_6_6_o_12_12_12_12,
1876 &ip_6_6_6_6_o_12_12_12_12,
1877 &ip_6_6_6_6_o_12_12_12_12,
1878 &ip_6_6_6_6_o_12_12_12_12,
1879 &ip_6_6_6_6_o_12_12_12_12,
1880 &ip_6_6_6_6_o_12_12_12_12,
1881 &ip_6_6_6_6_o_12_12_12_12,
1882 &ip_6_6_6_6_o_12_12_12_12,
1883 &ip_6_6_6_6_o_12_12_12_12,
1884 &ip_6_6_6_6_o_12_12_12_12,
1885 &ip_6_6_6_6_o_12_12_12_12,
1886 &ip_6_6_6_6_o_12_12_12_12,
1887 &ip_6_6_6_6_o_12_12_12_12,
1888 &ip_6_6_6_6_o_12_12_12_12,
1889 &ip_6_6_6_6_o_12_12_12_12,
1890 &ip_6_6_6_6_o_12_12_12_12,
1891 &ip_6_6_6_6_o_12_12_12_12,
1892 &ip_6_6_6_6_o_12_12_12_12,
1893 &ip_6_6_6_6_o_12_12_12_12,
1894 &ip_6_6_6_6_o_12_12_12_12,
1895 &ip_6_6_6_6_o_12_12_12_12,
1896 &ip_6_6_6_6_o_12_12_12_12,
1897 &ip_6_6_6_6_o_12_12_12_12,
1898 &ip_6_6_6_6_o_12_12_12_12,
1899 &ip_6_6_6_6_o_12_12_12_12,
1900 &ip_6_6_6_6_o_12_12_12_12,
1901 &ip_6_6_6_6_o_12_12_12_12,
1902 &ip_6_6_6_6_o_12_12_12_12,
1903 &ip_6_6_6_6_o_12_12_12_12,
1904 &ip_6_6_6_6_o_12_12_12_12,
1905 &ip_6_6_6_6_o_12_12_12_12,
1906 &ip_6_6_6_6_o_12_12_12_12,
1907 &ip_6_6_6_6_o_12_12_12_12,
1908 &ip_6_6_6_6_o_12_12_12_12,
1909 &ip_6_6_6_6_o_12_12_12_12,
1910 &ip_6_6_6_6_o_12_12_12_12),
1911 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1912
1913 fib_table_entry_path_remove(fib_index,
1914 &pfx_6_6_6_6_s_32,
1915 FIB_SOURCE_API,
1916 FIB_PROTOCOL_IP4,
1917 &nh_12_12_12_12,
1918 tm->hw[1]->sw_if_index,
1919 ~0, // invalid fib index
1920 100,
1921 FIB_ROUTE_PATH_FLAG_NONE);
1922
1923 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1924 FIB_TEST(fib_test_validate_entry(fei,
1925 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1926 64,
Neale Ranns81424992017-05-18 03:03:22 -07001927 &ip_o_10_10_10_2,
1928 &ip_o_10_10_10_2,
1929 &ip_o_10_10_10_2,
1930 &ip_o_10_10_10_2,
1931 &ip_o_10_10_10_2,
1932 &ip_o_10_10_10_2,
1933 &ip_o_10_10_10_2,
1934 &ip_o_10_10_10_2,
1935 &ip_o_10_10_10_2,
1936 &ip_o_10_10_10_2,
1937 &ip_o_10_10_10_2,
1938 &ip_o_10_10_10_2,
1939 &ip_o_10_10_10_2,
1940 &ip_o_10_10_10_2,
1941 &ip_o_10_10_10_2,
1942 &ip_o_10_10_10_2,
1943 &ip_o_10_10_10_2,
1944 &ip_o_10_10_10_2,
1945 &ip_o_10_10_10_2,
1946 &ip_o_10_10_10_2,
1947 &ip_o_10_10_10_2,
1948 &ip_o_10_10_10_2,
1949 &ip_o_10_10_10_2,
1950 &ip_o_10_10_10_2,
1951 &ip_o_10_10_10_2,
1952 &ip_o_10_10_10_2,
1953 &ip_o_10_10_10_2,
1954 &ip_o_10_10_10_2,
1955 &ip_o_10_10_10_2,
1956 &ip_o_10_10_10_2,
1957 &ip_o_10_10_10_2,
1958 &ip_o_10_10_10_2,
1959 &ip_o_10_10_10_2,
1960 &ip_o_10_10_10_2,
1961 &ip_o_10_10_10_2,
1962 &ip_o_10_10_10_2,
1963 &ip_o_10_10_10_2,
1964 &ip_o_10_10_10_2,
1965 &ip_o_10_10_10_2,
1966 &ip_o_10_10_10_2,
1967 &ip_o_10_10_10_2,
1968 &ip_o_10_10_10_2,
1969 &ip_o_10_10_10_2,
1970 &ip_o_10_10_10_2,
1971 &ip_o_10_10_10_2,
1972 &ip_o_10_10_10_2,
1973 &ip_o_10_10_10_2,
1974 &ip_o_10_10_10_2,
1975 &ip_o_10_10_10_2,
1976 &ip_o_10_10_10_2,
1977 &ip_o_10_10_10_2,
1978 &ip_o_10_10_10_2,
1979 &ip_o_10_10_10_2,
1980 &ip_o_10_10_10_2,
1981 &ip_o_10_10_10_2,
1982 &ip_o_10_10_10_2,
1983 &ip_o_10_10_10_2,
1984 &ip_o_10_10_10_2,
1985 &ip_o_10_10_10_2,
1986 &ip_o_10_10_10_2,
1987 &ip_o_10_10_10_2,
1988 &ip_o_10_10_10_2,
1989 &ip_o_10_10_10_2,
1990 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001991 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1992
1993 fib_table_entry_path_remove(fib_index,
1994 &pfx_6_6_6_6_s_32,
1995 FIB_SOURCE_API,
1996 FIB_PROTOCOL_IP4,
1997 &nh_10_10_10_2,
1998 tm->hw[0]->sw_if_index,
1999 ~0, // invalid fib index
2000 100,
2001 FIB_ROUTE_PATH_FLAG_NONE);
2002
2003 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
2004 FIB_TEST(fib_test_validate_entry(fei,
2005 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
2006 1,
Neale Ranns81424992017-05-18 03:03:22 -07002007 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00002008 "6.6.6.6/32 via 10.10.10.1");
2009
2010 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
2011
2012 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01002013 * A recursive via the two unequal cost entries
2014 */
2015 fib_prefix_t bgp_44_s_32 = {
2016 .fp_len = 32,
2017 .fp_proto = FIB_PROTOCOL_IP4,
2018 .fp_addr = {
2019 /* 200.200.200.201/32 */
2020 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
2021 },
2022 };
2023 fei = fib_table_entry_path_add(fib_index,
2024 &bgp_44_s_32,
2025 FIB_SOURCE_API,
2026 FIB_ENTRY_FLAG_NONE,
2027 FIB_PROTOCOL_IP4,
2028 &pfx_1_2_3_4_s_32.fp_addr,
2029 ~0,
2030 fib_index,
2031 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002032 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002033 FIB_ROUTE_PATH_FLAG_NONE);
2034 fei = fib_table_entry_path_add(fib_index,
2035 &bgp_44_s_32,
2036 FIB_SOURCE_API,
2037 FIB_ENTRY_FLAG_NONE,
2038 FIB_PROTOCOL_IP4,
2039 &pfx_1_2_3_5_s_32.fp_addr,
2040 ~0,
2041 fib_index,
2042 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002043 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002044 FIB_ROUTE_PATH_FLAG_NONE);
2045
2046 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2047 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2048 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2049 tm->hw[0]->sw_if_index,
2050 tm->hw[1]->sw_if_index),
2051 "RPF list for 1.2.3.4/32 contains both adjs");
2052
2053 /*
2054 * test the uRPF check functions
2055 */
Neale Ranns948e00f2016-10-20 13:39:34 +01002056 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01002057 index_t urpfi;
2058
2059 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2060 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2061
2062 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2063 "uRPF check for 68.68.68.68/32 on %d OK",
2064 tm->hw[0]->sw_if_index);
2065 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2066 "uRPF check for 68.68.68.68/32 on %d OK",
2067 tm->hw[1]->sw_if_index);
2068 FIB_TEST(!fib_urpf_check(urpfi, 99),
2069 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2070 99);
2071 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002072
2073 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002074 &bgp_44_s_32,
2075 FIB_SOURCE_API);
2076 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002077 &pfx_1_2_3_5_s_32,
2078 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002079 fib_table_entry_delete(fib_index,
2080 &pfx_1_2_3_4_s_32,
2081 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002082
2083 /*
2084 * Add a recursive route:
2085 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2086 */
2087 fib_prefix_t bgp_201_pfx = {
2088 .fp_len = 32,
2089 .fp_proto = FIB_PROTOCOL_IP4,
2090 .fp_addr = {
2091 /* 200.200.200.201/32 */
2092 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2093 },
2094 };
2095 /* via 1.1.1.200 */
2096 fib_prefix_t pfx_1_1_1_200_s_32 = {
2097 .fp_len = 32,
2098 .fp_proto = FIB_PROTOCOL_IP4,
2099 .fp_addr = {
2100 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2101 },
2102 };
2103
2104 fib_table_entry_path_add(fib_index,
2105 &bgp_201_pfx,
2106 FIB_SOURCE_API,
2107 FIB_ENTRY_FLAG_NONE,
2108 FIB_PROTOCOL_IP4,
2109 &pfx_1_1_1_200_s_32.fp_addr,
2110 ~0, // no index provided.
2111 fib_index, // nexthop in same fib as route
2112 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002113 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002114 FIB_ROUTE_PATH_FLAG_NONE);
2115
Neale Ranns3ee44042016-10-03 13:05:48 +01002116 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002117
2118 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2119 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2120 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002121 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2122 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002123
2124 /*
2125 * +2 entry (BGP & RR) and +1 shared-path-list
2126 */
2127 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2128 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002129 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002130 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002131 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002132 fib_entry_pool_size());
2133
2134 /*
2135 * insert a route that covers the missing 1.1.1.2/32. we epxect
2136 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2137 */
2138 fib_prefix_t pfx_1_1_1_0_s_24 = {
2139 .fp_len = 24,
2140 .fp_proto = FIB_PROTOCOL_IP4,
2141 .fp_addr = {
2142 /* 1.1.1.0/24 */
2143 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2144 },
2145 };
2146
2147 fib_table_entry_path_add(fib_index,
2148 &pfx_1_1_1_0_s_24,
2149 FIB_SOURCE_API,
2150 FIB_ENTRY_FLAG_NONE,
2151 FIB_PROTOCOL_IP4,
2152 &nh_10_10_10_1,
2153 tm->hw[0]->sw_if_index,
2154 ~0, // invalid fib index
2155 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002156 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002157 FIB_ROUTE_PATH_FLAG_NONE);
2158 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2159 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2160 ai = fib_entry_get_adj(fei);
2161 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2162 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2163 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2164 ai = fib_entry_get_adj(fei);
2165 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2166 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2167 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2168 ai = fib_entry_get_adj(fei);
2169 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2170
2171 /*
2172 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2173 */
2174 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2175 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002176 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002177 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002178 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002179 fib_entry_pool_size());
2180
2181 /*
2182 * the recursive adj for 200.200.200.200 should be updated.
2183 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002184 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2185 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2186 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2187 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2188 tm->hw[0]->sw_if_index),
2189 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002190
2191 /*
2192 * insert a more specific route than 1.1.1.0/24 that also covers the
2193 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2194 * 200.200.200.200 to resolve through it.
2195 */
2196 fib_prefix_t pfx_1_1_1_0_s_28 = {
2197 .fp_len = 28,
2198 .fp_proto = FIB_PROTOCOL_IP4,
2199 .fp_addr = {
2200 /* 1.1.1.0/24 */
2201 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2202 },
2203 };
2204
2205 fib_table_entry_path_add(fib_index,
2206 &pfx_1_1_1_0_s_28,
2207 FIB_SOURCE_API,
2208 FIB_ENTRY_FLAG_NONE,
2209 FIB_PROTOCOL_IP4,
2210 &nh_10_10_10_2,
2211 tm->hw[0]->sw_if_index,
2212 ~0, // invalid fib index
2213 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002214 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002215 FIB_ROUTE_PATH_FLAG_NONE);
2216 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2217 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2218 ai = fib_entry_get_adj(fei);
2219 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2220
2221 /*
2222 * +1 entry. +1 shared path-list
2223 */
2224 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2225 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002226 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002227 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002228 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002229 fib_entry_pool_size());
2230
2231 /*
2232 * the recursive adj for 200.200.200.200 should be updated.
2233 * 200.200.200.201 remains unchanged.
2234 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002235 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2236 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002237
2238 /*
2239 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2240 */
2241 fib_table_entry_path_remove(fib_index,
2242 &pfx_1_1_1_0_s_28,
2243 FIB_SOURCE_API,
2244 FIB_PROTOCOL_IP4,
2245 &nh_10_10_10_2,
2246 tm->hw[0]->sw_if_index,
2247 ~0,
2248 1,
2249 FIB_ROUTE_PATH_FLAG_NONE);
2250 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2251 FIB_NODE_INDEX_INVALID),
2252 "1.1.1.0/28 removed");
2253 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2254 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2255 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002256 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2257 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002258
2259 /*
2260 * -1 entry. -1 shared path-list
2261 */
2262 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2263 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002264 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002265 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002266 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002267 fib_entry_pool_size());
2268
2269 /*
2270 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2271 */
2272 fib_table_entry_path_remove(fib_index,
2273 &pfx_1_1_1_0_s_24,
2274 FIB_SOURCE_API,
2275 FIB_PROTOCOL_IP4,
2276 &nh_10_10_10_1,
2277 tm->hw[0]->sw_if_index,
2278 ~0,
2279 1,
2280 FIB_ROUTE_PATH_FLAG_NONE);
2281 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2282 FIB_NODE_INDEX_INVALID),
2283 "1.1.1.0/24 removed");
2284
2285 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2286 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2287 "1.1.1.2/32 route is DROP");
2288 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2289 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2290 "1.1.1.200/32 route is DROP");
2291
Neale Ranns3ee44042016-10-03 13:05:48 +01002292 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2293 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002294
2295 /*
2296 * -1 entry
2297 */
2298 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2299 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002300 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002301 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002302 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002303 fib_entry_pool_size());
2304
2305 /*
2306 * insert the missing 1.1.1.2/32
2307 */
2308 fei = fib_table_entry_path_add(fib_index,
2309 &pfx_1_1_1_2_s_32,
2310 FIB_SOURCE_API,
2311 FIB_ENTRY_FLAG_NONE,
2312 FIB_PROTOCOL_IP4,
2313 &nh_10_10_10_1,
2314 tm->hw[0]->sw_if_index,
2315 ~0, // invalid fib index
2316 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002317 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002318 FIB_ROUTE_PATH_FLAG_NONE);
2319 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2320 ai = fib_entry_get_adj(fei);
2321 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2322
Neale Ranns3ee44042016-10-03 13:05:48 +01002323 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2324 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002325
2326 /*
2327 * no change. 1.1.1.2/32 was already there RR sourced.
2328 */
2329 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2330 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002331 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002332 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002333 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002334 fib_entry_pool_size());
2335
2336 /*
2337 * remove 200.200.200.201/32 which does not have a valid via FIB
2338 */
2339 fib_table_entry_path_remove(fib_index,
2340 &bgp_201_pfx,
2341 FIB_SOURCE_API,
2342 FIB_PROTOCOL_IP4,
2343 &pfx_1_1_1_200_s_32.fp_addr,
2344 ~0, // no index provided.
2345 fib_index,
2346 1,
2347 FIB_ROUTE_PATH_FLAG_NONE);
2348
2349 /*
2350 * -2 entries (BGP and RR). -1 shared path-list;
2351 */
2352 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2353 FIB_NODE_INDEX_INVALID),
2354 "200.200.200.201/32 removed");
2355 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2356 FIB_NODE_INDEX_INVALID),
2357 "1.1.1.200/32 removed");
2358
2359 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2360 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002361 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002362 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002363 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002364 fib_entry_pool_size());
2365
2366 /*
2367 * remove 200.200.200.200/32 which does have a valid via FIB
2368 */
2369 fib_table_entry_path_remove(fib_index,
2370 &bgp_200_pfx,
2371 FIB_SOURCE_API,
2372 FIB_PROTOCOL_IP4,
2373 &pfx_1_1_1_2_s_32.fp_addr,
2374 ~0, // no index provided.
2375 fib_index,
2376 1,
2377 FIB_ROUTE_PATH_FLAG_NONE);
2378
2379 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2380 FIB_NODE_INDEX_INVALID),
2381 "200.200.200.200/32 removed");
2382 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2383 FIB_NODE_INDEX_INVALID),
2384 "1.1.1.2/32 still present");
2385
2386 /*
2387 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2388 */
2389 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2390 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002391 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002392 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002393 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002394 fib_entry_pool_size());
2395
2396 /*
2397 * A recursive prefix that has a 2 path load-balance.
2398 * It also shares a next-hop with other BGP prefixes and hence
2399 * test the ref counting of RR sourced prefixes and 2 level LB.
2400 */
2401 const fib_prefix_t bgp_102 = {
2402 .fp_len = 32,
2403 .fp_proto = FIB_PROTOCOL_IP4,
2404 .fp_addr = {
2405 /* 100.100.100.101/32 */
2406 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2407 },
2408 };
2409 fib_table_entry_path_add(fib_index,
2410 &bgp_102,
2411 FIB_SOURCE_API,
2412 FIB_ENTRY_FLAG_NONE,
2413 FIB_PROTOCOL_IP4,
2414 &pfx_1_1_1_1_s_32.fp_addr,
2415 ~0, // no index provided.
2416 fib_index, // same as route
2417 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002418 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002419 FIB_ROUTE_PATH_FLAG_NONE);
2420 fib_table_entry_path_add(fib_index,
2421 &bgp_102,
2422 FIB_SOURCE_API,
2423 FIB_ENTRY_FLAG_NONE,
2424 FIB_PROTOCOL_IP4,
2425 &pfx_1_1_1_2_s_32.fp_addr,
2426 ~0, // no index provided.
2427 fib_index, // same as route's FIB
2428 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002429 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002430 FIB_ROUTE_PATH_FLAG_NONE);
2431 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2432 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2433 dpo = fib_entry_contribute_ip_forwarding(fei);
2434
2435 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2436 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2437 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2438 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2439
2440 lb = load_balance_get(dpo->dpoi_index);
2441 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2442 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2443 "First via 10.10.10.1");
2444 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2445 "Second via 10.10.10.1");
2446
2447 fib_table_entry_path_remove(fib_index,
2448 &bgp_102,
2449 FIB_SOURCE_API,
2450 FIB_PROTOCOL_IP4,
2451 &pfx_1_1_1_1_s_32.fp_addr,
2452 ~0, // no index provided.
2453 fib_index, // same as route's FIB
2454 1,
2455 FIB_ROUTE_PATH_FLAG_NONE);
2456 fib_table_entry_path_remove(fib_index,
2457 &bgp_102,
2458 FIB_SOURCE_API,
2459 FIB_PROTOCOL_IP4,
2460 &pfx_1_1_1_2_s_32.fp_addr,
2461 ~0, // no index provided.
2462 fib_index, // same as route's FIB
2463 1,
2464 FIB_ROUTE_PATH_FLAG_NONE);
2465 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2466 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2467
2468 /*
2469 * remove the remaining recursives
2470 */
2471 fib_table_entry_path_remove(fib_index,
2472 &bgp_100_pfx,
2473 FIB_SOURCE_API,
2474 FIB_PROTOCOL_IP4,
2475 &pfx_1_1_1_1_s_32.fp_addr,
2476 ~0, // no index provided.
2477 fib_index, // same as route's FIB
2478 1,
2479 FIB_ROUTE_PATH_FLAG_NONE);
2480 fib_table_entry_path_remove(fib_index,
2481 &bgp_101_pfx,
2482 FIB_SOURCE_API,
2483 FIB_PROTOCOL_IP4,
2484 &pfx_1_1_1_1_s_32.fp_addr,
2485 ~0, // no index provided.
2486 fib_index, // same as route's FIB
2487 1,
2488 FIB_ROUTE_PATH_FLAG_NONE);
2489 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2490 FIB_NODE_INDEX_INVALID),
2491 "100.100.100.100/32 removed");
2492 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2493 FIB_NODE_INDEX_INVALID),
2494 "100.100.100.101/32 removed");
2495
2496 /*
2497 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2498 */
2499 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2500 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002501 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002502 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002503 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002504 fib_entry_pool_size());
2505
2506 /*
2507 * Add a recursive route via a connected cover, using an adj-fib that does exist
2508 */
2509 fib_table_entry_path_add(fib_index,
2510 &bgp_200_pfx,
2511 FIB_SOURCE_API,
2512 FIB_ENTRY_FLAG_NONE,
2513 FIB_PROTOCOL_IP4,
2514 &nh_10_10_10_1,
2515 ~0, // no index provided.
2516 fib_index, // Same as route's FIB
2517 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002518 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002519 FIB_ROUTE_PATH_FLAG_NONE);
2520
2521 /*
2522 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2523 */
2524 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2525 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002526 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002527 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002528 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002529 fib_entry_pool_size());
2530
2531 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2532 dpo = fib_entry_contribute_ip_forwarding(fei);
2533
2534 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2535 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2536
2537 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2538 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2539
2540 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2541 "Flags set on RR via existing attached");
2542
2543 /*
2544 * Add a recursive route via a connected cover, using and adj-fib that does
2545 * not exist
2546 */
2547 ip46_address_t nh_10_10_10_3 = {
2548 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2549 };
2550 fib_prefix_t pfx_10_10_10_3 = {
2551 .fp_len = 32,
2552 .fp_proto = FIB_PROTOCOL_IP4,
2553 .fp_addr = nh_10_10_10_3,
2554 };
2555
2556 fib_table_entry_path_add(fib_index,
2557 &bgp_201_pfx,
2558 FIB_SOURCE_API,
2559 FIB_ENTRY_FLAG_NONE,
2560 FIB_PROTOCOL_IP4,
2561 &nh_10_10_10_3,
2562 ~0, // no index provided.
2563 fib_index,
2564 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002565 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002566 FIB_ROUTE_PATH_FLAG_NONE);
2567
2568 /*
2569 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2570 * one unshared non-recursive via 10.10.10.3
2571 */
2572 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2573 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002574 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002575 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002576 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002577 fib_entry_pool_size());
2578
2579 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002580 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002581 &nh_10_10_10_3,
2582 tm->hw[0]->sw_if_index);
2583
2584 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2585 dpo = fib_entry_contribute_ip_forwarding(fei);
2586 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2587 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2588
2589 ai = fib_entry_get_adj(fei);
2590 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2591 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2592 fib_entry_get_flags(fei)),
2593 "Flags set on RR via non-existing attached");
2594
2595 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2596 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2597
2598 adj_unlock(ai_03);
2599
2600 /*
2601 * remove the recursives
2602 */
2603 fib_table_entry_path_remove(fib_index,
2604 &bgp_200_pfx,
2605 FIB_SOURCE_API,
2606 FIB_PROTOCOL_IP4,
2607 &nh_10_10_10_1,
2608 ~0, // no index provided.
2609 fib_index, // same as route's FIB
2610 1,
2611 FIB_ROUTE_PATH_FLAG_NONE);
2612 fib_table_entry_path_remove(fib_index,
2613 &bgp_201_pfx,
2614 FIB_SOURCE_API,
2615 FIB_PROTOCOL_IP4,
2616 &nh_10_10_10_3,
2617 ~0, // no index provided.
2618 fib_index, // same as route's FIB
2619 1,
2620 FIB_ROUTE_PATH_FLAG_NONE);
2621
2622 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2623 FIB_NODE_INDEX_INVALID),
2624 "200.200.200.201/32 removed");
2625 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2626 FIB_NODE_INDEX_INVALID),
2627 "200.200.200.200/32 removed");
2628 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2629 FIB_NODE_INDEX_INVALID),
2630 "10.10.10.3/32 removed");
2631
2632 /*
2633 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2634 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2635 */
2636 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2637 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002638 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002639 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002640 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002641 fib_entry_pool_size());
2642
2643
2644 /*
2645 * RECURSION LOOPS
2646 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2647 */
2648 fib_prefix_t pfx_5_5_5_5_s_32 = {
2649 .fp_len = 32,
2650 .fp_proto = FIB_PROTOCOL_IP4,
2651 .fp_addr = {
2652 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2653 },
2654 };
2655 fib_prefix_t pfx_5_5_5_6_s_32 = {
2656 .fp_len = 32,
2657 .fp_proto = FIB_PROTOCOL_IP4,
2658 .fp_addr = {
2659 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2660 },
2661 };
2662 fib_prefix_t pfx_5_5_5_7_s_32 = {
2663 .fp_len = 32,
2664 .fp_proto = FIB_PROTOCOL_IP4,
2665 .fp_addr = {
2666 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2667 },
2668 };
2669
2670 fib_table_entry_path_add(fib_index,
2671 &pfx_5_5_5_5_s_32,
2672 FIB_SOURCE_API,
2673 FIB_ENTRY_FLAG_NONE,
2674 FIB_PROTOCOL_IP4,
2675 &pfx_5_5_5_6_s_32.fp_addr,
2676 ~0, // no index provided.
2677 fib_index,
2678 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002679 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002680 FIB_ROUTE_PATH_FLAG_NONE);
2681 fib_table_entry_path_add(fib_index,
2682 &pfx_5_5_5_6_s_32,
2683 FIB_SOURCE_API,
2684 FIB_ENTRY_FLAG_NONE,
2685 FIB_PROTOCOL_IP4,
2686 &pfx_5_5_5_7_s_32.fp_addr,
2687 ~0, // no index provided.
2688 fib_index,
2689 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002690 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002691 FIB_ROUTE_PATH_FLAG_NONE);
2692 fib_table_entry_path_add(fib_index,
2693 &pfx_5_5_5_7_s_32,
2694 FIB_SOURCE_API,
2695 FIB_ENTRY_FLAG_NONE,
2696 FIB_PROTOCOL_IP4,
2697 &pfx_5_5_5_5_s_32.fp_addr,
2698 ~0, // no index provided.
2699 fib_index,
2700 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002701 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002702 FIB_ROUTE_PATH_FLAG_NONE);
2703 /*
2704 * +3 entries, +3 shared path-list
2705 */
2706 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2707 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002708 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002709 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002710 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002711 fib_entry_pool_size());
2712
2713 /*
2714 * All the entries have only looped paths, so they are all drop
2715 */
2716 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2717 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2718 "LB for 5.5.5.7/32 is via adj for DROP");
2719 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2720 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2721 "LB for 5.5.5.5/32 is via adj for DROP");
2722 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2723 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2724 "LB for 5.5.5.6/32 is via adj for DROP");
2725
2726 /*
2727 * provide 5.5.5.6/32 with alternate path.
2728 * this will allow only 5.5.5.6/32 to forward with this path, the others
2729 * are still drop since the loop is still present.
2730 */
2731 fib_table_entry_path_add(fib_index,
2732 &pfx_5_5_5_6_s_32,
2733 FIB_SOURCE_API,
2734 FIB_ENTRY_FLAG_NONE,
2735 FIB_PROTOCOL_IP4,
2736 &nh_10_10_10_1,
2737 tm->hw[0]->sw_if_index,
2738 ~0,
2739 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002740 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002741 FIB_ROUTE_PATH_FLAG_NONE);
2742
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002743 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2744 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2745
2746 lb = load_balance_get(dpo1->dpoi_index);
2747 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2748
2749 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2750 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2751 FIB_TEST((ai_01 == dpo2->dpoi_index),
2752 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2753
2754 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2755 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2756 "LB for 5.5.5.7/32 is via adj for DROP");
2757 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2758 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2759 "LB for 5.5.5.5/32 is via adj for DROP");
2760
2761 /*
2762 * remove the alternate path for 5.5.5.6/32
2763 * back to all drop
2764 */
2765 fib_table_entry_path_remove(fib_index,
2766 &pfx_5_5_5_6_s_32,
2767 FIB_SOURCE_API,
2768 FIB_PROTOCOL_IP4,
2769 &nh_10_10_10_1,
2770 tm->hw[0]->sw_if_index,
2771 ~0,
2772 1,
2773 FIB_ROUTE_PATH_FLAG_NONE);
2774
2775 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2776 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2777 "LB for 5.5.5.7/32 is via adj for DROP");
2778 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2779 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2780 "LB for 5.5.5.5/32 is via adj for DROP");
2781 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2782 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2783 "LB for 5.5.5.6/32 is via adj for DROP");
2784
2785 /*
2786 * break the loop by giving 5.5.5.5/32 a new set of paths
2787 * expect all to forward via this new path.
2788 */
2789 fib_table_entry_update_one_path(fib_index,
2790 &pfx_5_5_5_5_s_32,
2791 FIB_SOURCE_API,
2792 FIB_ENTRY_FLAG_NONE,
2793 FIB_PROTOCOL_IP4,
2794 &nh_10_10_10_1,
2795 tm->hw[0]->sw_if_index,
2796 ~0, // invalid fib index
2797 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002798 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002799 FIB_ROUTE_PATH_FLAG_NONE);
2800
2801 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2802 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2803 lb = load_balance_get(dpo1->dpoi_index);
2804 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2805
2806 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2807 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2808 FIB_TEST((ai_01 == dpo2->dpoi_index),
2809 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2810
2811 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2812 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2813
2814 lb = load_balance_get(dpo2->dpoi_index);
2815 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2816 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2817 "5.5.5.5.7 via 5.5.5.5");
2818
2819 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2820 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2821
2822 lb = load_balance_get(dpo1->dpoi_index);
2823 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2824 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2825 "5.5.5.5.6 via 5.5.5.7");
2826
2827 /*
2828 * revert back to the loop. so we can remove the prefixes with
2829 * the loop intact
2830 */
2831 fib_table_entry_update_one_path(fib_index,
2832 &pfx_5_5_5_5_s_32,
2833 FIB_SOURCE_API,
2834 FIB_ENTRY_FLAG_NONE,
2835 FIB_PROTOCOL_IP4,
2836 &pfx_5_5_5_6_s_32.fp_addr,
2837 ~0, // no index provided.
2838 fib_index,
2839 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002840 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002841 FIB_ROUTE_PATH_FLAG_NONE);
2842
2843 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2844 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2845 "LB for 5.5.5.7/32 is via adj for DROP");
2846 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2847 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2848 "LB for 5.5.5.5/32 is via adj for DROP");
2849 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2850 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2851 "LB for 5.5.5.6/32 is via adj for DROP");
2852
2853 /*
2854 * remove all the 5.5.5.x/32 prefixes
2855 */
2856 fib_table_entry_path_remove(fib_index,
2857 &pfx_5_5_5_5_s_32,
2858 FIB_SOURCE_API,
2859 FIB_PROTOCOL_IP4,
2860 &pfx_5_5_5_6_s_32.fp_addr,
2861 ~0, // no index provided.
2862 fib_index, // same as route's FIB
2863 1,
2864 FIB_ROUTE_PATH_FLAG_NONE);
2865 fib_table_entry_path_remove(fib_index,
2866 &pfx_5_5_5_6_s_32,
2867 FIB_SOURCE_API,
2868 FIB_PROTOCOL_IP4,
2869 &pfx_5_5_5_7_s_32.fp_addr,
2870 ~0, // no index provided.
2871 fib_index, // same as route's FIB
2872 1,
2873 FIB_ROUTE_PATH_FLAG_NONE);
2874 fib_table_entry_path_remove(fib_index,
2875 &pfx_5_5_5_7_s_32,
2876 FIB_SOURCE_API,
2877 FIB_PROTOCOL_IP4,
2878 &pfx_5_5_5_5_s_32.fp_addr,
2879 ~0, // no index provided.
2880 fib_index, // same as route's FIB
2881 1,
2882 FIB_ROUTE_PATH_FLAG_NONE);
2883 fib_table_entry_path_remove(fib_index,
2884 &pfx_5_5_5_6_s_32,
2885 FIB_SOURCE_API,
2886 FIB_PROTOCOL_IP4,
2887 &nh_10_10_10_2,
2888 ~0, // no index provided.
2889 fib_index, // same as route's FIB
2890 1,
2891 FIB_ROUTE_PATH_FLAG_NONE);
2892
2893 /*
2894 * -3 entries, -3 shared path-list
2895 */
2896 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2897 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002898 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002899 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002900 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002901 fib_entry_pool_size());
2902
2903 /*
2904 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2905 */
2906 fib_table_entry_path_add(fib_index,
2907 &pfx_5_5_5_6_s_32,
2908 FIB_SOURCE_API,
2909 FIB_ENTRY_FLAG_NONE,
2910 FIB_PROTOCOL_IP4,
2911 &pfx_5_5_5_6_s_32.fp_addr,
2912 ~0, // no index provided.
2913 fib_index,
2914 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002915 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002916 FIB_ROUTE_PATH_FLAG_NONE);
2917 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2918 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2919 "1-level 5.5.5.6/32 loop is via adj for DROP");
2920
2921 fib_table_entry_path_remove(fib_index,
2922 &pfx_5_5_5_6_s_32,
2923 FIB_SOURCE_API,
2924 FIB_PROTOCOL_IP4,
2925 &pfx_5_5_5_6_s_32.fp_addr,
2926 ~0, // no index provided.
2927 fib_index, // same as route's FIB
2928 1,
2929 FIB_ROUTE_PATH_FLAG_NONE);
2930 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2931 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2932 "1-level 5.5.5.6/32 loop is removed");
2933
2934 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002935 * A recursive route whose next-hop is covered by the prefix.
2936 * This would mean the via-fib, which inherits forwarding from its
2937 * cover, thus picks up forwarding from the prfix, which is via the
2938 * via-fib, and we have a loop.
2939 */
2940 fib_prefix_t pfx_23_23_23_0_s_24 = {
2941 .fp_len = 24,
2942 .fp_proto = FIB_PROTOCOL_IP4,
2943 .fp_addr = {
2944 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2945 },
2946 };
2947 fib_prefix_t pfx_23_23_23_23_s_32 = {
2948 .fp_len = 32,
2949 .fp_proto = FIB_PROTOCOL_IP4,
2950 .fp_addr = {
2951 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2952 },
2953 };
2954 fei = fib_table_entry_path_add(fib_index,
2955 &pfx_23_23_23_0_s_24,
2956 FIB_SOURCE_API,
2957 FIB_ENTRY_FLAG_NONE,
2958 FIB_PROTOCOL_IP4,
2959 &pfx_23_23_23_23_s_32.fp_addr,
2960 ~0, // recursive
2961 fib_index,
2962 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002963 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002964 FIB_ROUTE_PATH_FLAG_NONE);
2965 dpo = fib_entry_contribute_ip_forwarding(fei);
2966 FIB_TEST(load_balance_is_drop(dpo),
2967 "23.23.23.0/24 via covered is DROP");
2968 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2969
2970 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002971 * add-remove test. no change.
2972 */
2973 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2974 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002975 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002976 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002977 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002978 fib_entry_pool_size());
2979
2980 /*
Neale Ranns08b16482017-05-13 05:52:58 -07002981 * Make the default route recursive via a unknown next-hop. Thus the
2982 * next hop's cover would be the default route
2983 */
2984 fei = fib_table_entry_path_add(fib_index,
2985 &pfx_0_0_0_0_s_0,
2986 FIB_SOURCE_API,
2987 FIB_ENTRY_FLAG_NONE,
2988 FIB_PROTOCOL_IP4,
2989 &pfx_23_23_23_23_s_32.fp_addr,
2990 ~0, // recursive
2991 fib_index,
2992 1,
2993 NULL,
2994 FIB_ROUTE_PATH_FLAG_NONE);
2995 dpo = fib_entry_contribute_ip_forwarding(fei);
2996 FIB_TEST(load_balance_is_drop(dpo),
2997 "0.0.0.0.0/0 via is DROP");
2998 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
2999 "no resolving interface for looped 0.0.0.0/0");
3000
3001 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3002 dpo = fib_entry_contribute_ip_forwarding(fei);
3003 FIB_TEST(load_balance_is_drop(dpo),
3004 "23.23.23.23/32 via is DROP");
3005 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3006 "no resolving interface for looped 23.23.23.23/32");
3007
3008 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3009
3010 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003011 * A recursive route with recursion constraints.
3012 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3013 */
3014 fib_table_entry_path_add(fib_index,
3015 &bgp_200_pfx,
3016 FIB_SOURCE_API,
3017 FIB_ENTRY_FLAG_NONE,
3018 FIB_PROTOCOL_IP4,
3019 &nh_1_1_1_1,
3020 ~0,
3021 fib_index,
3022 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003023 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003024 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3025
3026 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3027 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3028
3029 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3030 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3031
3032 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3033 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3034
3035 /*
3036 * save the load-balance. we expect it to be inplace modified
3037 */
3038 lb = load_balance_get(dpo1->dpoi_index);
3039
3040 /*
3041 * add a covering prefix for the via fib that would otherwise serve
3042 * as the resolving route when the host is removed
3043 */
3044 fib_table_entry_path_add(fib_index,
3045 &pfx_1_1_1_0_s_28,
3046 FIB_SOURCE_API,
3047 FIB_ENTRY_FLAG_NONE,
3048 FIB_PROTOCOL_IP4,
3049 &nh_10_10_10_1,
3050 tm->hw[0]->sw_if_index,
3051 ~0, // invalid fib index
3052 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003053 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003054 FIB_ROUTE_PATH_FLAG_NONE);
3055 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3056 ai = fib_entry_get_adj(fei);
3057 FIB_TEST((ai == ai_01),
3058 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3059
3060 /*
3061 * remove the host via FIB - expect the BGP prefix to be drop
3062 */
3063 fib_table_entry_path_remove(fib_index,
3064 &pfx_1_1_1_1_s_32,
3065 FIB_SOURCE_API,
3066 FIB_PROTOCOL_IP4,
3067 &nh_10_10_10_1,
3068 tm->hw[0]->sw_if_index,
3069 ~0, // invalid fib index
3070 1,
3071 FIB_ROUTE_PATH_FLAG_NONE);
3072
3073 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3074 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3075
3076 /*
3077 * add the via-entry host reoute back. expect to resolve again
3078 */
3079 fib_table_entry_path_add(fib_index,
3080 &pfx_1_1_1_1_s_32,
3081 FIB_SOURCE_API,
3082 FIB_ENTRY_FLAG_NONE,
3083 FIB_PROTOCOL_IP4,
3084 &nh_10_10_10_1,
3085 tm->hw[0]->sw_if_index,
3086 ~0, // invalid fib index
3087 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003088 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003089 FIB_ROUTE_PATH_FLAG_NONE);
3090 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3091 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3092
3093 /*
3094 * add another path for the recursive. it will then have 2.
3095 */
3096 fib_prefix_t pfx_1_1_1_3_s_32 = {
3097 .fp_len = 32,
3098 .fp_proto = FIB_PROTOCOL_IP4,
3099 .fp_addr = {
3100 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3101 },
3102 };
3103 fib_table_entry_path_add(fib_index,
3104 &pfx_1_1_1_3_s_32,
3105 FIB_SOURCE_API,
3106 FIB_ENTRY_FLAG_NONE,
3107 FIB_PROTOCOL_IP4,
3108 &nh_10_10_10_2,
3109 tm->hw[0]->sw_if_index,
3110 ~0, // invalid fib index
3111 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003112 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003113 FIB_ROUTE_PATH_FLAG_NONE);
3114
3115 fib_table_entry_path_add(fib_index,
3116 &bgp_200_pfx,
3117 FIB_SOURCE_API,
3118 FIB_ENTRY_FLAG_NONE,
3119 FIB_PROTOCOL_IP4,
3120 &pfx_1_1_1_3_s_32.fp_addr,
3121 ~0,
3122 fib_index,
3123 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003124 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003125 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3126
Neale Rannsf12a83f2017-04-18 09:09:40 -07003127 /*
3128 * add a bunch load more entries using this path combo so that we get
3129 * an LB-map created.
3130 */
3131#define N_P 128
3132 fib_prefix_t bgp_78s[N_P];
3133 for (ii = 0; ii < N_P; ii++)
3134 {
3135 bgp_78s[ii].fp_len = 32;
3136 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3137 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3138
3139
3140 fib_table_entry_path_add(fib_index,
3141 &bgp_78s[ii],
3142 FIB_SOURCE_API,
3143 FIB_ENTRY_FLAG_NONE,
3144 FIB_PROTOCOL_IP4,
3145 &pfx_1_1_1_3_s_32.fp_addr,
3146 ~0,
3147 fib_index,
3148 1,
3149 NULL,
3150 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3151 fib_table_entry_path_add(fib_index,
3152 &bgp_78s[ii],
3153 FIB_SOURCE_API,
3154 FIB_ENTRY_FLAG_NONE,
3155 FIB_PROTOCOL_IP4,
3156 &nh_1_1_1_1,
3157 ~0,
3158 fib_index,
3159 1,
3160 NULL,
3161 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3162 }
3163
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003164 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3165 dpo = fib_entry_contribute_ip_forwarding(fei);
3166
3167 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3168 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3169 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3170 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3171 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3172 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3173 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3174 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3175
3176 /*
3177 * expect the lb-map used by the recursive's load-balance is using both buckets
3178 */
3179 load_balance_map_t *lbm;
3180 index_t lbmi;
3181
3182 lb = load_balance_get(dpo->dpoi_index);
3183 lbmi = lb->lb_map;
3184 load_balance_map_lock(lbmi);
3185 lbm = load_balance_map_get(lbmi);
3186
3187 FIB_TEST(lbm->lbm_buckets[0] == 0,
3188 "LB maps's bucket 0 is %d",
3189 lbm->lbm_buckets[0]);
3190 FIB_TEST(lbm->lbm_buckets[1] == 1,
3191 "LB maps's bucket 1 is %d",
3192 lbm->lbm_buckets[1]);
3193
3194 /*
3195 * withdraw one of the /32 via-entrys.
3196 * that ECMP path will be unresolved and forwarding should continue on the
3197 * other available path. this is an iBGP PIC edge failover.
3198 * Test the forwarding changes without re-fetching the adj from the
3199 * recursive entry. this ensures its the same one that is updated; i.e. an
3200 * inplace-modify.
3201 */
3202 fib_table_entry_path_remove(fib_index,
3203 &pfx_1_1_1_1_s_32,
3204 FIB_SOURCE_API,
3205 FIB_PROTOCOL_IP4,
3206 &nh_10_10_10_1,
3207 tm->hw[0]->sw_if_index,
3208 ~0, // invalid fib index
3209 1,
3210 FIB_ROUTE_PATH_FLAG_NONE);
3211
Neale Rannsf12a83f2017-04-18 09:09:40 -07003212 /* suspend so the update walk kicks int */
3213 vlib_process_suspend(vlib_get_main(), 1e-5);
3214
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003215 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3216 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3217 "post PIC 200.200.200.200/32 was inplace modified");
3218
3219 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3220 "post PIC adj for 200.200.200.200/32 is recursive"
3221 " via adj for 1.1.1.3");
3222
3223 /*
3224 * the LB maps that was locked above should have been modified to remove
3225 * the path that was down, and thus its bucket points to a path that is
3226 * still up.
3227 */
3228 FIB_TEST(lbm->lbm_buckets[0] == 1,
3229 "LB maps's bucket 0 is %d",
3230 lbm->lbm_buckets[0]);
3231 FIB_TEST(lbm->lbm_buckets[1] == 1,
3232 "LB maps's bucket 1 is %d",
3233 lbm->lbm_buckets[1]);
3234
Neale Ranns994dab42017-04-18 12:56:45 -07003235 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003236
3237 /*
3238 * add it back. again
3239 */
3240 fib_table_entry_path_add(fib_index,
3241 &pfx_1_1_1_1_s_32,
3242 FIB_SOURCE_API,
3243 FIB_ENTRY_FLAG_NONE,
3244 FIB_PROTOCOL_IP4,
3245 &nh_10_10_10_1,
3246 tm->hw[0]->sw_if_index,
3247 ~0, // invalid fib index
3248 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003249 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003250 FIB_ROUTE_PATH_FLAG_NONE);
3251
Neale Rannsf12a83f2017-04-18 09:09:40 -07003252 /* suspend so the update walk kicks in */
3253 vlib_process_suspend(vlib_get_main(), 1e-5);
3254
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003255 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3256 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3257 "via adj for 1.1.1.1");
3258 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3259 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3260 "via adj for 1.1.1.3");
3261
3262 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3263 dpo = fib_entry_contribute_ip_forwarding(fei);
3264 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3265 "post PIC 200.200.200.200/32 was inplace modified");
3266
3267 /*
3268 * add a 3rd path. this makes the LB 16 buckets.
3269 */
3270 fib_table_entry_path_add(fib_index,
3271 &bgp_200_pfx,
3272 FIB_SOURCE_API,
3273 FIB_ENTRY_FLAG_NONE,
3274 FIB_PROTOCOL_IP4,
3275 &pfx_1_1_1_2_s_32.fp_addr,
3276 ~0,
3277 fib_index,
3278 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003279 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003280 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003281 for (ii = 0; ii < N_P; ii++)
3282 {
3283 fib_table_entry_path_add(fib_index,
3284 &bgp_78s[ii],
3285 FIB_SOURCE_API,
3286 FIB_ENTRY_FLAG_NONE,
3287 FIB_PROTOCOL_IP4,
3288 &pfx_1_1_1_2_s_32.fp_addr,
3289 ~0,
3290 fib_index,
3291 1,
3292 NULL,
3293 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3294 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003295
3296 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3297 dpo = fib_entry_contribute_ip_forwarding(fei);
3298 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3299 "200.200.200.200/32 was inplace modified for 3rd path");
3300 FIB_TEST(16 == lb->lb_n_buckets,
3301 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3302
3303 lbmi = lb->lb_map;
3304 load_balance_map_lock(lbmi);
3305 lbm = load_balance_map_get(lbmi);
3306
3307 for (ii = 0; ii < 16; ii++)
3308 {
3309 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3310 "LB Map for 200.200.200.200/32 at %d is %d",
3311 ii, lbm->lbm_buckets[ii]);
3312 }
3313
3314 /*
3315 * trigger PIC by removing the first via-entry
3316 * the first 6 buckets of the map should map to the next 6
3317 */
3318 fib_table_entry_path_remove(fib_index,
3319 &pfx_1_1_1_1_s_32,
3320 FIB_SOURCE_API,
3321 FIB_PROTOCOL_IP4,
3322 &nh_10_10_10_1,
3323 tm->hw[0]->sw_if_index,
3324 ~0,
3325 1,
3326 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003327 /* suspend so the update walk kicks int */
3328 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003329
3330 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3331 dpo = fib_entry_contribute_ip_forwarding(fei);
3332 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3333 "200.200.200.200/32 was inplace modified for 3rd path");
3334 FIB_TEST(2 == lb->lb_n_buckets,
3335 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3336
3337 for (ii = 0; ii < 6; ii++)
3338 {
3339 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3340 "LB Map for 200.200.200.200/32 at %d is %d",
3341 ii, lbm->lbm_buckets[ii]);
3342 }
3343 for (ii = 6; ii < 16; ii++)
3344 {
3345 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3346 "LB Map for 200.200.200.200/32 at %d is %d",
3347 ii, lbm->lbm_buckets[ii]);
3348 }
Neale Ranns994dab42017-04-18 12:56:45 -07003349 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003350
3351 /*
3352 * tidy up
3353 */
3354 fib_table_entry_path_add(fib_index,
3355 &pfx_1_1_1_1_s_32,
3356 FIB_SOURCE_API,
3357 FIB_ENTRY_FLAG_NONE,
3358 FIB_PROTOCOL_IP4,
3359 &nh_10_10_10_1,
3360 tm->hw[0]->sw_if_index,
3361 ~0,
3362 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003363 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003364 FIB_ROUTE_PATH_FLAG_NONE);
3365
Neale Rannsf12a83f2017-04-18 09:09:40 -07003366 for (ii = 0; ii < N_P; ii++)
3367 {
3368 fib_table_entry_delete(fib_index,
3369 &bgp_78s[ii],
3370 FIB_SOURCE_API);
3371 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3372 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3373 "%U removed",
3374 format_fib_prefix, &bgp_78s[ii]);
3375 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003376 fib_table_entry_path_remove(fib_index,
3377 &bgp_200_pfx,
3378 FIB_SOURCE_API,
3379 FIB_PROTOCOL_IP4,
3380 &pfx_1_1_1_2_s_32.fp_addr,
3381 ~0,
3382 fib_index,
3383 1,
3384 MPLS_LABEL_INVALID);
3385 fib_table_entry_path_remove(fib_index,
3386 &bgp_200_pfx,
3387 FIB_SOURCE_API,
3388 FIB_PROTOCOL_IP4,
3389 &nh_1_1_1_1,
3390 ~0,
3391 fib_index,
3392 1,
3393 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3394 fib_table_entry_path_remove(fib_index,
3395 &bgp_200_pfx,
3396 FIB_SOURCE_API,
3397 FIB_PROTOCOL_IP4,
3398 &pfx_1_1_1_3_s_32.fp_addr,
3399 ~0,
3400 fib_index,
3401 1,
3402 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3403 fib_table_entry_delete(fib_index,
3404 &pfx_1_1_1_3_s_32,
3405 FIB_SOURCE_API);
3406 fib_table_entry_delete(fib_index,
3407 &pfx_1_1_1_0_s_28,
3408 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003409 /* suspend so the update walk kicks int */
3410 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003411 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3412 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3413 "1.1.1.1/28 removed");
3414 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3415 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3416 "1.1.1.3/32 removed");
3417 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3418 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3419 "200.200.200.200/32 removed");
3420
3421 /*
3422 * add-remove test. no change.
3423 */
3424 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3425 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003426 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003427 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003428 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003429 fib_entry_pool_size());
3430
3431 /*
3432 * A route whose paths are built up iteratively and then removed
3433 * all at once
3434 */
3435 fib_prefix_t pfx_4_4_4_4_s_32 = {
3436 .fp_len = 32,
3437 .fp_proto = FIB_PROTOCOL_IP4,
3438 .fp_addr = {
3439 /* 4.4.4.4/32 */
3440 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3441 },
3442 };
3443
3444 fib_table_entry_path_add(fib_index,
3445 &pfx_4_4_4_4_s_32,
3446 FIB_SOURCE_API,
3447 FIB_ENTRY_FLAG_NONE,
3448 FIB_PROTOCOL_IP4,
3449 &nh_10_10_10_1,
3450 tm->hw[0]->sw_if_index,
3451 ~0,
3452 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003453 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003454 FIB_ROUTE_PATH_FLAG_NONE);
3455 fib_table_entry_path_add(fib_index,
3456 &pfx_4_4_4_4_s_32,
3457 FIB_SOURCE_API,
3458 FIB_ENTRY_FLAG_NONE,
3459 FIB_PROTOCOL_IP4,
3460 &nh_10_10_10_2,
3461 tm->hw[0]->sw_if_index,
3462 ~0,
3463 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003464 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003465 FIB_ROUTE_PATH_FLAG_NONE);
3466 fib_table_entry_path_add(fib_index,
3467 &pfx_4_4_4_4_s_32,
3468 FIB_SOURCE_API,
3469 FIB_ENTRY_FLAG_NONE,
3470 FIB_PROTOCOL_IP4,
3471 &nh_10_10_10_3,
3472 tm->hw[0]->sw_if_index,
3473 ~0,
3474 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003475 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003476 FIB_ROUTE_PATH_FLAG_NONE);
3477 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3478 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3479 "4.4.4.4/32 present");
3480
3481 fib_table_entry_delete(fib_index,
3482 &pfx_4_4_4_4_s_32,
3483 FIB_SOURCE_API);
3484 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3485 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3486 "4.4.4.4/32 removed");
3487
3488 /*
3489 * add-remove test. no change.
3490 */
3491 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3492 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003493 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003494 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003495 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003496 fib_entry_pool_size());
3497
3498 /*
3499 * A route with multiple paths at once
3500 */
3501 fib_route_path_t *r_paths = NULL;
3502
3503 for (ii = 0; ii < 4; ii++)
3504 {
3505 fib_route_path_t r_path = {
3506 .frp_proto = FIB_PROTOCOL_IP4,
3507 .frp_addr = {
3508 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3509 },
3510 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3511 .frp_weight = 1,
3512 .frp_fib_index = ~0,
3513 };
3514 vec_add1(r_paths, r_path);
3515 }
3516
3517 fib_table_entry_update(fib_index,
3518 &pfx_4_4_4_4_s_32,
3519 FIB_SOURCE_API,
3520 FIB_ENTRY_FLAG_NONE,
3521 r_paths);
3522
3523 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3524 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3525 dpo = fib_entry_contribute_ip_forwarding(fei);
3526
3527 lb = load_balance_get(dpo->dpoi_index);
3528 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3529
3530 fib_table_entry_delete(fib_index,
3531 &pfx_4_4_4_4_s_32,
3532 FIB_SOURCE_API);
3533 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3534 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3535 "4.4.4.4/32 removed");
3536 vec_free(r_paths);
3537
3538 /*
3539 * add-remove test. no change.
3540 */
3541 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3542 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003543 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003544 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003545 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003546 fib_entry_pool_size());
3547
3548 /*
3549 * A route deag route
3550 */
3551 fib_table_entry_path_add(fib_index,
3552 &pfx_4_4_4_4_s_32,
3553 FIB_SOURCE_API,
3554 FIB_ENTRY_FLAG_NONE,
3555 FIB_PROTOCOL_IP4,
3556 &zero_addr,
3557 ~0,
3558 fib_index,
3559 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003560 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003561 FIB_ROUTE_PATH_FLAG_NONE);
3562
3563 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3564 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3565
3566 dpo = fib_entry_contribute_ip_forwarding(fei);
3567 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3568 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3569
3570 FIB_TEST((fib_index == lkd->lkd_fib_index),
3571 "4.4.4.4/32 is deag in %d %U",
3572 lkd->lkd_fib_index,
3573 format_dpo_id, dpo, 0);
3574
3575 fib_table_entry_delete(fib_index,
3576 &pfx_4_4_4_4_s_32,
3577 FIB_SOURCE_API);
3578 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3579 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3580 "4.4.4.4/32 removed");
3581 vec_free(r_paths);
3582
3583 /*
3584 * add-remove test. no change.
3585 */
3586 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3587 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003588 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003589 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003590 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003591 fib_entry_pool_size());
3592
3593 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003594 * Duplicate paths:
3595 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3596 */
3597 fib_prefix_t pfx_34_1_1_1_s_32 = {
3598 .fp_len = 32,
3599 .fp_proto = FIB_PROTOCOL_IP4,
3600 .fp_addr = {
3601 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3602 },
3603 };
3604 fib_prefix_t pfx_34_34_1_1_s_32 = {
3605 .fp_len = 32,
3606 .fp_proto = FIB_PROTOCOL_IP4,
3607 .fp_addr = {
3608 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3609 },
3610 };
3611 fei = fib_table_entry_path_add(fib_index,
3612 &pfx_34_1_1_1_s_32,
3613 FIB_SOURCE_API,
3614 FIB_ENTRY_FLAG_NONE,
3615 FIB_PROTOCOL_IP4,
3616 &pfx_34_34_1_1_s_32.fp_addr,
3617 ~0,
3618 fib_index,
3619 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003620 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003621 FIB_ROUTE_PATH_FLAG_NONE);
3622 fei = fib_table_entry_path_add(fib_index,
3623 &pfx_34_1_1_1_s_32,
3624 FIB_SOURCE_API,
3625 FIB_ENTRY_FLAG_NONE,
3626 FIB_PROTOCOL_IP4,
3627 &pfx_34_34_1_1_s_32.fp_addr,
3628 ~0,
3629 fib_index,
3630 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003631 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003632 FIB_ROUTE_PATH_FLAG_NONE);
3633 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3634 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3635
3636 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003637 * CLEANUP
3638 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3639 * all of which are via 10.10.10.1, Itf1
3640 */
3641 fib_table_entry_path_remove(fib_index,
3642 &pfx_1_1_1_2_s_32,
3643 FIB_SOURCE_API,
3644 FIB_PROTOCOL_IP4,
3645 &nh_10_10_10_1,
3646 tm->hw[0]->sw_if_index,
3647 ~0,
3648 1,
3649 FIB_ROUTE_PATH_FLAG_NONE);
3650 fib_table_entry_path_remove(fib_index,
3651 &pfx_1_1_1_1_s_32,
3652 FIB_SOURCE_API,
3653 FIB_PROTOCOL_IP4,
3654 &nh_10_10_10_1,
3655 tm->hw[0]->sw_if_index,
3656 ~0,
3657 1,
3658 FIB_ROUTE_PATH_FLAG_NONE);
3659 fib_table_entry_path_remove(fib_index,
3660 &pfx_1_1_2_0_s_24,
3661 FIB_SOURCE_API,
3662 FIB_PROTOCOL_IP4,
3663 &nh_10_10_10_1,
3664 tm->hw[0]->sw_if_index,
3665 ~0,
3666 1,
3667 FIB_ROUTE_PATH_FLAG_NONE);
3668
3669 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3670 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3671 "1.1.1.1/32 removed");
3672 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3673 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3674 "1.1.1.2/32 removed");
3675 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3676 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3677 "1.1.2.0/24 removed");
3678
3679 /*
3680 * -3 entries and -1 shared path-list
3681 */
3682 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3683 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003684 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003685 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003686 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003687 fib_entry_pool_size());
3688
3689 /*
3690 * An attached-host route. Expect to link to the incomplete adj
3691 */
3692 fib_prefix_t pfx_4_1_1_1_s_32 = {
3693 .fp_len = 32,
3694 .fp_proto = FIB_PROTOCOL_IP4,
3695 .fp_addr = {
3696 /* 4.1.1.1/32 */
3697 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3698 },
3699 };
3700 fib_table_entry_path_add(fib_index,
3701 &pfx_4_1_1_1_s_32,
3702 FIB_SOURCE_API,
3703 FIB_ENTRY_FLAG_NONE,
3704 FIB_PROTOCOL_IP4,
3705 &zero_addr,
3706 tm->hw[0]->sw_if_index,
3707 fib_index,
3708 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003709 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003710 FIB_ROUTE_PATH_FLAG_NONE);
3711
3712 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3713 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3714 ai = fib_entry_get_adj(fei);
3715
3716 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003717 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003718 &pfx_4_1_1_1_s_32.fp_addr,
3719 tm->hw[0]->sw_if_index);
3720 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3721 adj_unlock(ai2);
3722
3723 /*
3724 * +1 entry and +1 shared path-list
3725 */
3726 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3727 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003728 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003729 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003730 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003731 fib_entry_pool_size());
3732
3733 fib_table_entry_delete(fib_index,
3734 &pfx_4_1_1_1_s_32,
3735 FIB_SOURCE_API);
3736
3737 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3738 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003739 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003740 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003741 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003742 fib_entry_pool_size());
3743
3744 /*
3745 * add a v6 prefix via v4 next-hops
3746 */
3747 fib_prefix_t pfx_2001_s_64 = {
3748 .fp_len = 64,
3749 .fp_proto = FIB_PROTOCOL_IP6,
3750 .fp_addr = {
3751 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3752 },
3753 };
3754 fei = fib_table_entry_path_add(0, //default v6 table
3755 &pfx_2001_s_64,
3756 FIB_SOURCE_API,
3757 FIB_ENTRY_FLAG_NONE,
3758 FIB_PROTOCOL_IP4,
3759 &nh_10_10_10_1,
3760 tm->hw[0]->sw_if_index,
3761 fib_index,
3762 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003763 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003764 FIB_ROUTE_PATH_FLAG_NONE);
3765
3766 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3767 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3768 ai = fib_entry_get_adj(fei);
3769 adj = adj_get(ai);
3770 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3771 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003772 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003773 "2001::/64 is link type v6");
3774 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3775 "2001::/64 ADJ-adj is NH proto v4");
3776 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3777
Neale Ranns3ee44042016-10-03 13:05:48 +01003778 /*
3779 * add a uRPF exempt prefix:
3780 * test:
3781 * - it's forwarding is drop
3782 * - it's uRPF list is not empty
3783 * - the uRPF list for the default route (it's cover) is empty
3784 */
3785 fei = fib_table_entry_special_add(fib_index,
3786 &pfx_4_1_1_1_s_32,
3787 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003788 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003789 dpo = fib_entry_contribute_ip_forwarding(fei);
3790 FIB_TEST(load_balance_is_drop(dpo),
3791 "uRPF exempt 4.1.1.1/32 DROP");
3792 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3793 "uRPF list for exempt prefix has itf index 0");
3794 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3795 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3796 "uRPF list for 0.0.0.0/0 empty");
3797
3798 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003799
3800 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003801 * An adj-fib that fails the refinement criteria - no connected cover
3802 */
3803 fib_prefix_t pfx_12_10_10_2_s_32 = {
3804 .fp_len = 32,
3805 .fp_proto = FIB_PROTOCOL_IP4,
3806 .fp_addr = {
3807 /* 12.10.10.2 */
3808 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3809 },
3810 };
3811
Neale Ranns81424992017-05-18 03:03:22 -07003812 fib_table_entry_path_add(fib_index,
3813 &pfx_12_10_10_2_s_32,
3814 FIB_SOURCE_ADJ,
3815 FIB_ENTRY_FLAG_ATTACHED,
3816 FIB_PROTOCOL_IP4,
3817 &pfx_12_10_10_2_s_32.fp_addr,
3818 tm->hw[0]->sw_if_index,
3819 ~0, // invalid fib index
3820 1,
3821 NULL,
3822 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003823
3824 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3825 dpo = fib_entry_contribute_ip_forwarding(fei);
3826 FIB_TEST(!dpo_id_is_valid(dpo),
3827 "no connected cover adj-fib fails refinement");
3828
3829 fib_table_entry_delete(fib_index,
3830 &pfx_12_10_10_2_s_32,
3831 FIB_SOURCE_ADJ);
3832
3833 /*
3834 * An adj-fib that fails the refinement criteria - cover is connected
3835 * but on a different interface
3836 */
3837 fib_prefix_t pfx_10_10_10_127_s_32 = {
3838 .fp_len = 32,
3839 .fp_proto = FIB_PROTOCOL_IP4,
3840 .fp_addr = {
3841 /* 10.10.10.127 */
3842 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3843 },
3844 };
3845
Neale Ranns81424992017-05-18 03:03:22 -07003846 fib_table_entry_path_add(fib_index,
3847 &pfx_10_10_10_127_s_32,
3848 FIB_SOURCE_ADJ,
3849 FIB_ENTRY_FLAG_ATTACHED,
3850 FIB_PROTOCOL_IP4,
3851 &pfx_10_10_10_127_s_32.fp_addr,
3852 tm->hw[1]->sw_if_index,
3853 ~0, // invalid fib index
3854 1,
3855 NULL,
3856 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003857
3858 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3859 dpo = fib_entry_contribute_ip_forwarding(fei);
3860 FIB_TEST(!dpo_id_is_valid(dpo),
3861 "wrong interface adj-fib fails refinement");
3862
3863 fib_table_entry_delete(fib_index,
3864 &pfx_10_10_10_127_s_32,
3865 FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07003866
3867 /*
3868 * add a second path to an adj-fib
3869 * this is a sumiluation of another ARP entry created
3870 * on an interface on which the connected prefi does not exist.
3871 * The second path fails refinement. Expect to forward through the
3872 * first.
3873 */
3874 fib_prefix_t pfx_10_10_10_3_s_32 = {
3875 .fp_len = 32,
3876 .fp_proto = FIB_PROTOCOL_IP4,
3877 .fp_addr = {
3878 /* 10.10.10.3 */
3879 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3880 },
3881 };
3882
3883 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3884 VNET_LINK_IP4,
3885 &nh_10_10_10_3,
3886 tm->hw[0]->sw_if_index);
3887
3888 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
3889 .type = FT_LB_ADJ,
3890 .adj = {
3891 .adj = ai_03,
3892 },
3893 };
3894 fei = fib_table_entry_path_add(fib_index,
3895 &pfx_10_10_10_3_s_32,
3896 FIB_SOURCE_ADJ,
3897 FIB_ENTRY_FLAG_NONE,
3898 FIB_PROTOCOL_IP4,
3899 &nh_10_10_10_3,
3900 tm->hw[0]->sw_if_index,
3901 fib_index,
3902 1,
3903 NULL,
3904 FIB_ROUTE_PATH_FLAG_NONE);
3905 fei = fib_table_entry_path_add(fib_index,
3906 &pfx_10_10_10_3_s_32,
3907 FIB_SOURCE_ADJ,
3908 FIB_ENTRY_FLAG_NONE,
3909 FIB_PROTOCOL_IP4,
3910 &nh_12_12_12_12,
3911 tm->hw[1]->sw_if_index,
3912 fib_index,
3913 1,
3914 NULL,
3915 FIB_ROUTE_PATH_FLAG_NONE);
3916 FIB_TEST(fib_test_validate_entry(fei,
3917 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3918 1,
3919 &ip_o_10_10_10_3),
3920 "10.10.10.3 via 10.10.10.3/Eth0 only");
3921
3922 /*
3923 * remove the path that refines the cover, should go unresolved
3924 */
3925 fib_table_entry_path_remove(fib_index,
3926 &pfx_10_10_10_3_s_32,
3927 FIB_SOURCE_ADJ,
3928 FIB_PROTOCOL_IP4,
3929 &nh_10_10_10_3,
3930 tm->hw[0]->sw_if_index,
3931 fib_index,
3932 1,
3933 FIB_ROUTE_PATH_FLAG_NONE);
3934 dpo = fib_entry_contribute_ip_forwarding(fei);
3935 FIB_TEST(!dpo_id_is_valid(dpo),
3936 "wrong interface adj-fib fails refinement");
3937
3938 /*
3939 * add back the path that refines the cover
3940 */
3941 fei = fib_table_entry_path_add(fib_index,
3942 &pfx_10_10_10_3_s_32,
3943 FIB_SOURCE_ADJ,
3944 FIB_ENTRY_FLAG_NONE,
3945 FIB_PROTOCOL_IP4,
3946 &nh_10_10_10_3,
3947 tm->hw[0]->sw_if_index,
3948 fib_index,
3949 1,
3950 NULL,
3951 FIB_ROUTE_PATH_FLAG_NONE);
3952 FIB_TEST(fib_test_validate_entry(fei,
3953 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3954 1,
3955 &ip_o_10_10_10_3),
3956 "10.10.10.3 via 10.10.10.3/Eth0 only");
3957
3958 /*
3959 * remove the path that does not refine the cover
3960 */
3961 fib_table_entry_path_remove(fib_index,
3962 &pfx_10_10_10_3_s_32,
3963 FIB_SOURCE_ADJ,
3964 FIB_PROTOCOL_IP4,
3965 &nh_12_12_12_12,
3966 tm->hw[1]->sw_if_index,
3967 fib_index,
3968 1,
3969 FIB_ROUTE_PATH_FLAG_NONE);
3970 FIB_TEST(fib_test_validate_entry(fei,
3971 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3972 1,
3973 &ip_o_10_10_10_3),
3974 "10.10.10.3 via 10.10.10.3/Eth0 only");
3975
3976 /*
3977 * remove the path that does refine, it's the last path, so
3978 * the entry should be gone
3979 */
3980 fib_table_entry_path_remove(fib_index,
3981 &pfx_10_10_10_3_s_32,
3982 FIB_SOURCE_ADJ,
3983 FIB_PROTOCOL_IP4,
3984 &nh_10_10_10_3,
3985 tm->hw[0]->sw_if_index,
3986 fib_index,
3987 1,
3988 FIB_ROUTE_PATH_FLAG_NONE);
3989 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
3990 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
3991
3992 adj_unlock(ai_03);
3993
Neale Ranns227038a2017-04-21 01:07:59 -07003994 /*
3995 * change the table's flow-hash config - expect the update to propagete to
3996 * the entries' load-balance objects
3997 */
3998 flow_hash_config_t old_hash_config, new_hash_config;
3999
4000 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4001 FIB_PROTOCOL_IP4);
4002 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4003 IP_FLOW_HASH_DST_ADDR);
4004
4005 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4006 dpo = fib_entry_contribute_ip_forwarding(fei);
4007 lb = load_balance_get(dpo->dpoi_index);
4008 FIB_TEST((lb->lb_hash_config == old_hash_config),
4009 "Table and LB hash config match: %U",
4010 format_ip_flow_hash_config, lb->lb_hash_config);
4011
4012 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4013
4014 FIB_TEST((lb->lb_hash_config == new_hash_config),
4015 "Table and LB newhash config match: %U",
4016 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08004017
4018 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004019 * CLEANUP
4020 * remove adj-fibs:
4021 */
4022 fib_table_entry_delete(fib_index,
4023 &pfx_10_10_10_1_s_32,
4024 FIB_SOURCE_ADJ);
4025 fib_table_entry_delete(fib_index,
4026 &pfx_10_10_10_2_s_32,
4027 FIB_SOURCE_ADJ);
4028 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4029 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4030 "10.10.10.1/32 adj-fib removed");
4031 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4032 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4033 "10.10.10.2/32 adj-fib removed");
4034
4035 /*
4036 * -2 entries and -2 non-shared path-list
4037 */
4038 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4039 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004040 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004041 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004042 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004043 fib_entry_pool_size());
4044
4045 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01004046 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004047 * These are the last locks on these adjs. they should thus go away.
4048 */
4049 adj_unlock(ai_02);
4050 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01004051 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004052
4053 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4054 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00004055
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004056 /*
4057 * CLEANUP
4058 * remove the interface prefixes
4059 */
4060 local_pfx.fp_len = 32;
4061 fib_table_entry_special_remove(fib_index, &local_pfx,
4062 FIB_SOURCE_INTERFACE);
4063 fei = fib_table_lookup(fib_index, &local_pfx);
4064
4065 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4066 fib_table_lookup_exact_match(fib_index, &local_pfx),
4067 "10.10.10.10/32 adj-fib removed");
4068
4069 local_pfx.fp_len = 24;
4070 fib_table_entry_delete(fib_index, &local_pfx,
4071 FIB_SOURCE_INTERFACE);
4072
4073 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4074 fib_table_lookup_exact_match(fib_index, &local_pfx),
4075 "10.10.10.10/24 adj-fib removed");
4076
4077 /*
4078 * -2 entries and -2 non-shared path-list
4079 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07004080 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004081 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004082 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004083 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004084 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004085 fib_entry_pool_size());
4086
4087 /*
4088 * Last but not least, remove the VRF
4089 */
4090 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4091 FIB_PROTOCOL_IP4,
4092 FIB_SOURCE_API)),
4093 "NO API Source'd prefixes");
4094 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4095 FIB_PROTOCOL_IP4,
4096 FIB_SOURCE_RR)),
4097 "NO RR Source'd prefixes");
4098 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4099 FIB_PROTOCOL_IP4,
4100 FIB_SOURCE_INTERFACE)),
4101 "NO INterface Source'd prefixes");
4102
4103 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
4104
4105 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4106 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004107 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004108 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004109 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004110 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004111 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01004112 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004113 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07004114 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004115 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4116 pool_elts(load_balance_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004117
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004118 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004119}
4120
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004121static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004122fib_test_v6 (void)
4123{
4124 /*
4125 * In the default table check for the presence and correct forwarding
4126 * of the special entries
4127 */
4128 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4129 const dpo_id_t *dpo, *dpo_drop;
4130 const ip_adjacency_t *adj;
4131 const receive_dpo_t *rd;
4132 test_main_t *tm;
4133 u32 fib_index;
4134 int ii;
4135
4136 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4137 adj_nbr_db_size());
4138
4139 /* via 2001:0:0:1::2 */
4140 ip46_address_t nh_2001_2 = {
4141 .ip6 = {
4142 .as_u64 = {
4143 [0] = clib_host_to_net_u64(0x2001000000000001),
4144 [1] = clib_host_to_net_u64(0x0000000000000002),
4145 },
4146 },
4147 };
4148
4149 tm = &test_main;
4150
4151 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4152
4153 /* Find or create FIB table 11 */
4154 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
4155
4156 for (ii = 0; ii < 4; ii++)
4157 {
4158 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4159 }
4160
4161 fib_prefix_t pfx_0_0 = {
4162 .fp_len = 0,
4163 .fp_proto = FIB_PROTOCOL_IP6,
4164 .fp_addr = {
4165 .ip6 = {
4166 {0, 0},
4167 },
4168 },
4169 };
4170
4171 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4172 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4173 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4174 "Default route is DROP");
4175
4176 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4177 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4178 &ip6_main,
4179 1,
4180 &pfx_0_0.fp_addr.ip6)),
4181 "default-route; fwd and non-fwd tables match");
4182
4183 // FIXME - check specials.
4184
4185 /*
4186 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004187 * each with 2 entries and a v6 mfib with 4 path-lists.
4188 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004189 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004190#define ENPS (5+4)
4191#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004192 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004193 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004194 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004195 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004196 fib_entry_pool_size());
4197
4198 /*
4199 * add interface routes.
4200 * validate presence of /64 attached and /128 recieve.
4201 * test for the presence of the receive address in the glean and local adj
4202 *
4203 * receive on 2001:0:0:1::1/128
4204 */
4205 fib_prefix_t local_pfx = {
4206 .fp_len = 64,
4207 .fp_proto = FIB_PROTOCOL_IP6,
4208 .fp_addr = {
4209 .ip6 = {
4210 .as_u64 = {
4211 [0] = clib_host_to_net_u64(0x2001000000000001),
4212 [1] = clib_host_to_net_u64(0x0000000000000001),
4213 },
4214 },
4215 }
4216 };
4217
4218 fib_table_entry_update_one_path(fib_index, &local_pfx,
4219 FIB_SOURCE_INTERFACE,
4220 (FIB_ENTRY_FLAG_CONNECTED |
4221 FIB_ENTRY_FLAG_ATTACHED),
4222 FIB_PROTOCOL_IP6,
4223 NULL,
4224 tm->hw[0]->sw_if_index,
4225 ~0,
4226 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004227 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004228 FIB_ROUTE_PATH_FLAG_NONE);
4229 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4230
4231 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4232
4233 ai = fib_entry_get_adj(fei);
4234 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4235 adj = adj_get(ai);
4236 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4237 "attached interface adj is glean");
4238 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4239 &adj->sub_type.glean.receive_addr)),
4240 "attached interface adj is receive ok");
4241 dpo = fib_entry_contribute_ip_forwarding(fei);
4242 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4243 &ip6_main,
4244 1,
4245 &local_pfx.fp_addr.ip6)),
4246 "attached-route; fwd and non-fwd tables match");
4247
4248 local_pfx.fp_len = 128;
4249 fib_table_entry_update_one_path(fib_index, &local_pfx,
4250 FIB_SOURCE_INTERFACE,
4251 (FIB_ENTRY_FLAG_CONNECTED |
4252 FIB_ENTRY_FLAG_LOCAL),
4253 FIB_PROTOCOL_IP6,
4254 NULL,
4255 tm->hw[0]->sw_if_index,
4256 ~0, // invalid fib index
4257 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004258 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004259 FIB_ROUTE_PATH_FLAG_NONE);
4260 fei = fib_table_lookup(fib_index, &local_pfx);
4261
4262 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4263
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
4270 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4271 &rd->rd_addr)),
4272 "local interface adj is receive ok");
4273
4274 dpo = fib_entry_contribute_ip_forwarding(fei);
4275 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4276 &ip6_main,
4277 1,
4278 &local_pfx.fp_addr.ip6)),
4279 "local-route; fwd and non-fwd tables match");
4280
4281 /*
4282 * +2 entries. +2 unshared path-lists
4283 */
4284 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004285 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004286 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004287 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004288 fib_entry_pool_size());
4289
4290 /*
4291 * Modify the default route to be via an adj not yet known.
4292 * this sources the defalut route with the API source, which is
4293 * a higher preference to the DEFAULT_ROUTE source
4294 */
4295 fib_table_entry_path_add(fib_index, &pfx_0_0,
4296 FIB_SOURCE_API,
4297 FIB_ENTRY_FLAG_NONE,
4298 FIB_PROTOCOL_IP6,
4299 &nh_2001_2,
4300 tm->hw[0]->sw_if_index,
4301 ~0,
4302 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004303 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004304 FIB_ROUTE_PATH_FLAG_NONE);
4305 fei = fib_table_lookup(fib_index, &pfx_0_0);
4306
4307 FIB_TEST((fei == dfrt), "default route same index");
4308 ai = fib_entry_get_adj(fei);
4309 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4310 adj = adj_get(ai);
4311 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4312 "adj is incomplete");
4313 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4314 "adj nbr next-hop ok");
4315
4316 /*
4317 * find the adj in the shared db
4318 */
4319 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004320 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004321 &nh_2001_2,
4322 tm->hw[0]->sw_if_index);
4323 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4324 adj_unlock(locked_ai);
4325
4326 /*
4327 * no more entires. +1 shared path-list
4328 */
4329 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4330 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004331 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004332 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004333 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004334 fib_entry_pool_size());
4335
4336 /*
4337 * remove the API source from the default route. We expected
4338 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4339 */
4340 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4341 FIB_SOURCE_API,
4342 FIB_PROTOCOL_IP6,
4343 &nh_2001_2,
4344 tm->hw[0]->sw_if_index,
4345 ~0,
4346 1,
4347 FIB_ROUTE_PATH_FLAG_NONE);
4348 fei = fib_table_lookup(fib_index, &pfx_0_0);
4349
4350 FIB_TEST((fei == dfrt), "default route same index");
4351 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4352 "Default route is DROP");
4353
4354 /*
4355 * no more entires. -1 shared path-list
4356 */
4357 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4358 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004359 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004360 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004361 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004362 fib_entry_pool_size());
4363
4364 /*
4365 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4366 */
4367 fib_prefix_t pfx_2001_1_2_s_128 = {
4368 .fp_len = 128,
4369 .fp_proto = FIB_PROTOCOL_IP6,
4370 .fp_addr = {
4371 .ip6 = {
4372 .as_u64 = {
4373 [0] = clib_host_to_net_u64(0x2001000000000001),
4374 [1] = clib_host_to_net_u64(0x0000000000000002),
4375 },
4376 },
4377 }
4378 };
4379 fib_prefix_t pfx_2001_1_3_s_128 = {
4380 .fp_len = 128,
4381 .fp_proto = FIB_PROTOCOL_IP6,
4382 .fp_addr = {
4383 .ip6 = {
4384 .as_u64 = {
4385 [0] = clib_host_to_net_u64(0x2001000000000001),
4386 [1] = clib_host_to_net_u64(0x0000000000000003),
4387 },
4388 },
4389 }
4390 };
4391 u8 eth_addr[] = {
4392 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4393 };
4394
4395 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004396 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004397 &pfx_2001_1_2_s_128.fp_addr,
4398 tm->hw[0]->sw_if_index);
4399 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4400 adj = adj_get(ai_01);
4401 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4402 "adj is incomplete");
4403 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4404 &adj->sub_type.nbr.next_hop)),
4405 "adj nbr next-hop ok");
4406
Neale Rannsb80c5362016-10-08 13:03:40 +01004407 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4408 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004409 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4410 "adj is complete");
4411 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4412 &adj->sub_type.nbr.next_hop)),
4413 "adj nbr next-hop ok");
4414
Neale Ranns81424992017-05-18 03:03:22 -07004415 fib_table_entry_path_add(fib_index,
4416 &pfx_2001_1_2_s_128,
4417 FIB_SOURCE_ADJ,
4418 FIB_ENTRY_FLAG_ATTACHED,
4419 FIB_PROTOCOL_IP6,
4420 &pfx_2001_1_2_s_128.fp_addr,
4421 tm->hw[0]->sw_if_index,
4422 ~0,
4423 1,
4424 NULL,
4425 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004426
4427 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4428 ai = fib_entry_get_adj(fei);
4429 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4430
4431 eth_addr[5] = 0xb2;
4432
4433 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004434 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004435 &pfx_2001_1_3_s_128.fp_addr,
4436 tm->hw[0]->sw_if_index);
4437 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4438 adj = adj_get(ai_02);
4439 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4440 "adj is incomplete");
4441 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4442 &adj->sub_type.nbr.next_hop)),
4443 "adj nbr next-hop ok");
4444
Neale Rannsb80c5362016-10-08 13:03:40 +01004445 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4446 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004447 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4448 "adj is complete");
4449 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4450 &adj->sub_type.nbr.next_hop)),
4451 "adj nbr next-hop ok");
4452 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4453
Neale Ranns81424992017-05-18 03:03:22 -07004454 fib_table_entry_path_add(fib_index,
4455 &pfx_2001_1_3_s_128,
4456 FIB_SOURCE_ADJ,
4457 FIB_ENTRY_FLAG_ATTACHED,
4458 FIB_PROTOCOL_IP6,
4459 &pfx_2001_1_3_s_128.fp_addr,
4460 tm->hw[0]->sw_if_index,
4461 ~0,
4462 1,
4463 NULL,
4464 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004465
4466 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4467 ai = fib_entry_get_adj(fei);
4468 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4469
4470 /*
4471 * +2 entries, +2 unshread path-lists.
4472 */
4473 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4474 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004475 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004476 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004477 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004478 fib_entry_pool_size());
4479
4480 /*
4481 * Add a 2 routes via the first ADJ. ensure path-list sharing
4482 */
4483 fib_prefix_t pfx_2001_a_s_64 = {
4484 .fp_len = 64,
4485 .fp_proto = FIB_PROTOCOL_IP6,
4486 .fp_addr = {
4487 .ip6 = {
4488 .as_u64 = {
4489 [0] = clib_host_to_net_u64(0x200100000000000a),
4490 [1] = clib_host_to_net_u64(0x0000000000000000),
4491 },
4492 },
4493 }
4494 };
4495 fib_prefix_t pfx_2001_b_s_64 = {
4496 .fp_len = 64,
4497 .fp_proto = FIB_PROTOCOL_IP6,
4498 .fp_addr = {
4499 .ip6 = {
4500 .as_u64 = {
4501 [0] = clib_host_to_net_u64(0x200100000000000b),
4502 [1] = clib_host_to_net_u64(0x0000000000000000),
4503 },
4504 },
4505 }
4506 };
4507
4508 fib_table_entry_path_add(fib_index,
4509 &pfx_2001_a_s_64,
4510 FIB_SOURCE_API,
4511 FIB_ENTRY_FLAG_NONE,
4512 FIB_PROTOCOL_IP6,
4513 &nh_2001_2,
4514 tm->hw[0]->sw_if_index,
4515 ~0,
4516 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004517 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004518 FIB_ROUTE_PATH_FLAG_NONE);
4519 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4520 ai = fib_entry_get_adj(fei);
4521 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4522 fib_table_entry_path_add(fib_index,
4523 &pfx_2001_b_s_64,
4524 FIB_SOURCE_API,
4525 FIB_ENTRY_FLAG_NONE,
4526 FIB_PROTOCOL_IP6,
4527 &nh_2001_2,
4528 tm->hw[0]->sw_if_index,
4529 ~0,
4530 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004531 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004532 FIB_ROUTE_PATH_FLAG_NONE);
4533 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4534 ai = fib_entry_get_adj(fei);
4535 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4536
4537 /*
4538 * +2 entries, +1 shared path-list.
4539 */
4540 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4541 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004542 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004543 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004544 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004545 fib_entry_pool_size());
4546
4547 /*
4548 * add a v4 prefix via a v6 next-hop
4549 */
4550 fib_prefix_t pfx_1_1_1_1_s_32 = {
4551 .fp_len = 32,
4552 .fp_proto = FIB_PROTOCOL_IP4,
4553 .fp_addr = {
4554 .ip4.as_u32 = 0x01010101,
4555 },
4556 };
4557 fei = fib_table_entry_path_add(0, // default table
4558 &pfx_1_1_1_1_s_32,
4559 FIB_SOURCE_API,
4560 FIB_ENTRY_FLAG_NONE,
4561 FIB_PROTOCOL_IP6,
4562 &nh_2001_2,
4563 tm->hw[0]->sw_if_index,
4564 ~0,
4565 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004566 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004567 FIB_ROUTE_PATH_FLAG_NONE);
4568 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4569 "1.1.1.1/32 o v6 route present");
4570 ai = fib_entry_get_adj(fei);
4571 adj = adj_get(ai);
4572 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4573 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004574 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004575 "1.1.1.1/32 ADJ-adj is link type v4");
4576 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4577 "1.1.1.1/32 ADJ-adj is NH proto v6");
4578 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4579
4580 /*
4581 * An attached route
4582 */
4583 fib_prefix_t pfx_2001_c_s_64 = {
4584 .fp_len = 64,
4585 .fp_proto = FIB_PROTOCOL_IP6,
4586 .fp_addr = {
4587 .ip6 = {
4588 .as_u64 = {
4589 [0] = clib_host_to_net_u64(0x200100000000000c),
4590 [1] = clib_host_to_net_u64(0x0000000000000000),
4591 },
4592 },
4593 }
4594 };
4595 fib_table_entry_path_add(fib_index,
4596 &pfx_2001_c_s_64,
4597 FIB_SOURCE_CLI,
4598 FIB_ENTRY_FLAG_ATTACHED,
4599 FIB_PROTOCOL_IP6,
4600 NULL,
4601 tm->hw[0]->sw_if_index,
4602 ~0,
4603 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004604 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004605 FIB_ROUTE_PATH_FLAG_NONE);
4606 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4607 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4608 ai = fib_entry_get_adj(fei);
4609 adj = adj_get(ai);
4610 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4611 "2001:0:0:c/64 attached resolves via glean");
4612
4613 fib_table_entry_path_remove(fib_index,
4614 &pfx_2001_c_s_64,
4615 FIB_SOURCE_CLI,
4616 FIB_PROTOCOL_IP6,
4617 NULL,
4618 tm->hw[0]->sw_if_index,
4619 ~0,
4620 1,
4621 FIB_ROUTE_PATH_FLAG_NONE);
4622 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4623 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4624
4625 /*
4626 * Shutdown the interface on which we have a connected and through
4627 * which the routes are reachable.
4628 * This will result in the connected, adj-fibs, and routes linking to drop
4629 * The local/for-us prefix continues to receive.
4630 */
4631 clib_error_t * error;
4632
4633 error = vnet_sw_interface_set_flags(vnet_get_main(),
4634 tm->hw[0]->sw_if_index,
4635 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4636 FIB_TEST((NULL == error), "Interface shutdown OK");
4637
4638 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4639 dpo = fib_entry_contribute_ip_forwarding(fei);
4640 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4641 "2001::b/64 resolves via drop");
4642
4643 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4644 dpo = fib_entry_contribute_ip_forwarding(fei);
4645 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4646 "2001::a/64 resolves via drop");
4647 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4648 dpo = fib_entry_contribute_ip_forwarding(fei);
4649 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4650 "2001:0:0:1::3/64 resolves via drop");
4651 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4652 dpo = fib_entry_contribute_ip_forwarding(fei);
4653 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4654 "2001:0:0:1::2/64 resolves via drop");
4655 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4656 dpo = fib_entry_contribute_ip_forwarding(fei);
4657 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4658 "2001:0:0:1::1/128 not drop");
4659 local_pfx.fp_len = 64;
4660 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4661 dpo = fib_entry_contribute_ip_forwarding(fei);
4662 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4663 "2001:0:0:1/64 resolves via drop");
4664
4665 /*
4666 * no change
4667 */
4668 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4669 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004670 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004671 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004672 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004673 fib_entry_pool_size());
4674
4675 /*
4676 * shutdown one of the other interfaces, then add a connected.
4677 * and swap one of the routes to it.
4678 */
4679 error = vnet_sw_interface_set_flags(vnet_get_main(),
4680 tm->hw[1]->sw_if_index,
4681 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4682 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4683
4684 fib_prefix_t connected_pfx = {
4685 .fp_len = 64,
4686 .fp_proto = FIB_PROTOCOL_IP6,
4687 .fp_addr = {
4688 .ip6 = {
4689 /* 2001:0:0:2::1/64 */
4690 .as_u64 = {
4691 [0] = clib_host_to_net_u64(0x2001000000000002),
4692 [1] = clib_host_to_net_u64(0x0000000000000001),
4693 },
4694 },
4695 }
4696 };
4697 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4698 FIB_SOURCE_INTERFACE,
4699 (FIB_ENTRY_FLAG_CONNECTED |
4700 FIB_ENTRY_FLAG_ATTACHED),
4701 FIB_PROTOCOL_IP6,
4702 NULL,
4703 tm->hw[1]->sw_if_index,
4704 ~0,
4705 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004706 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004707 FIB_ROUTE_PATH_FLAG_NONE);
4708 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4709 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4710 dpo = fib_entry_contribute_ip_forwarding(fei);
4711 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4712 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4713 "2001:0:0:2/64 not resolves via drop");
4714
4715 connected_pfx.fp_len = 128;
4716 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4717 FIB_SOURCE_INTERFACE,
4718 (FIB_ENTRY_FLAG_CONNECTED |
4719 FIB_ENTRY_FLAG_LOCAL),
4720 FIB_PROTOCOL_IP6,
4721 NULL,
4722 tm->hw[0]->sw_if_index,
4723 ~0, // invalid fib index
4724 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004725 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004726 FIB_ROUTE_PATH_FLAG_NONE);
4727 fei = fib_table_lookup(fib_index, &connected_pfx);
4728
4729 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4730 dpo = fib_entry_contribute_ip_forwarding(fei);
4731 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4732 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4733 "local interface adj is local");
4734 rd = receive_dpo_get(dpo->dpoi_index);
4735 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4736 &rd->rd_addr)),
4737 "local interface adj is receive ok");
4738
4739 /*
4740 * +2 entries, +2 unshared path-lists
4741 */
4742 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4743 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004744 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004745 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004746 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004747 fib_entry_pool_size());
4748
4749
4750 /*
4751 * bring the interface back up. we expected the routes to return
4752 * to normal forwarding.
4753 */
4754 error = vnet_sw_interface_set_flags(vnet_get_main(),
4755 tm->hw[0]->sw_if_index,
4756 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4757 FIB_TEST((NULL == error), "Interface bring-up OK");
4758 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4759 ai = fib_entry_get_adj(fei);
4760 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4761 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4762 ai = fib_entry_get_adj(fei);
4763 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4764 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4765 ai = fib_entry_get_adj(fei);
4766 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4767 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4768 ai = fib_entry_get_adj(fei);
4769 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4770 local_pfx.fp_len = 64;
4771 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4772 ai = fib_entry_get_adj(fei);
4773 adj = adj_get(ai);
4774 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4775 "attached interface adj is glean");
4776
4777 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004778 * Same test as above, but this time the HW interface goes down
4779 */
4780 error = vnet_hw_interface_set_flags(vnet_get_main(),
4781 tm->hw_if_indicies[0],
4782 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4783 FIB_TEST((NULL == error), "Interface shutdown OK");
4784
4785 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4786 dpo = fib_entry_contribute_ip_forwarding(fei);
4787 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4788 "2001::b/64 resolves via drop");
4789 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4790 dpo = fib_entry_contribute_ip_forwarding(fei);
4791 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4792 "2001::a/64 resolves via drop");
4793 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4794 dpo = fib_entry_contribute_ip_forwarding(fei);
4795 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4796 "2001:0:0:1::3/128 resolves via drop");
4797 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4798 dpo = fib_entry_contribute_ip_forwarding(fei);
4799 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4800 "2001:0:0:1::2/128 resolves via drop");
4801 local_pfx.fp_len = 128;
4802 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4803 dpo = fib_entry_contribute_ip_forwarding(fei);
4804 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4805 "2001:0:0:1::1/128 not drop");
4806 local_pfx.fp_len = 64;
4807 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4808 dpo = fib_entry_contribute_ip_forwarding(fei);
4809 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4810 "2001:0:0:1/64 resolves via drop");
4811
4812 error = vnet_hw_interface_set_flags(vnet_get_main(),
4813 tm->hw_if_indicies[0],
4814 VNET_HW_INTERFACE_FLAG_LINK_UP);
4815 FIB_TEST((NULL == error), "Interface bring-up OK");
4816 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4817 ai = fib_entry_get_adj(fei);
4818 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4819 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4820 ai = fib_entry_get_adj(fei);
4821 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4822 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4823 ai = fib_entry_get_adj(fei);
4824 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4825 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4826 ai = fib_entry_get_adj(fei);
4827 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4828 local_pfx.fp_len = 64;
4829 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4830 ai = fib_entry_get_adj(fei);
4831 adj = adj_get(ai);
4832 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4833 "attached interface adj is glean");
4834
4835 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004836 * Delete the interface that the routes reolve through.
4837 * Again no routes are removed. They all point to drop.
4838 *
4839 * This is considered an error case. The control plane should
4840 * not remove interfaces through which routes resolve, but
4841 * such things can happen. ALL affected routes will drop.
4842 */
4843 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4844
4845 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4846 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4847 "2001::b/64 resolves via drop");
4848 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4849 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4850 "2001::b/64 resolves via drop");
4851 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4852 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4853 "2001:0:0:1::3/64 resolves via drop");
4854 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4855 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4856 "2001:0:0:1::2/64 resolves via drop");
4857 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4858 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4859 "2001:0:0:1::1/128 is drop");
4860 local_pfx.fp_len = 64;
4861 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4862 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4863 "2001:0:0:1/64 resolves via drop");
4864
4865 /*
4866 * no change
4867 */
4868 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4869 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004870 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004871 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004872 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004873 fib_entry_pool_size());
4874
4875 /*
4876 * Add the interface back. routes stay unresolved.
4877 */
4878 error = ethernet_register_interface(vnet_get_main(),
4879 test_interface_device_class.index,
4880 0 /* instance */,
4881 hw_address,
4882 &tm->hw_if_indicies[0],
4883 /* flag change */ 0);
4884
4885 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4886 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4887 "2001::b/64 resolves via drop");
4888 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4889 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4890 "2001::b/64 resolves via drop");
4891 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4892 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4893 "2001:0:0:1::3/64 resolves via drop");
4894 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4895 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4896 "2001:0:0:1::2/64 resolves via drop");
4897 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4898 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4899 "2001:0:0:1::1/128 is drop");
4900 local_pfx.fp_len = 64;
4901 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4902 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4903 "2001:0:0:1/64 resolves via drop");
4904
4905 /*
4906 * CLEANUP ALL the routes
4907 */
4908 fib_table_entry_delete(fib_index,
4909 &pfx_2001_c_s_64,
4910 FIB_SOURCE_API);
4911 fib_table_entry_delete(fib_index,
4912 &pfx_2001_a_s_64,
4913 FIB_SOURCE_API);
4914 fib_table_entry_delete(fib_index,
4915 &pfx_2001_b_s_64,
4916 FIB_SOURCE_API);
4917 fib_table_entry_delete(fib_index,
4918 &pfx_2001_1_3_s_128,
4919 FIB_SOURCE_ADJ);
4920 fib_table_entry_delete(fib_index,
4921 &pfx_2001_1_2_s_128,
4922 FIB_SOURCE_ADJ);
4923 local_pfx.fp_len = 64;
4924 fib_table_entry_delete(fib_index, &local_pfx,
4925 FIB_SOURCE_INTERFACE);
4926 local_pfx.fp_len = 128;
4927 fib_table_entry_special_remove(fib_index, &local_pfx,
4928 FIB_SOURCE_INTERFACE);
4929 connected_pfx.fp_len = 64;
4930 fib_table_entry_delete(fib_index, &connected_pfx,
4931 FIB_SOURCE_INTERFACE);
4932 connected_pfx.fp_len = 128;
4933 fib_table_entry_special_remove(fib_index, &connected_pfx,
4934 FIB_SOURCE_INTERFACE);
4935
4936 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4937 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4938 "2001::a/64 removed");
4939 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4940 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4941 "2001::b/64 removed");
4942 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4943 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4944 "2001:0:0:1::3/128 removed");
4945 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4946 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4947 "2001:0:0:1::3/128 removed");
4948 local_pfx.fp_len = 64;
4949 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4950 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4951 "2001:0:0:1/64 removed");
4952 local_pfx.fp_len = 128;
4953 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4954 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4955 "2001:0:0:1::1/128 removed");
4956 connected_pfx.fp_len = 64;
4957 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4958 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4959 "2001:0:0:2/64 removed");
4960 connected_pfx.fp_len = 128;
4961 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4962 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4963 "2001:0:0:2::1/128 removed");
4964
4965 /*
4966 * -8 entries. -7 path-lists (1 was shared).
4967 */
4968 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4969 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004970 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004971 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004972 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004973 fib_entry_pool_size());
4974
4975 /*
4976 * now remove the VRF
4977 */
4978 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4979
4980 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4981 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004982 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004983 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004984 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004985 fib_entry_pool_size());
4986
4987 adj_unlock(ai_02);
4988 adj_unlock(ai_01);
4989
4990 /*
4991 * return the interfaces to up state
4992 */
4993 error = vnet_sw_interface_set_flags(vnet_get_main(),
4994 tm->hw[0]->sw_if_index,
4995 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4996 error = vnet_sw_interface_set_flags(vnet_get_main(),
4997 tm->hw[1]->sw_if_index,
4998 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4999
5000 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5001 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005002
5003 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005004}
5005
5006/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005007 * Test Attached Exports
5008 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005009static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005010fib_test_ae (void)
5011{
5012 const dpo_id_t *dpo, *dpo_drop;
5013 const u32 fib_index = 0;
5014 fib_node_index_t fei;
5015 test_main_t *tm;
5016 ip4_main_t *im;
5017
5018 tm = &test_main;
5019 im = &ip4_main;
5020
5021 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5022 adj_nbr_db_size());
5023
5024 /*
5025 * add interface routes. We'll assume this works. It's more rigorously
5026 * tested elsewhere.
5027 */
5028 fib_prefix_t local_pfx = {
5029 .fp_len = 24,
5030 .fp_proto = FIB_PROTOCOL_IP4,
5031 .fp_addr = {
5032 .ip4 = {
5033 /* 10.10.10.10 */
5034 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5035 },
5036 },
5037 };
5038
5039 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5040 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5041
5042 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5043
5044 fib_table_entry_update_one_path(fib_index, &local_pfx,
5045 FIB_SOURCE_INTERFACE,
5046 (FIB_ENTRY_FLAG_CONNECTED |
5047 FIB_ENTRY_FLAG_ATTACHED),
5048 FIB_PROTOCOL_IP4,
5049 NULL,
5050 tm->hw[0]->sw_if_index,
5051 ~0,
5052 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005053 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005054 FIB_ROUTE_PATH_FLAG_NONE);
5055 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5056 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5057 "attached interface route present");
5058
5059 local_pfx.fp_len = 32;
5060 fib_table_entry_update_one_path(fib_index, &local_pfx,
5061 FIB_SOURCE_INTERFACE,
5062 (FIB_ENTRY_FLAG_CONNECTED |
5063 FIB_ENTRY_FLAG_LOCAL),
5064 FIB_PROTOCOL_IP4,
5065 NULL,
5066 tm->hw[0]->sw_if_index,
5067 ~0, // invalid fib index
5068 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005069 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005070 FIB_ROUTE_PATH_FLAG_NONE);
5071 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5072
5073 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5074 "local interface route present");
5075
5076 /*
5077 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5078 */
5079 fib_prefix_t pfx_10_10_10_1_s_32 = {
5080 .fp_len = 32,
5081 .fp_proto = FIB_PROTOCOL_IP4,
5082 .fp_addr = {
5083 /* 10.10.10.1 */
5084 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5085 },
5086 };
5087 fib_node_index_t ai;
5088
Neale Ranns81424992017-05-18 03:03:22 -07005089 fib_table_entry_path_add(fib_index,
5090 &pfx_10_10_10_1_s_32,
5091 FIB_SOURCE_ADJ,
5092 FIB_ENTRY_FLAG_ATTACHED,
5093 FIB_PROTOCOL_IP4,
5094 &pfx_10_10_10_1_s_32.fp_addr,
5095 tm->hw[0]->sw_if_index,
5096 ~0, // invalid fib index
5097 1,
5098 NULL,
5099 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005100
5101 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5102 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5103 ai = fib_entry_get_adj(fei);
5104
5105 /*
5106 * create another FIB table into which routes will be imported
5107 */
5108 u32 import_fib_index1;
5109
5110 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
5111
5112 /*
5113 * Add an attached route in the import FIB
5114 */
5115 local_pfx.fp_len = 24;
5116 fib_table_entry_update_one_path(import_fib_index1,
5117 &local_pfx,
5118 FIB_SOURCE_API,
5119 FIB_ENTRY_FLAG_NONE,
5120 FIB_PROTOCOL_IP4,
5121 NULL,
5122 tm->hw[0]->sw_if_index,
5123 ~0, // invalid fib index
5124 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005125 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005126 FIB_ROUTE_PATH_FLAG_NONE);
5127 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5128 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5129
5130 /*
5131 * check for the presence of the adj-fibs in the import table
5132 */
5133 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5134 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5135 FIB_TEST((ai == fib_entry_get_adj(fei)),
5136 "adj-fib1 Import uses same adj as export");
5137
5138 /*
5139 * check for the presence of the local in the import table
5140 */
5141 local_pfx.fp_len = 32;
5142 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5143 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5144
5145 /*
5146 * Add another adj-fin in the export table. Expect this
5147 * to get magically exported;
5148 */
5149 fib_prefix_t pfx_10_10_10_2_s_32 = {
5150 .fp_len = 32,
5151 .fp_proto = FIB_PROTOCOL_IP4,
5152 .fp_addr = {
5153 /* 10.10.10.2 */
5154 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5155 },
5156 };
5157
Neale Ranns81424992017-05-18 03:03:22 -07005158 fib_table_entry_path_add(fib_index,
5159 &pfx_10_10_10_2_s_32,
5160 FIB_SOURCE_ADJ,
5161 FIB_ENTRY_FLAG_ATTACHED,
5162 FIB_PROTOCOL_IP4,
5163 &pfx_10_10_10_2_s_32.fp_addr,
5164 tm->hw[0]->sw_if_index,
5165 ~0, // invalid fib index
5166 1,
5167 NULL,
5168 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005169 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5170 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5171 ai = fib_entry_get_adj(fei);
5172
5173 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5174 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5175 FIB_TEST((ai == fib_entry_get_adj(fei)),
5176 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005177 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5178 "ADJ-fib2 imported flags %d",
5179 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005180
5181 /*
5182 * create a 2nd FIB table into which routes will be imported
5183 */
5184 u32 import_fib_index2;
5185
5186 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
5187
5188 /*
5189 * Add an attached route in the import FIB
5190 */
5191 local_pfx.fp_len = 24;
5192 fib_table_entry_update_one_path(import_fib_index2,
5193 &local_pfx,
5194 FIB_SOURCE_API,
5195 FIB_ENTRY_FLAG_NONE,
5196 FIB_PROTOCOL_IP4,
5197 NULL,
5198 tm->hw[0]->sw_if_index,
5199 ~0, // invalid fib index
5200 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005201 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005202 FIB_ROUTE_PATH_FLAG_NONE);
5203 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5204 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5205
5206 /*
5207 * check for the presence of all the adj-fibs and local in the import table
5208 */
5209 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5210 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5211 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5212 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5213 local_pfx.fp_len = 32;
5214 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5215 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5216
5217 /*
5218 * add a 3rd adj-fib. expect it to be exported to both tables.
5219 */
5220 fib_prefix_t pfx_10_10_10_3_s_32 = {
5221 .fp_len = 32,
5222 .fp_proto = FIB_PROTOCOL_IP4,
5223 .fp_addr = {
5224 /* 10.10.10.3 */
5225 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5226 },
5227 };
5228
Neale Ranns81424992017-05-18 03:03:22 -07005229 fib_table_entry_path_add(fib_index,
5230 &pfx_10_10_10_3_s_32,
5231 FIB_SOURCE_ADJ,
5232 FIB_ENTRY_FLAG_ATTACHED,
5233 FIB_PROTOCOL_IP4,
5234 &pfx_10_10_10_3_s_32.fp_addr,
5235 tm->hw[0]->sw_if_index,
5236 ~0, // invalid fib index
5237 1,
5238 NULL,
5239 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005240 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5241 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5242 ai = fib_entry_get_adj(fei);
5243
5244 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5245 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5246 FIB_TEST((ai == fib_entry_get_adj(fei)),
5247 "Import uses same adj as export");
5248 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5249 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5250 FIB_TEST((ai == fib_entry_get_adj(fei)),
5251 "Import uses same adj as export");
5252
5253 /*
5254 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5255 */
5256 fib_table_entry_delete(fib_index,
5257 &pfx_10_10_10_3_s_32,
5258 FIB_SOURCE_ADJ);
5259
5260 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5261 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5262
5263 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5264 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5265
5266 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5267 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5268
5269 /*
5270 * remove the attached route from the 2nd FIB. expect the imported
5271 * entires to be removed
5272 */
5273 local_pfx.fp_len = 24;
5274 fib_table_entry_delete(import_fib_index2,
5275 &local_pfx,
5276 FIB_SOURCE_API);
5277 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5278 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5279
5280 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5281 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5282 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5283 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5284 local_pfx.fp_len = 32;
5285 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5286 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5287
5288 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5289 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5290 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5291 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5292 local_pfx.fp_len = 32;
5293 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5294 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5295
5296 /*
5297 * modify the route in FIB1 so it is no longer attached. expect the imported
5298 * entires to be removed
5299 */
5300 local_pfx.fp_len = 24;
5301 fib_table_entry_update_one_path(import_fib_index1,
5302 &local_pfx,
5303 FIB_SOURCE_API,
5304 FIB_ENTRY_FLAG_NONE,
5305 FIB_PROTOCOL_IP4,
5306 &pfx_10_10_10_2_s_32.fp_addr,
5307 tm->hw[0]->sw_if_index,
5308 ~0, // invalid fib index
5309 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005310 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005311 FIB_ROUTE_PATH_FLAG_NONE);
5312 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5313 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5314 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5315 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5316 local_pfx.fp_len = 32;
5317 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5318 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5319
5320 /*
5321 * modify it back to attached. expect the adj-fibs back
5322 */
5323 local_pfx.fp_len = 24;
5324 fib_table_entry_update_one_path(import_fib_index1,
5325 &local_pfx,
5326 FIB_SOURCE_API,
5327 FIB_ENTRY_FLAG_NONE,
5328 FIB_PROTOCOL_IP4,
5329 NULL,
5330 tm->hw[0]->sw_if_index,
5331 ~0, // invalid fib index
5332 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005333 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005334 FIB_ROUTE_PATH_FLAG_NONE);
5335 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5336 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5337 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5338 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5339 local_pfx.fp_len = 32;
5340 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5341 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5342
5343 /*
5344 * add a covering attached next-hop for the interface address, so we have
5345 * a valid adj to find when we check the forwarding tables
5346 */
5347 fib_prefix_t pfx_10_0_0_0_s_8 = {
5348 .fp_len = 8,
5349 .fp_proto = FIB_PROTOCOL_IP4,
5350 .fp_addr = {
5351 /* 10.0.0.0 */
5352 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5353 },
5354 };
5355
5356 fei = fib_table_entry_update_one_path(fib_index,
5357 &pfx_10_0_0_0_s_8,
5358 FIB_SOURCE_API,
5359 FIB_ENTRY_FLAG_NONE,
5360 FIB_PROTOCOL_IP4,
5361 &pfx_10_10_10_3_s_32.fp_addr,
5362 tm->hw[0]->sw_if_index,
5363 ~0, // invalid fib index
5364 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005365 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005366 FIB_ROUTE_PATH_FLAG_NONE);
5367 dpo = fib_entry_contribute_ip_forwarding(fei);
5368
5369 /*
5370 * remove the route in the export fib. expect the adj-fibs to be removed
5371 */
5372 local_pfx.fp_len = 24;
5373 fib_table_entry_delete(fib_index,
5374 &local_pfx,
5375 FIB_SOURCE_INTERFACE);
5376
5377 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5378 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5379 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5380 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5381 local_pfx.fp_len = 32;
5382 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5383 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5384
5385 /*
5386 * the adj-fibs in the export VRF are present in the FIB table,
5387 * but not installed in forwarding, since they have no attached cover.
5388 * Consequently a lookup in the MTRIE gives the adj for the covering
5389 * route 10.0.0.0/8.
5390 */
5391 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5392 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5393
5394 index_t lbi;
5395 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5396 FIB_TEST(lbi == dpo->dpoi_index,
5397 "10.10.10.1 forwards on \n%U not \n%U",
5398 format_load_balance, lbi, 0,
5399 format_dpo_id, dpo, 0);
5400 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5401 FIB_TEST(lbi == dpo->dpoi_index,
5402 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5403 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5404 FIB_TEST(lbi == dpo->dpoi_index,
5405 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5406
5407 /*
5408 * add the export prefix back, but not as attached.
5409 * No adj-fibs in export nor import tables
5410 */
5411 local_pfx.fp_len = 24;
5412 fei = fib_table_entry_update_one_path(fib_index,
5413 &local_pfx,
5414 FIB_SOURCE_API,
5415 FIB_ENTRY_FLAG_NONE,
5416 FIB_PROTOCOL_IP4,
5417 &pfx_10_10_10_1_s_32.fp_addr,
5418 tm->hw[0]->sw_if_index,
5419 ~0, // invalid fib index
5420 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005421 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005422 FIB_ROUTE_PATH_FLAG_NONE);
5423 dpo = fib_entry_contribute_ip_forwarding(fei);
5424
5425 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5426 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5427 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5428 FIB_TEST(lbi == dpo->dpoi_index,
5429 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5430 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5431 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5432 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5433 FIB_TEST(lbi == dpo->dpoi_index,
5434 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5435
5436 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5437 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5438 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5439 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5440 local_pfx.fp_len = 32;
5441 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5442 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5443
5444 /*
5445 * modify the export prefix so it is attached. expect all covereds to return
5446 */
5447 local_pfx.fp_len = 24;
5448 fib_table_entry_update_one_path(fib_index,
5449 &local_pfx,
5450 FIB_SOURCE_API,
5451 FIB_ENTRY_FLAG_NONE,
5452 FIB_PROTOCOL_IP4,
5453 NULL,
5454 tm->hw[0]->sw_if_index,
5455 ~0, // invalid fib index
5456 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005457 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005458 FIB_ROUTE_PATH_FLAG_NONE);
5459
5460 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5461 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5462 dpo = fib_entry_contribute_ip_forwarding(fei);
5463 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5464 "Adj-fib1 is not drop in export");
5465 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5466 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5467 local_pfx.fp_len = 32;
5468 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5469 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5470 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5471 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5472 dpo = fib_entry_contribute_ip_forwarding(fei);
5473 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5474 "Adj-fib1 is not drop in export");
5475 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5476 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5477 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5478 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5479 local_pfx.fp_len = 32;
5480 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5481 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5482
5483 /*
5484 * modify the export prefix so connected. no change.
5485 */
5486 local_pfx.fp_len = 24;
5487 fib_table_entry_update_one_path(fib_index, &local_pfx,
5488 FIB_SOURCE_INTERFACE,
5489 (FIB_ENTRY_FLAG_CONNECTED |
5490 FIB_ENTRY_FLAG_ATTACHED),
5491 FIB_PROTOCOL_IP4,
5492 NULL,
5493 tm->hw[0]->sw_if_index,
5494 ~0,
5495 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005496 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005497 FIB_ROUTE_PATH_FLAG_NONE);
5498
5499 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5500 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5501 dpo = fib_entry_contribute_ip_forwarding(fei);
5502 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5503 "Adj-fib1 is not drop in export");
5504 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5505 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5506 local_pfx.fp_len = 32;
5507 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5508 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5509 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5510 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5511 dpo = fib_entry_contribute_ip_forwarding(fei);
5512 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5513 "Adj-fib1 is not drop in export");
5514 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5515 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5516 local_pfx.fp_len = 32;
5517 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5518 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5519
5520 /*
5521 * CLEANUP
5522 */
5523 fib_table_entry_delete(fib_index,
5524 &pfx_10_0_0_0_s_8,
5525 FIB_SOURCE_API);
5526 fib_table_entry_delete(fib_index,
5527 &pfx_10_10_10_1_s_32,
5528 FIB_SOURCE_ADJ);
5529 fib_table_entry_delete(fib_index,
5530 &pfx_10_10_10_2_s_32,
5531 FIB_SOURCE_ADJ);
5532 local_pfx.fp_len = 32;
5533 fib_table_entry_delete(fib_index,
5534 &local_pfx,
5535 FIB_SOURCE_INTERFACE);
5536 local_pfx.fp_len = 24;
5537 fib_table_entry_delete(fib_index,
5538 &local_pfx,
5539 FIB_SOURCE_API);
5540 fib_table_entry_delete(fib_index,
5541 &local_pfx,
5542 FIB_SOURCE_INTERFACE);
5543 local_pfx.fp_len = 24;
5544 fib_table_entry_delete(import_fib_index1,
5545 &local_pfx,
5546 FIB_SOURCE_API);
5547
5548 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5549 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5550
5551 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5552 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005553
5554 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005555}
5556
Neale Rannsad422ed2016-11-02 14:20:04 +00005557
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005558/*
5559 * Test the recursive route route handling for GRE tunnels
5560 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005561static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005562fib_test_label (void)
5563{
5564 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;
5565 const u32 fib_index = 0;
5566 test_main_t *tm;
5567 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005568 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005569
5570 lb_count = pool_elts(load_balance_pool);
5571 tm = &test_main;
5572 im = &ip4_main;
5573
5574 /*
5575 * add interface routes. We'll assume this works. It's more rigorously
5576 * tested elsewhere.
5577 */
5578 fib_prefix_t local0_pfx = {
5579 .fp_len = 24,
5580 .fp_proto = FIB_PROTOCOL_IP4,
5581 .fp_addr = {
5582 .ip4 = {
5583 /* 10.10.10.10 */
5584 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5585 },
5586 },
5587 };
5588
5589 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5590 adj_nbr_db_size());
5591
5592 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5593 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5594
5595 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5596 FIB_SOURCE_INTERFACE,
5597 (FIB_ENTRY_FLAG_CONNECTED |
5598 FIB_ENTRY_FLAG_ATTACHED),
5599 FIB_PROTOCOL_IP4,
5600 NULL,
5601 tm->hw[0]->sw_if_index,
5602 ~0,
5603 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005604 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005605 FIB_ROUTE_PATH_FLAG_NONE);
5606 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5607 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5608 "attached interface route present");
5609
5610 local0_pfx.fp_len = 32;
5611 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5612 FIB_SOURCE_INTERFACE,
5613 (FIB_ENTRY_FLAG_CONNECTED |
5614 FIB_ENTRY_FLAG_LOCAL),
5615 FIB_PROTOCOL_IP4,
5616 NULL,
5617 tm->hw[0]->sw_if_index,
5618 ~0, // invalid fib index
5619 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005620 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005621 FIB_ROUTE_PATH_FLAG_NONE);
5622 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5623
5624 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5625 "local interface route present");
5626
5627 fib_prefix_t local1_pfx = {
5628 .fp_len = 24,
5629 .fp_proto = FIB_PROTOCOL_IP4,
5630 .fp_addr = {
5631 .ip4 = {
5632 /* 10.10.11.10 */
5633 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5634 },
5635 },
5636 };
5637
5638 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5639 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5640
5641 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5642 FIB_SOURCE_INTERFACE,
5643 (FIB_ENTRY_FLAG_CONNECTED |
5644 FIB_ENTRY_FLAG_ATTACHED),
5645 FIB_PROTOCOL_IP4,
5646 NULL,
5647 tm->hw[1]->sw_if_index,
5648 ~0,
5649 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005650 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005651 FIB_ROUTE_PATH_FLAG_NONE);
5652 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5653 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5654 "attached interface route present");
5655
5656 local1_pfx.fp_len = 32;
5657 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5658 FIB_SOURCE_INTERFACE,
5659 (FIB_ENTRY_FLAG_CONNECTED |
5660 FIB_ENTRY_FLAG_LOCAL),
5661 FIB_PROTOCOL_IP4,
5662 NULL,
5663 tm->hw[1]->sw_if_index,
5664 ~0, // invalid fib index
5665 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005666 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005667 FIB_ROUTE_PATH_FLAG_NONE);
5668 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5669
5670 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5671 "local interface route present");
5672
5673 ip46_address_t nh_10_10_10_1 = {
5674 .ip4 = {
5675 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5676 },
5677 };
5678 ip46_address_t nh_10_10_11_1 = {
5679 .ip4 = {
5680 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5681 },
5682 };
5683 ip46_address_t nh_10_10_11_2 = {
5684 .ip4 = {
5685 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5686 },
5687 };
5688
5689 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005690 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005691 &nh_10_10_11_1,
5692 tm->hw[1]->sw_if_index);
5693 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005694 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005695 &nh_10_10_11_2,
5696 tm->hw[1]->sw_if_index);
5697 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005698 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005699 &nh_10_10_10_1,
5700 tm->hw[0]->sw_if_index);
5701 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005702 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005703 &nh_10_10_11_2,
5704 tm->hw[1]->sw_if_index);
5705 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005706 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005707 &nh_10_10_11_1,
5708 tm->hw[1]->sw_if_index);
5709
5710 /*
5711 * Add an etry with one path with a real out-going label
5712 */
5713 fib_prefix_t pfx_1_1_1_1_s_32 = {
5714 .fp_len = 32,
5715 .fp_proto = FIB_PROTOCOL_IP4,
5716 .fp_addr = {
5717 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5718 },
5719 };
5720 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5721 .type = FT_LB_LABEL_O_ADJ,
5722 .label_o_adj = {
5723 .adj = ai_mpls_10_10_10_1,
5724 .label = 99,
5725 .eos = MPLS_EOS,
5726 },
5727 };
5728 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5729 .type = FT_LB_LABEL_O_ADJ,
5730 .label_o_adj = {
5731 .adj = ai_mpls_10_10_10_1,
5732 .label = 99,
5733 .eos = MPLS_NON_EOS,
5734 },
5735 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005736 mpls_label_t *l99 = NULL;
5737 vec_add1(l99, 99);
5738
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005739 fib_table_entry_update_one_path(fib_index,
5740 &pfx_1_1_1_1_s_32,
5741 FIB_SOURCE_API,
5742 FIB_ENTRY_FLAG_NONE,
5743 FIB_PROTOCOL_IP4,
5744 &nh_10_10_10_1,
5745 tm->hw[0]->sw_if_index,
5746 ~0, // invalid fib index
5747 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005748 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005749 FIB_ROUTE_PATH_FLAG_NONE);
5750
5751 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5752 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5753
5754 FIB_TEST(fib_test_validate_entry(fei,
5755 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5756 1,
5757 &l99_eos_o_10_10_10_1),
5758 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5759
5760 /*
5761 * add a path with an implicit NULL label
5762 */
5763 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5764 .type = FT_LB_ADJ,
5765 .adj = {
5766 .adj = ai_v4_10_10_11_1,
5767 },
5768 };
5769 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5770 .type = FT_LB_ADJ,
5771 .adj = {
5772 .adj = ai_mpls_10_10_11_1,
5773 },
5774 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005775 mpls_label_t *l_imp_null = NULL;
5776 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005777
5778 fei = fib_table_entry_path_add(fib_index,
5779 &pfx_1_1_1_1_s_32,
5780 FIB_SOURCE_API,
5781 FIB_ENTRY_FLAG_NONE,
5782 FIB_PROTOCOL_IP4,
5783 &nh_10_10_11_1,
5784 tm->hw[1]->sw_if_index,
5785 ~0, // invalid fib index
5786 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005787 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005788 FIB_ROUTE_PATH_FLAG_NONE);
5789
5790 FIB_TEST(fib_test_validate_entry(fei,
5791 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5792 2,
5793 &l99_eos_o_10_10_10_1,
5794 &a_o_10_10_11_1),
5795 "1.1.1.1/32 LB 2 buckets via: "
5796 "label 99 over 10.10.10.1, "
5797 "adj over 10.10.11.1");
5798
5799 /*
5800 * assign the route a local label
5801 */
5802 fib_table_entry_local_label_add(fib_index,
5803 &pfx_1_1_1_1_s_32,
5804 24001);
5805
5806 fib_prefix_t pfx_24001_eos = {
5807 .fp_proto = FIB_PROTOCOL_MPLS,
5808 .fp_label = 24001,
5809 .fp_eos = MPLS_EOS,
5810 };
5811 fib_prefix_t pfx_24001_neos = {
5812 .fp_proto = FIB_PROTOCOL_MPLS,
5813 .fp_label = 24001,
5814 .fp_eos = MPLS_NON_EOS,
5815 };
5816
5817 /*
5818 * The EOS entry should link to both the paths,
5819 * and use an ip adj for the imp-null
5820 * The NON-EOS entry should link to both the paths,
5821 * and use an mpls adj for the imp-null
5822 */
5823 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5824 &pfx_24001_eos);
5825 FIB_TEST(fib_test_validate_entry(fei,
5826 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5827 2,
5828 &l99_eos_o_10_10_10_1,
5829 &a_o_10_10_11_1),
5830 "24001/eos LB 2 buckets via: "
5831 "label 99 over 10.10.10.1, "
5832 "adj over 10.10.11.1");
5833
5834
5835 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5836 &pfx_24001_neos);
5837 FIB_TEST(fib_test_validate_entry(fei,
5838 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5839 2,
5840 &l99_neos_o_10_10_10_1,
5841 &a_mpls_o_10_10_11_1),
5842 "24001/neos LB 1 bucket via: "
5843 "label 99 over 10.10.10.1 ",
5844 "mpls-adj via 10.10.11.1");
5845
5846 /*
5847 * add an unlabelled path, this is excluded from the neos chains,
5848 */
5849 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5850 .type = FT_LB_ADJ,
5851 .adj = {
5852 .adj = ai_v4_10_10_11_2,
5853 },
5854 };
5855
5856 fei = fib_table_entry_path_add(fib_index,
5857 &pfx_1_1_1_1_s_32,
5858 FIB_SOURCE_API,
5859 FIB_ENTRY_FLAG_NONE,
5860 FIB_PROTOCOL_IP4,
5861 &nh_10_10_11_2,
5862 tm->hw[1]->sw_if_index,
5863 ~0, // invalid fib index
5864 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005865 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005866 FIB_ROUTE_PATH_FLAG_NONE);
5867
5868 FIB_TEST(fib_test_validate_entry(fei,
5869 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5870 16, // 3 choices spread over 16 buckets
5871 &l99_eos_o_10_10_10_1,
5872 &l99_eos_o_10_10_10_1,
5873 &l99_eos_o_10_10_10_1,
5874 &l99_eos_o_10_10_10_1,
5875 &l99_eos_o_10_10_10_1,
5876 &l99_eos_o_10_10_10_1,
5877 &a_o_10_10_11_1,
5878 &a_o_10_10_11_1,
5879 &a_o_10_10_11_1,
5880 &a_o_10_10_11_1,
5881 &a_o_10_10_11_1,
5882 &adj_o_10_10_11_2,
5883 &adj_o_10_10_11_2,
5884 &adj_o_10_10_11_2,
5885 &adj_o_10_10_11_2,
5886 &adj_o_10_10_11_2),
5887 "1.1.1.1/32 LB 16 buckets via: "
5888 "label 99 over 10.10.10.1, "
5889 "adj over 10.10.11.1",
5890 "adj over 10.10.11.2");
5891
5892 /*
5893 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5894 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005895 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005896 fib_entry_contribute_forwarding(fei,
5897 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5898 &non_eos_1_1_1_1);
5899
5900 /*
5901 * n-eos has only the 2 labelled paths
5902 */
5903 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5904 &pfx_24001_neos);
5905
5906 FIB_TEST(fib_test_validate_entry(fei,
5907 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5908 2,
5909 &l99_neos_o_10_10_10_1,
5910 &a_mpls_o_10_10_11_1),
5911 "24001/neos LB 2 buckets via: "
5912 "label 99 over 10.10.10.1, "
5913 "adj-mpls over 10.10.11.2");
5914
5915 /*
5916 * A labelled recursive
5917 */
5918 fib_prefix_t pfx_2_2_2_2_s_32 = {
5919 .fp_len = 32,
5920 .fp_proto = FIB_PROTOCOL_IP4,
5921 .fp_addr = {
5922 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5923 },
5924 };
5925 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5926 .type = FT_LB_LABEL_O_LB,
5927 .label_o_lb = {
5928 .lb = non_eos_1_1_1_1.dpoi_index,
5929 .label = 1600,
5930 .eos = MPLS_EOS,
5931 },
5932 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005933 mpls_label_t *l1600 = NULL;
5934 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005935
5936 fib_table_entry_update_one_path(fib_index,
5937 &pfx_2_2_2_2_s_32,
5938 FIB_SOURCE_API,
5939 FIB_ENTRY_FLAG_NONE,
5940 FIB_PROTOCOL_IP4,
5941 &pfx_1_1_1_1_s_32.fp_addr,
5942 ~0,
5943 fib_index,
5944 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005945 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005946 FIB_ROUTE_PATH_FLAG_NONE);
5947
5948 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5949 FIB_TEST(fib_test_validate_entry(fei,
5950 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5951 1,
5952 &l1600_eos_o_1_1_1_1),
5953 "2.2.2.2.2/32 LB 1 buckets via: "
5954 "label 1600 over 1.1.1.1");
5955
Neale Ranns948e00f2016-10-20 13:39:34 +01005956 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005957 index_t urpfi;
5958
5959 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5960 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5961
5962 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5963 "uRPF check for 2.2.2.2/32 on %d OK",
5964 tm->hw[0]->sw_if_index);
5965 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5966 "uRPF check for 2.2.2.2/32 on %d OK",
5967 tm->hw[1]->sw_if_index);
5968 FIB_TEST(!fib_urpf_check(urpfi, 99),
5969 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5970 99);
5971
5972 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5973 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5974 "Shared uRPF on IP and non-EOS chain");
5975
5976 dpo_reset(&dpo_44);
5977
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005978 /*
5979 * we are holding a lock on the non-eos LB of the via-entry.
5980 * do a PIC-core failover by shutting the link of the via-entry.
5981 *
5982 * shut down the link with the valid label
5983 */
5984 vnet_sw_interface_set_flags(vnet_get_main(),
5985 tm->hw[0]->sw_if_index,
5986 0);
5987
5988 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5989 FIB_TEST(fib_test_validate_entry(fei,
5990 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5991 2,
5992 &a_o_10_10_11_1,
5993 &adj_o_10_10_11_2),
5994 "1.1.1.1/32 LB 2 buckets via: "
5995 "adj over 10.10.11.1, ",
5996 "adj-v4 over 10.10.11.2");
5997
5998 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5999 &pfx_24001_eos);
6000 FIB_TEST(fib_test_validate_entry(fei,
6001 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6002 2,
6003 &a_o_10_10_11_1,
6004 &adj_o_10_10_11_2),
6005 "24001/eos LB 2 buckets via: "
6006 "adj over 10.10.11.1, ",
6007 "adj-v4 over 10.10.11.2");
6008
6009 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6010 &pfx_24001_neos);
6011 FIB_TEST(fib_test_validate_entry(fei,
6012 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6013 1,
6014 &a_mpls_o_10_10_11_1),
6015 "24001/neos LB 1 buckets via: "
6016 "adj-mpls over 10.10.11.2");
6017
6018 /*
6019 * test that the pre-failover load-balance has been in-place
6020 * modified
6021 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006022 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006023 fib_entry_contribute_forwarding(fei,
6024 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6025 &current);
6026
6027 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6028 &current),
6029 "PIC-core LB inplace modified %U %U",
6030 format_dpo_id, &non_eos_1_1_1_1, 0,
6031 format_dpo_id, &current, 0);
6032
6033 dpo_reset(&non_eos_1_1_1_1);
6034 dpo_reset(&current);
6035
6036 /*
6037 * no-shut the link with the valid label
6038 */
6039 vnet_sw_interface_set_flags(vnet_get_main(),
6040 tm->hw[0]->sw_if_index,
6041 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6042
6043 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6044 FIB_TEST(fib_test_validate_entry(fei,
6045 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6046 16, // 3 choices spread over 16 buckets
6047 &l99_eos_o_10_10_10_1,
6048 &l99_eos_o_10_10_10_1,
6049 &l99_eos_o_10_10_10_1,
6050 &l99_eos_o_10_10_10_1,
6051 &l99_eos_o_10_10_10_1,
6052 &l99_eos_o_10_10_10_1,
6053 &a_o_10_10_11_1,
6054 &a_o_10_10_11_1,
6055 &a_o_10_10_11_1,
6056 &a_o_10_10_11_1,
6057 &a_o_10_10_11_1,
6058 &adj_o_10_10_11_2,
6059 &adj_o_10_10_11_2,
6060 &adj_o_10_10_11_2,
6061 &adj_o_10_10_11_2,
6062 &adj_o_10_10_11_2),
6063 "1.1.1.1/32 LB 16 buckets via: "
6064 "label 99 over 10.10.10.1, "
6065 "adj over 10.10.11.1",
6066 "adj-v4 over 10.10.11.2");
6067
6068
6069 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6070 &pfx_24001_eos);
6071 FIB_TEST(fib_test_validate_entry(fei,
6072 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6073 16, // 3 choices spread over 16 buckets
6074 &l99_eos_o_10_10_10_1,
6075 &l99_eos_o_10_10_10_1,
6076 &l99_eos_o_10_10_10_1,
6077 &l99_eos_o_10_10_10_1,
6078 &l99_eos_o_10_10_10_1,
6079 &l99_eos_o_10_10_10_1,
6080 &a_o_10_10_11_1,
6081 &a_o_10_10_11_1,
6082 &a_o_10_10_11_1,
6083 &a_o_10_10_11_1,
6084 &a_o_10_10_11_1,
6085 &adj_o_10_10_11_2,
6086 &adj_o_10_10_11_2,
6087 &adj_o_10_10_11_2,
6088 &adj_o_10_10_11_2,
6089 &adj_o_10_10_11_2),
6090 "24001/eos LB 16 buckets via: "
6091 "label 99 over 10.10.10.1, "
6092 "adj over 10.10.11.1",
6093 "adj-v4 over 10.10.11.2");
6094
6095 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6096 &pfx_24001_neos);
6097 FIB_TEST(fib_test_validate_entry(fei,
6098 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6099 2,
6100 &l99_neos_o_10_10_10_1,
6101 &a_mpls_o_10_10_11_1),
6102 "24001/neos LB 2 buckets via: "
6103 "label 99 over 10.10.10.1, "
6104 "adj-mpls over 10.10.11.2");
6105
6106 /*
6107 * remove the first path with the valid label
6108 */
6109 fib_table_entry_path_remove(fib_index,
6110 &pfx_1_1_1_1_s_32,
6111 FIB_SOURCE_API,
6112 FIB_PROTOCOL_IP4,
6113 &nh_10_10_10_1,
6114 tm->hw[0]->sw_if_index,
6115 ~0, // invalid fib index
6116 1,
6117 FIB_ROUTE_PATH_FLAG_NONE);
6118
6119 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6120 FIB_TEST(fib_test_validate_entry(fei,
6121 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6122 2,
6123 &a_o_10_10_11_1,
6124 &adj_o_10_10_11_2),
6125 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006126 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006127 "adj-v4 over 10.10.11.2");
6128
6129 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6130 &pfx_24001_eos);
6131 FIB_TEST(fib_test_validate_entry(fei,
6132 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6133 2,
6134 &a_o_10_10_11_1,
6135 &adj_o_10_10_11_2),
6136 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006137 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006138 "adj-v4 over 10.10.11.2");
6139
6140 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6141 &pfx_24001_neos);
6142
6143 FIB_TEST(fib_test_validate_entry(fei,
6144 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6145 1,
6146 &a_mpls_o_10_10_11_1),
6147 "24001/neos LB 1 buckets via: "
6148 "adj-mpls over 10.10.11.2");
6149
6150 /*
6151 * remove the other path with a valid label
6152 */
6153 fib_test_lb_bucket_t bucket_drop = {
6154 .type = FT_LB_SPECIAL,
6155 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00006156 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006157 },
6158 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006159 fib_test_lb_bucket_t mpls_bucket_drop = {
6160 .type = FT_LB_SPECIAL,
6161 .special = {
6162 .adj = DPO_PROTO_MPLS,
6163 },
6164 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006165
6166 fib_table_entry_path_remove(fib_index,
6167 &pfx_1_1_1_1_s_32,
6168 FIB_SOURCE_API,
6169 FIB_PROTOCOL_IP4,
6170 &nh_10_10_11_1,
6171 tm->hw[1]->sw_if_index,
6172 ~0, // invalid fib index
6173 1,
6174 FIB_ROUTE_PATH_FLAG_NONE);
6175
6176 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6177 FIB_TEST(fib_test_validate_entry(fei,
6178 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6179 1,
6180 &adj_o_10_10_11_2),
6181 "1.1.1.1/32 LB 1 buckets via: "
6182 "adj over 10.10.11.2");
6183
6184 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6185 &pfx_24001_eos);
6186 FIB_TEST(fib_test_validate_entry(fei,
6187 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6188 1,
6189 &adj_o_10_10_11_2),
6190 "24001/eos LB 1 buckets via: "
6191 "adj over 10.10.11.2");
6192
6193 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6194 &pfx_24001_neos);
6195 FIB_TEST(fib_test_validate_entry(fei,
6196 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006197 1,
6198 &mpls_bucket_drop),
6199 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006200
6201 /*
6202 * add back the path with the valid label
6203 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006204 l99 = NULL;
6205 vec_add1(l99, 99);
6206
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006207 fib_table_entry_path_add(fib_index,
6208 &pfx_1_1_1_1_s_32,
6209 FIB_SOURCE_API,
6210 FIB_ENTRY_FLAG_NONE,
6211 FIB_PROTOCOL_IP4,
6212 &nh_10_10_10_1,
6213 tm->hw[0]->sw_if_index,
6214 ~0, // invalid fib index
6215 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006216 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006217 FIB_ROUTE_PATH_FLAG_NONE);
6218
6219 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6220 FIB_TEST(fib_test_validate_entry(fei,
6221 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6222 2,
6223 &l99_eos_o_10_10_10_1,
6224 &adj_o_10_10_11_2),
6225 "1.1.1.1/32 LB 2 buckets via: "
6226 "label 99 over 10.10.10.1, "
6227 "adj over 10.10.11.2");
6228
6229 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6230 &pfx_24001_eos);
6231 FIB_TEST(fib_test_validate_entry(fei,
6232 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6233 2,
6234 &l99_eos_o_10_10_10_1,
6235 &adj_o_10_10_11_2),
6236 "24001/eos LB 2 buckets via: "
6237 "label 99 over 10.10.10.1, "
6238 "adj over 10.10.11.2");
6239
6240 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6241 &pfx_24001_neos);
6242 FIB_TEST(fib_test_validate_entry(fei,
6243 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6244 1,
6245 &l99_neos_o_10_10_10_1),
6246 "24001/neos LB 1 buckets via: "
6247 "label 99 over 10.10.10.1");
6248
6249 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006250 * change the local label
6251 */
6252 fib_table_entry_local_label_add(fib_index,
6253 &pfx_1_1_1_1_s_32,
6254 25005);
6255
6256 fib_prefix_t pfx_25005_eos = {
6257 .fp_proto = FIB_PROTOCOL_MPLS,
6258 .fp_label = 25005,
6259 .fp_eos = MPLS_EOS,
6260 };
6261 fib_prefix_t pfx_25005_neos = {
6262 .fp_proto = FIB_PROTOCOL_MPLS,
6263 .fp_label = 25005,
6264 .fp_eos = MPLS_NON_EOS,
6265 };
6266
6267 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6268 fib_table_lookup(fib_index, &pfx_24001_eos)),
6269 "24001/eos removed after label change");
6270 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6271 fib_table_lookup(fib_index, &pfx_24001_neos)),
6272 "24001/eos removed after label change");
6273
6274 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6275 &pfx_25005_eos);
6276 FIB_TEST(fib_test_validate_entry(fei,
6277 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6278 2,
6279 &l99_eos_o_10_10_10_1,
6280 &adj_o_10_10_11_2),
6281 "25005/eos LB 2 buckets via: "
6282 "label 99 over 10.10.10.1, "
6283 "adj over 10.10.11.2");
6284
6285 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6286 &pfx_25005_neos);
6287 FIB_TEST(fib_test_validate_entry(fei,
6288 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6289 1,
6290 &l99_neos_o_10_10_10_1),
6291 "25005/neos LB 1 buckets via: "
6292 "label 99 over 10.10.10.1");
6293
6294 /*
6295 * remove the local label.
6296 * the check that the MPLS entries are gone is done by the fact the
6297 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006298 */
6299 fib_table_entry_local_label_remove(fib_index,
6300 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006301 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006302
6303 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6304 FIB_TEST(fib_test_validate_entry(fei,
6305 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6306 2,
6307 &l99_eos_o_10_10_10_1,
6308 &adj_o_10_10_11_2),
6309 "24001/eos LB 2 buckets via: "
6310 "label 99 over 10.10.10.1, "
6311 "adj over 10.10.11.2");
6312
6313 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6314 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6315 "No more MPLS FIB entries => table removed");
6316
6317 /*
6318 * add another via-entry for the recursive
6319 */
6320 fib_prefix_t pfx_1_1_1_2_s_32 = {
6321 .fp_len = 32,
6322 .fp_proto = FIB_PROTOCOL_IP4,
6323 .fp_addr = {
6324 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6325 },
6326 };
6327 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6328 .type = FT_LB_LABEL_O_ADJ,
6329 .label_o_adj = {
6330 .adj = ai_mpls_10_10_10_1,
6331 .label = 101,
6332 .eos = MPLS_EOS,
6333 },
6334 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006335 mpls_label_t *l101 = NULL;
6336 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006337
6338 fei = fib_table_entry_update_one_path(fib_index,
6339 &pfx_1_1_1_2_s_32,
6340 FIB_SOURCE_API,
6341 FIB_ENTRY_FLAG_NONE,
6342 FIB_PROTOCOL_IP4,
6343 &nh_10_10_10_1,
6344 tm->hw[0]->sw_if_index,
6345 ~0, // invalid fib index
6346 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006347 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006348 FIB_ROUTE_PATH_FLAG_NONE);
6349
6350 FIB_TEST(fib_test_validate_entry(fei,
6351 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6352 1,
6353 &l101_eos_o_10_10_10_1),
6354 "1.1.1.2/32 LB 1 buckets via: "
6355 "label 101 over 10.10.10.1");
6356
Neale Ranns948e00f2016-10-20 13:39:34 +01006357 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006358 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6359 &pfx_1_1_1_1_s_32),
6360 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6361 &non_eos_1_1_1_1);
6362 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6363 &pfx_1_1_1_2_s_32),
6364 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6365 &non_eos_1_1_1_2);
6366
6367 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6368 .type = FT_LB_LABEL_O_LB,
6369 .label_o_lb = {
6370 .lb = non_eos_1_1_1_2.dpoi_index,
6371 .label = 1601,
6372 .eos = MPLS_EOS,
6373 },
6374 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006375 mpls_label_t *l1601 = NULL;
6376 vec_add1(l1601, 1601);
6377
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006378 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6379
6380 fei = fib_table_entry_path_add(fib_index,
6381 &pfx_2_2_2_2_s_32,
6382 FIB_SOURCE_API,
6383 FIB_ENTRY_FLAG_NONE,
6384 FIB_PROTOCOL_IP4,
6385 &pfx_1_1_1_2_s_32.fp_addr,
6386 ~0,
6387 fib_index,
6388 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006389 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006390 FIB_ROUTE_PATH_FLAG_NONE);
6391
6392 FIB_TEST(fib_test_validate_entry(fei,
6393 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6394 2,
6395 &l1600_eos_o_1_1_1_1,
6396 &l1601_eos_o_1_1_1_2),
6397 "2.2.2.2/32 LB 2 buckets via: "
6398 "label 1600 via 1.1,1.1, "
6399 "label 16001 via 1.1.1.2");
6400
6401 /*
6402 * update the via-entry so it no longer has an imp-null path.
6403 * the LB for the recursive can use an imp-null
6404 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006405 l_imp_null = NULL;
6406 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6407
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006408 fei = fib_table_entry_update_one_path(fib_index,
6409 &pfx_1_1_1_2_s_32,
6410 FIB_SOURCE_API,
6411 FIB_ENTRY_FLAG_NONE,
6412 FIB_PROTOCOL_IP4,
6413 &nh_10_10_11_1,
6414 tm->hw[1]->sw_if_index,
6415 ~0, // invalid fib index
6416 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006417 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006418 FIB_ROUTE_PATH_FLAG_NONE);
6419
6420 FIB_TEST(fib_test_validate_entry(fei,
6421 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6422 1,
6423 &a_o_10_10_11_1),
6424 "1.1.1.2/32 LB 1 buckets via: "
6425 "adj 10.10.11.1");
6426
6427 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6428 FIB_TEST(fib_test_validate_entry(fei,
6429 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6430 2,
6431 &l1600_eos_o_1_1_1_1,
6432 &l1601_eos_o_1_1_1_2),
6433 "2.2.2.2/32 LB 2 buckets via: "
6434 "label 1600 via 1.1,1.1, "
6435 "label 16001 via 1.1.1.2");
6436
6437 /*
6438 * update the via-entry so it no longer has labelled paths.
6439 * the LB for the recursive should exclue this via form its LB
6440 */
6441 fei = fib_table_entry_update_one_path(fib_index,
6442 &pfx_1_1_1_2_s_32,
6443 FIB_SOURCE_API,
6444 FIB_ENTRY_FLAG_NONE,
6445 FIB_PROTOCOL_IP4,
6446 &nh_10_10_11_1,
6447 tm->hw[1]->sw_if_index,
6448 ~0, // invalid fib index
6449 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006450 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006451 FIB_ROUTE_PATH_FLAG_NONE);
6452
6453 FIB_TEST(fib_test_validate_entry(fei,
6454 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6455 1,
6456 &a_o_10_10_11_1),
6457 "1.1.1.2/32 LB 1 buckets via: "
6458 "adj 10.10.11.1");
6459
6460 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6461 FIB_TEST(fib_test_validate_entry(fei,
6462 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6463 1,
6464 &l1600_eos_o_1_1_1_1),
6465 "2.2.2.2/32 LB 1 buckets via: "
6466 "label 1600 via 1.1,1.1");
6467
6468 dpo_reset(&non_eos_1_1_1_1);
6469 dpo_reset(&non_eos_1_1_1_2);
6470
6471 /*
6472 * Add a recursive with no out-labels. We expect to use the IP of the via
6473 */
6474 fib_prefix_t pfx_2_2_2_3_s_32 = {
6475 .fp_len = 32,
6476 .fp_proto = FIB_PROTOCOL_IP4,
6477 .fp_addr = {
6478 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6479 },
6480 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006481 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006482
6483 fib_table_entry_update_one_path(fib_index,
6484 &pfx_2_2_2_3_s_32,
6485 FIB_SOURCE_API,
6486 FIB_ENTRY_FLAG_NONE,
6487 FIB_PROTOCOL_IP4,
6488 &pfx_1_1_1_1_s_32.fp_addr,
6489 ~0,
6490 fib_index,
6491 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006492 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006493 FIB_ROUTE_PATH_FLAG_NONE);
6494
6495 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6496 &pfx_1_1_1_1_s_32),
6497 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6498 &ip_1_1_1_1);
6499
6500 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6501 .type = FT_LB_O_LB,
6502 .lb = {
6503 .lb = ip_1_1_1_1.dpoi_index,
6504 },
6505 };
6506
6507 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6508 FIB_TEST(fib_test_validate_entry(fei,
6509 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6510 1,
6511 &ip_o_1_1_1_1),
6512 "2.2.2.2.3/32 LB 1 buckets via: "
6513 "ip 1.1.1.1");
6514
6515 /*
6516 * Add a recursive with an imp-null out-label.
6517 * We expect to use the IP of the via
6518 */
6519 fib_prefix_t pfx_2_2_2_4_s_32 = {
6520 .fp_len = 32,
6521 .fp_proto = FIB_PROTOCOL_IP4,
6522 .fp_addr = {
6523 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6524 },
6525 };
6526
6527 fib_table_entry_update_one_path(fib_index,
6528 &pfx_2_2_2_4_s_32,
6529 FIB_SOURCE_API,
6530 FIB_ENTRY_FLAG_NONE,
6531 FIB_PROTOCOL_IP4,
6532 &pfx_1_1_1_1_s_32.fp_addr,
6533 ~0,
6534 fib_index,
6535 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006536 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006537 FIB_ROUTE_PATH_FLAG_NONE);
6538
6539 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6540 FIB_TEST(fib_test_validate_entry(fei,
6541 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6542 1,
6543 &ip_o_1_1_1_1),
6544 "2.2.2.2.4/32 LB 1 buckets via: "
6545 "ip 1.1.1.1");
6546
6547 dpo_reset(&ip_1_1_1_1);
6548
6549 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006550 * Create an entry with a deep label stack
6551 */
6552 fib_prefix_t pfx_2_2_5_5_s_32 = {
6553 .fp_len = 32,
6554 .fp_proto = FIB_PROTOCOL_IP4,
6555 .fp_addr = {
6556 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6557 },
6558 };
6559 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6560 .type = FT_LB_LABEL_STACK_O_ADJ,
6561 .label_stack_o_adj = {
6562 .adj = ai_mpls_10_10_11_1,
6563 .label_stack_size = 8,
6564 .label_stack = {
6565 200, 201, 202, 203, 204, 205, 206, 207
6566 },
6567 .eos = MPLS_EOS,
6568 },
6569 };
6570 mpls_label_t *label_stack = NULL;
6571 vec_validate(label_stack, 7);
6572 for (ii = 0; ii < 8; ii++)
6573 {
6574 label_stack[ii] = ii + 200;
6575 }
6576
6577 fei = fib_table_entry_update_one_path(fib_index,
6578 &pfx_2_2_5_5_s_32,
6579 FIB_SOURCE_API,
6580 FIB_ENTRY_FLAG_NONE,
6581 FIB_PROTOCOL_IP4,
6582 &nh_10_10_11_1,
6583 tm->hw[1]->sw_if_index,
6584 ~0, // invalid fib index
6585 1,
6586 label_stack,
6587 FIB_ROUTE_PATH_FLAG_NONE);
6588
6589 FIB_TEST(fib_test_validate_entry(fei,
6590 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6591 1,
6592 &ls_eos_o_10_10_10_1),
6593 "2.2.5.5/32 LB 1 buckets via: "
6594 "adj 10.10.11.1");
6595 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6596
6597 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006598 * cleanup
6599 */
6600 fib_table_entry_delete(fib_index,
6601 &pfx_1_1_1_2_s_32,
6602 FIB_SOURCE_API);
6603
6604 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6605 FIB_TEST(fib_test_validate_entry(fei,
6606 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6607 1,
6608 &l1600_eos_o_1_1_1_1),
6609 "2.2.2.2/32 LB 1 buckets via: "
6610 "label 1600 via 1.1,1.1");
6611
6612 fib_table_entry_delete(fib_index,
6613 &pfx_1_1_1_1_s_32,
6614 FIB_SOURCE_API);
6615
6616 FIB_TEST(fib_test_validate_entry(fei,
6617 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6618 1,
6619 &bucket_drop),
6620 "2.2.2.2/32 LB 1 buckets via: DROP");
6621
6622 fib_table_entry_delete(fib_index,
6623 &pfx_2_2_2_2_s_32,
6624 FIB_SOURCE_API);
6625 fib_table_entry_delete(fib_index,
6626 &pfx_2_2_2_3_s_32,
6627 FIB_SOURCE_API);
6628 fib_table_entry_delete(fib_index,
6629 &pfx_2_2_2_4_s_32,
6630 FIB_SOURCE_API);
6631
6632 adj_unlock(ai_mpls_10_10_10_1);
6633 adj_unlock(ai_mpls_10_10_11_2);
6634 adj_unlock(ai_v4_10_10_11_1);
6635 adj_unlock(ai_v4_10_10_11_2);
6636 adj_unlock(ai_mpls_10_10_11_1);
6637
6638 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6639 adj_nbr_db_size());
6640
6641 local0_pfx.fp_len = 32;
6642 fib_table_entry_delete(fib_index,
6643 &local0_pfx,
6644 FIB_SOURCE_INTERFACE);
6645 local0_pfx.fp_len = 24;
6646 fib_table_entry_delete(fib_index,
6647 &local0_pfx,
6648 FIB_SOURCE_INTERFACE);
6649 local1_pfx.fp_len = 32;
6650 fib_table_entry_delete(fib_index,
6651 &local1_pfx,
6652 FIB_SOURCE_INTERFACE);
6653 local1_pfx.fp_len = 24;
6654 fib_table_entry_delete(fib_index,
6655 &local1_pfx,
6656 FIB_SOURCE_INTERFACE);
6657
6658 /*
6659 * +1 for the drop LB in the MPLS tables.
6660 */
6661 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6662 "Load-balance resources freed %d of %d",
6663 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006664
6665 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006666}
6667
6668#define N_TEST_CHILDREN 4
6669#define PARENT_INDEX 0
6670
6671typedef struct fib_node_test_t_
6672{
6673 fib_node_t node;
6674 u32 sibling;
6675 u32 index;
6676 fib_node_back_walk_ctx_t *ctxs;
6677 u32 destroyed;
6678} fib_node_test_t;
6679
6680static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6681
6682#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6683
6684#define FOR_EACH_TEST_CHILD(_tc) \
6685 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6686 ii < N_TEST_CHILDREN+1; \
6687 ii++, (_tc) = &fib_test_nodes[ii])
6688
6689static fib_node_t *
6690fib_test_child_get_node (fib_node_index_t index)
6691{
6692 return (&fib_test_nodes[index].node);
6693}
6694
6695static int fib_test_walk_spawns_walks;
6696
6697static fib_node_back_walk_rc_t
6698fib_test_child_back_walk_notify (fib_node_t *node,
6699 fib_node_back_walk_ctx_t *ctx)
6700{
6701 fib_node_test_t *tc = (fib_node_test_t*) node;
6702
6703 vec_add1(tc->ctxs, *ctx);
6704
6705 if (1 == fib_test_walk_spawns_walks)
6706 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6707 if (2 == fib_test_walk_spawns_walks)
6708 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6709 FIB_WALK_PRIORITY_HIGH, ctx);
6710
6711 return (FIB_NODE_BACK_WALK_CONTINUE);
6712}
6713
6714static void
6715fib_test_child_last_lock_gone (fib_node_t *node)
6716{
6717 fib_node_test_t *tc = (fib_node_test_t *)node;
6718
6719 tc->destroyed = 1;
6720}
6721
6722/**
6723 * The FIB walk's graph node virtual function table
6724 */
6725static const fib_node_vft_t fib_test_child_vft = {
6726 .fnv_get = fib_test_child_get_node,
6727 .fnv_last_lock = fib_test_child_last_lock_gone,
6728 .fnv_back_walk = fib_test_child_back_walk_notify,
6729};
6730
6731/*
6732 * the function (that should have been static but isn't so I can do this)
6733 * that processes the walk from the async queue,
6734 */
6735f64 fib_walk_process_queues(vlib_main_t * vm,
6736 const f64 quota);
6737u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6738
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006739static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006740fib_test_walk (void)
6741{
6742 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6743 fib_node_test_t *tc;
6744 vlib_main_t *vm;
6745 u32 ii;
6746
6747 vm = vlib_get_main();
6748 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6749
6750 /*
6751 * init a fake node on which we will add children
6752 */
6753 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6754 FIB_NODE_TYPE_TEST);
6755
6756 FOR_EACH_TEST_CHILD(tc)
6757 {
6758 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6759 fib_node_lock(&tc->node);
6760 tc->ctxs = NULL;
6761 tc->index = ii;
6762 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6763 PARENT_INDEX,
6764 FIB_NODE_TYPE_TEST, ii);
6765 }
6766
6767 /*
6768 * enqueue a walk across the parents children.
6769 */
Neale Ranns450cd302016-11-09 17:49:42 +00006770 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006771
6772 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6773 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6774 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6775 "Parent has %d children pre-walk",
6776 fib_node_list_get_size(PARENT()->fn_children));
6777
6778 /*
6779 * give the walk a large amount of time so it gets to the end
6780 */
6781 fib_walk_process_queues(vm, 1);
6782
6783 FOR_EACH_TEST_CHILD(tc)
6784 {
6785 FIB_TEST(1 == vec_len(tc->ctxs),
6786 "%d child visitsed %d times",
6787 ii, vec_len(tc->ctxs));
6788 vec_free(tc->ctxs);
6789 }
6790 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6791 "Queue is empty post walk");
6792 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6793 "Parent has %d children post walk",
6794 fib_node_list_get_size(PARENT()->fn_children));
6795
6796 /*
6797 * walk again. should be no increase in the number of visits, since
6798 * the walk will have terminated.
6799 */
6800 fib_walk_process_queues(vm, 1);
6801
6802 FOR_EACH_TEST_CHILD(tc)
6803 {
6804 FIB_TEST(0 == vec_len(tc->ctxs),
6805 "%d child visitsed %d times",
6806 ii, vec_len(tc->ctxs));
6807 }
6808
6809 /*
6810 * schedule a low and hig priority walk. expect the high to be performed
6811 * before the low.
6812 * schedule the high prio walk first so that it is further from the head
6813 * of the dependency list. that way it won't merge with the low one.
6814 */
6815 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6816 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6817
6818 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6819 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6820 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6821 FIB_WALK_PRIORITY_LOW, &low_ctx);
6822
6823 fib_walk_process_queues(vm, 1);
6824
6825 FOR_EACH_TEST_CHILD(tc)
6826 {
6827 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6828 "%d child visitsed by high prio walk", ii);
6829 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6830 "%d child visitsed by low prio walk", ii);
6831 vec_free(tc->ctxs);
6832 }
6833 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6834 "Queue is empty post prio walk");
6835 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6836 "Parent has %d children post prio walk",
6837 fib_node_list_get_size(PARENT()->fn_children));
6838
6839 /*
6840 * schedule 2 walks of the same priority that can be megred.
6841 * expect that each child is thus visited only once.
6842 */
6843 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6844 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6845
6846 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6847 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6848 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6849 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6850
6851 fib_walk_process_queues(vm, 1);
6852
6853 FOR_EACH_TEST_CHILD(tc)
6854 {
6855 FIB_TEST(1 == vec_len(tc->ctxs),
6856 "%d child visitsed %d times during merge walk",
6857 ii, vec_len(tc->ctxs));
6858 vec_free(tc->ctxs);
6859 }
6860 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6861 "Queue is empty post merge walk");
6862 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6863 "Parent has %d children post merge walk",
6864 fib_node_list_get_size(PARENT()->fn_children));
6865
6866 /*
6867 * schedule 2 walks of the same priority that cannot be megred.
6868 * expect that each child is thus visited twice and in the order
6869 * in which the walks were scheduled.
6870 */
6871 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6872 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6873
6874 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6875 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6876 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6877 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6878
6879 fib_walk_process_queues(vm, 1);
6880
6881 FOR_EACH_TEST_CHILD(tc)
6882 {
6883 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6884 "%d child visitsed by high prio walk", ii);
6885 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6886 "%d child visitsed by low prio walk", ii);
6887 vec_free(tc->ctxs);
6888 }
6889 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6890 "Queue is empty post no-merge walk");
6891 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6892 "Parent has %d children post no-merge walk",
6893 fib_node_list_get_size(PARENT()->fn_children));
6894
6895 /*
6896 * schedule a walk that makes one one child progress.
6897 * we do this by giving the queue draining process zero
6898 * time quanta. it's a do..while loop, so it does something.
6899 */
Neale Ranns450cd302016-11-09 17:49:42 +00006900 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006901
6902 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6903 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6904 fib_walk_process_queues(vm, 0);
6905
6906 FOR_EACH_TEST_CHILD(tc)
6907 {
6908 if (ii == N_TEST_CHILDREN)
6909 {
6910 FIB_TEST(1 == vec_len(tc->ctxs),
6911 "%d child visitsed %d times in zero quanta walk",
6912 ii, vec_len(tc->ctxs));
6913 }
6914 else
6915 {
6916 FIB_TEST(0 == vec_len(tc->ctxs),
6917 "%d child visitsed %d times in 0 quanta walk",
6918 ii, vec_len(tc->ctxs));
6919 }
6920 }
6921 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6922 "Queue is not empty post zero quanta walk");
6923 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6924 "Parent has %d children post zero qunta walk",
6925 fib_node_list_get_size(PARENT()->fn_children));
6926
6927 /*
6928 * another one step
6929 */
6930 fib_walk_process_queues(vm, 0);
6931
6932 FOR_EACH_TEST_CHILD(tc)
6933 {
6934 if (ii >= N_TEST_CHILDREN-1)
6935 {
6936 FIB_TEST(1 == vec_len(tc->ctxs),
6937 "%d child visitsed %d times in 2nd zero quanta walk",
6938 ii, vec_len(tc->ctxs));
6939 }
6940 else
6941 {
6942 FIB_TEST(0 == vec_len(tc->ctxs),
6943 "%d child visitsed %d times in 2nd 0 quanta walk",
6944 ii, vec_len(tc->ctxs));
6945 }
6946 }
6947 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6948 "Queue is not empty post zero quanta walk");
6949 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6950 "Parent has %d children post zero qunta walk",
6951 fib_node_list_get_size(PARENT()->fn_children));
6952
6953 /*
6954 * schedule another walk that will catch-up and merge.
6955 */
6956 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6957 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6958 fib_walk_process_queues(vm, 1);
6959
6960 FOR_EACH_TEST_CHILD(tc)
6961 {
6962 if (ii >= N_TEST_CHILDREN-1)
6963 {
6964 FIB_TEST(2 == vec_len(tc->ctxs),
6965 "%d child visitsed %d times in 2nd zero quanta merge walk",
6966 ii, vec_len(tc->ctxs));
6967 vec_free(tc->ctxs);
6968 }
6969 else
6970 {
6971 FIB_TEST(1 == vec_len(tc->ctxs),
6972 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6973 ii, vec_len(tc->ctxs));
6974 vec_free(tc->ctxs);
6975 }
6976 }
6977 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6978 "Queue is not empty post 2nd zero quanta merge walk");
6979 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6980 "Parent has %d children post 2nd zero qunta merge walk",
6981 fib_node_list_get_size(PARENT()->fn_children));
6982
6983 /*
6984 * park a async walk in the middle of the list, then have an sync walk catch
6985 * it. same expectations as async catches async.
6986 */
Neale Ranns450cd302016-11-09 17:49:42 +00006987 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006988
6989 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6990 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6991
6992 fib_walk_process_queues(vm, 0);
6993 fib_walk_process_queues(vm, 0);
6994
6995 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6996
6997 FOR_EACH_TEST_CHILD(tc)
6998 {
6999 if (ii >= N_TEST_CHILDREN-1)
7000 {
7001 FIB_TEST(2 == vec_len(tc->ctxs),
7002 "%d child visitsed %d times in sync catches async walk",
7003 ii, vec_len(tc->ctxs));
7004 vec_free(tc->ctxs);
7005 }
7006 else
7007 {
7008 FIB_TEST(1 == vec_len(tc->ctxs),
7009 "%d child visitsed %d times in sync catches async walk",
7010 ii, vec_len(tc->ctxs));
7011 vec_free(tc->ctxs);
7012 }
7013 }
7014 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7015 "Queue is not empty post 2nd zero quanta merge walk");
7016 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7017 "Parent has %d children post 2nd zero qunta merge walk",
7018 fib_node_list_get_size(PARENT()->fn_children));
7019
7020 /*
7021 * make the parent a child of one of its children, thus inducing a routing loop.
7022 */
7023 fib_test_nodes[PARENT_INDEX].sibling =
7024 fib_node_child_add(FIB_NODE_TYPE_TEST,
7025 1, // the first child
7026 FIB_NODE_TYPE_TEST,
7027 PARENT_INDEX);
7028
7029 /*
7030 * execute a sync walk from the parent. each child visited spawns more sync
7031 * walks. we expect the walk to terminate.
7032 */
7033 fib_test_walk_spawns_walks = 1;
7034
7035 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7036
7037 FOR_EACH_TEST_CHILD(tc)
7038 {
7039 /*
7040 * child 1 - which is last in the list - has the loop.
7041 * the other children a re thus visitsed first. the we meet
7042 * child 1. we go round the loop again, visting the other children.
7043 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7044 * again.
7045 */
7046 if (1 == ii)
7047 {
7048 FIB_TEST(1 == vec_len(tc->ctxs),
7049 "child %d visitsed %d times during looped sync walk",
7050 ii, vec_len(tc->ctxs));
7051 }
7052 else
7053 {
7054 FIB_TEST(2 == vec_len(tc->ctxs),
7055 "child %d visitsed %d times during looped sync walk",
7056 ii, vec_len(tc->ctxs));
7057 }
7058 vec_free(tc->ctxs);
7059 }
7060 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7061 "Parent has %d children post sync loop walk",
7062 fib_node_list_get_size(PARENT()->fn_children));
7063
7064 /*
7065 * the walk doesn't reach the max depth because the infra knows that sync
7066 * meets sync implies a loop and bails early.
7067 */
7068 FIB_TEST(high_ctx.fnbw_depth == 9,
7069 "Walk context depth %d post sync loop walk",
7070 high_ctx.fnbw_depth);
7071
7072 /*
7073 * execute an async walk of the graph loop, with each child spawns sync walks
7074 */
7075 high_ctx.fnbw_depth = 0;
7076 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7077 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7078
7079 fib_walk_process_queues(vm, 1);
7080
7081 FOR_EACH_TEST_CHILD(tc)
7082 {
7083 /*
7084 * we don't really care how many times the children are visisted, as long as
7085 * it is more than once.
7086 */
7087 FIB_TEST(1 <= vec_len(tc->ctxs),
7088 "child %d visitsed %d times during looped aync spawns sync walk",
7089 ii, vec_len(tc->ctxs));
7090 vec_free(tc->ctxs);
7091 }
7092
7093 /*
7094 * execute an async walk of the graph loop, with each child spawns async walks
7095 */
7096 fib_test_walk_spawns_walks = 2;
7097 high_ctx.fnbw_depth = 0;
7098 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7099 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7100
7101 fib_walk_process_queues(vm, 1);
7102
7103 FOR_EACH_TEST_CHILD(tc)
7104 {
7105 /*
7106 * we don't really care how many times the children are visisted, as long as
7107 * it is more than once.
7108 */
7109 FIB_TEST(1 <= vec_len(tc->ctxs),
7110 "child %d visitsed %d times during looped async spawns async walk",
7111 ii, vec_len(tc->ctxs));
7112 vec_free(tc->ctxs);
7113 }
7114
7115
7116 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7117 1, // the first child
7118 fib_test_nodes[PARENT_INDEX].sibling);
7119
7120 /*
7121 * cleanup
7122 */
7123 FOR_EACH_TEST_CHILD(tc)
7124 {
7125 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7126 tc->sibling);
7127 fib_node_deinit(&tc->node);
7128 fib_node_unlock(&tc->node);
7129 }
7130 fib_node_deinit(PARENT());
7131
7132 /*
7133 * The parent will be destroyed when the last lock on it goes.
7134 * this test ensures all the walk objects are unlocking it.
7135 */
7136 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7137 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007138
7139 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007140}
7141
Neale Ranns88fc83e2017-04-05 08:11:14 -07007142/*
7143 * declaration of the otherwise static callback functions
7144 */
7145void fib_bfd_notify (bfd_listen_event_e event,
7146 const bfd_session_t *session);
7147void adj_bfd_notify (bfd_listen_event_e event,
7148 const bfd_session_t *session);
7149
7150/**
7151 * Test BFD session interaction with FIB
7152 */
7153static int
7154fib_test_bfd (void)
7155{
7156 fib_node_index_t fei;
7157 test_main_t *tm;
7158 int n_feis;
7159
7160 /* via 10.10.10.1 */
7161 ip46_address_t nh_10_10_10_1 = {
7162 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7163 };
7164 /* via 10.10.10.2 */
7165 ip46_address_t nh_10_10_10_2 = {
7166 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7167 };
7168 /* via 10.10.10.10 */
7169 ip46_address_t nh_10_10_10_10 = {
7170 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7171 };
7172 n_feis = fib_entry_pool_size();
7173
7174 tm = &test_main;
7175
7176 /*
7177 * add interface routes. we'll assume this works. it's tested elsewhere
7178 */
7179 fib_prefix_t pfx_10_10_10_10_s_24 = {
7180 .fp_len = 24,
7181 .fp_proto = FIB_PROTOCOL_IP4,
7182 .fp_addr = nh_10_10_10_10,
7183 };
7184
7185 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7186 FIB_SOURCE_INTERFACE,
7187 (FIB_ENTRY_FLAG_CONNECTED |
7188 FIB_ENTRY_FLAG_ATTACHED),
7189 FIB_PROTOCOL_IP4,
7190 NULL,
7191 tm->hw[0]->sw_if_index,
7192 ~0, // invalid fib index
7193 1, // weight
7194 NULL,
7195 FIB_ROUTE_PATH_FLAG_NONE);
7196
7197 fib_prefix_t pfx_10_10_10_10_s_32 = {
7198 .fp_len = 32,
7199 .fp_proto = FIB_PROTOCOL_IP4,
7200 .fp_addr = nh_10_10_10_10,
7201 };
7202 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7203 FIB_SOURCE_INTERFACE,
7204 (FIB_ENTRY_FLAG_CONNECTED |
7205 FIB_ENTRY_FLAG_LOCAL),
7206 FIB_PROTOCOL_IP4,
7207 NULL,
7208 tm->hw[0]->sw_if_index,
7209 ~0, // invalid fib index
7210 1, // weight
7211 NULL,
7212 FIB_ROUTE_PATH_FLAG_NONE);
7213
7214 /*
7215 * A BFD session via a neighbour we do not yet know
7216 */
7217 bfd_session_t bfd_10_10_10_1 = {
7218 .udp = {
7219 .key = {
7220 .fib_index = 0,
7221 .peer_addr = nh_10_10_10_1,
7222 },
7223 },
7224 .hop_type = BFD_HOP_TYPE_MULTI,
7225 .local_state = BFD_STATE_init,
7226 };
7227
7228 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7229
7230 /*
7231 * A new entry will be created that forwards via the adj
7232 */
7233 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7234 VNET_LINK_IP4,
7235 &nh_10_10_10_1,
7236 tm->hw[0]->sw_if_index);
7237 fib_prefix_t pfx_10_10_10_1_s_32 = {
7238 .fp_addr = nh_10_10_10_1,
7239 .fp_len = 32,
7240 .fp_proto = FIB_PROTOCOL_IP4,
7241 };
7242 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7243 .type = FT_LB_ADJ,
7244 .adj = {
7245 .adj = ai_10_10_10_1,
7246 },
7247 };
7248
7249 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7250 FIB_TEST(fib_test_validate_entry(fei,
7251 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7252 1,
7253 &adj_o_10_10_10_1),
7254 "BFD sourced %U via %U",
7255 format_fib_prefix, &pfx_10_10_10_1_s_32,
7256 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7257
7258 /*
7259 * Delete the BFD session. Expect the fib_entry to be removed
7260 */
7261 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7262
7263 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7264 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7265 "BFD sourced %U removed",
7266 format_fib_prefix, &pfx_10_10_10_1_s_32);
7267
7268 /*
7269 * Add the BFD source back
7270 */
7271 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7272
7273 /*
7274 * source the entry via the ADJ fib
7275 */
Neale Ranns81424992017-05-18 03:03:22 -07007276 fei = fib_table_entry_path_add(0,
7277 &pfx_10_10_10_1_s_32,
7278 FIB_SOURCE_ADJ,
7279 FIB_ENTRY_FLAG_ATTACHED,
7280 FIB_PROTOCOL_IP4,
7281 &nh_10_10_10_1,
7282 tm->hw[0]->sw_if_index,
7283 ~0, // invalid fib index
7284 1,
7285 NULL,
7286 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007287
7288 /*
7289 * Delete the BFD session. Expect the fib_entry to remain
7290 */
7291 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7292
7293 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7294 FIB_TEST(fib_test_validate_entry(fei,
7295 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7296 1,
7297 &adj_o_10_10_10_1),
7298 "BFD sourced %U remains via %U",
7299 format_fib_prefix, &pfx_10_10_10_1_s_32,
7300 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7301
7302 /*
7303 * Add the BFD source back
7304 */
7305 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7306
7307 /*
7308 * Create another ADJ FIB
7309 */
7310 fib_prefix_t pfx_10_10_10_2_s_32 = {
7311 .fp_addr = nh_10_10_10_2,
7312 .fp_len = 32,
7313 .fp_proto = FIB_PROTOCOL_IP4,
7314 };
Neale Ranns81424992017-05-18 03:03:22 -07007315 fib_table_entry_path_add(0,
7316 &pfx_10_10_10_2_s_32,
7317 FIB_SOURCE_ADJ,
7318 FIB_ENTRY_FLAG_ATTACHED,
7319 FIB_PROTOCOL_IP4,
7320 &nh_10_10_10_2,
7321 tm->hw[0]->sw_if_index,
7322 ~0, // invalid fib index
7323 1,
7324 NULL,
7325 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007326 /*
7327 * A BFD session for the new ADJ FIB
7328 */
7329 bfd_session_t bfd_10_10_10_2 = {
7330 .udp = {
7331 .key = {
7332 .fib_index = 0,
7333 .peer_addr = nh_10_10_10_2,
7334 },
7335 },
7336 .hop_type = BFD_HOP_TYPE_MULTI,
7337 .local_state = BFD_STATE_init,
7338 };
7339
7340 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7341
7342 /*
7343 * remove the adj-fib source whilst the session is present
7344 * then add it back
7345 */
7346 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07007347 fib_table_entry_path_add(0,
7348 &pfx_10_10_10_2_s_32,
7349 FIB_SOURCE_ADJ,
7350 FIB_ENTRY_FLAG_ATTACHED,
7351 FIB_PROTOCOL_IP4,
7352 &nh_10_10_10_2,
7353 tm->hw[0]->sw_if_index,
7354 ~0, // invalid fib index
7355 1,
7356 NULL,
7357 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007358
7359 /*
7360 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7361 * bring one of the sessions UP, leave the other down
7362 */
7363 bfd_10_10_10_1.local_state = BFD_STATE_up;
7364 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7365 bfd_10_10_10_2.local_state = BFD_STATE_down;
7366 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7367
7368 /*
7369 * A recursive prefix via both of the ADJ FIBs
7370 */
7371 fib_prefix_t pfx_200_0_0_0_s_24 = {
7372 .fp_proto = FIB_PROTOCOL_IP4,
7373 .fp_len = 32,
7374 .fp_addr = {
7375 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7376 },
7377 };
7378 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7379
7380 dpo_10_10_10_1 =
7381 fib_entry_contribute_ip_forwarding(
7382 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7383 dpo_10_10_10_2 =
7384 fib_entry_contribute_ip_forwarding(
7385 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7386
7387 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7388 .type = FT_LB_O_LB,
7389 .lb = {
7390 .lb = dpo_10_10_10_1->dpoi_index,
7391 },
7392 };
7393 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7394 .type = FT_LB_O_LB,
7395 .lb = {
7396 .lb = dpo_10_10_10_2->dpoi_index,
7397 },
7398 };
7399
7400 /*
7401 * A prefix via the adj-fib that is BFD down => DROP
7402 */
7403 fei = fib_table_entry_path_add(0,
7404 &pfx_200_0_0_0_s_24,
7405 FIB_SOURCE_API,
7406 FIB_ENTRY_FLAG_NONE,
7407 FIB_PROTOCOL_IP4,
7408 &nh_10_10_10_2,
7409 ~0, // recursive
7410 0, // default fib index
7411 1,
7412 NULL,
7413 FIB_ROUTE_PATH_FLAG_NONE);
7414 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7415 "%U resolves via drop",
7416 format_fib_prefix, &pfx_200_0_0_0_s_24);
7417
7418 /*
7419 * add a path via the UP BFD adj-fib.
7420 * we expect that the DOWN BFD ADJ FIB is not used.
7421 */
7422 fei = fib_table_entry_path_add(0,
7423 &pfx_200_0_0_0_s_24,
7424 FIB_SOURCE_API,
7425 FIB_ENTRY_FLAG_NONE,
7426 FIB_PROTOCOL_IP4,
7427 &nh_10_10_10_1,
7428 ~0, // recursive
7429 0, // default fib index
7430 1,
7431 NULL,
7432 FIB_ROUTE_PATH_FLAG_NONE);
7433
7434 FIB_TEST(fib_test_validate_entry(fei,
7435 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7436 1,
7437 &lb_o_10_10_10_1),
7438 "Recursive %U only UP BFD adj-fibs",
7439 format_fib_prefix, &pfx_200_0_0_0_s_24);
7440
7441 /*
7442 * Send a BFD state change to UP - both sessions are now up
7443 * the recursive prefix should LB over both
7444 */
7445 bfd_10_10_10_2.local_state = BFD_STATE_up;
7446 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7447
7448
7449 FIB_TEST(fib_test_validate_entry(fei,
7450 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7451 2,
7452 &lb_o_10_10_10_1,
7453 &lb_o_10_10_10_2),
7454 "Recursive %U via both UP BFD adj-fibs",
7455 format_fib_prefix, &pfx_200_0_0_0_s_24);
7456
7457 /*
7458 * Send a BFD state change to DOWN
7459 * the recursive prefix should exclude the down
7460 */
7461 bfd_10_10_10_2.local_state = BFD_STATE_down;
7462 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7463
7464
7465 FIB_TEST(fib_test_validate_entry(fei,
7466 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7467 1,
7468 &lb_o_10_10_10_1),
7469 "Recursive %U via only UP",
7470 format_fib_prefix, &pfx_200_0_0_0_s_24);
7471
7472 /*
7473 * Delete the BFD session while it is in the DOWN state.
7474 * FIB should consider the entry's state as back up
7475 */
7476 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
7477
7478 FIB_TEST(fib_test_validate_entry(fei,
7479 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7480 2,
7481 &lb_o_10_10_10_1,
7482 &lb_o_10_10_10_2),
7483 "Recursive %U via both UP BFD adj-fibs post down session delete",
7484 format_fib_prefix, &pfx_200_0_0_0_s_24);
7485
7486 /*
7487 * Delete the BFD other session while it is in the UP state.
7488 */
7489 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7490
7491 FIB_TEST(fib_test_validate_entry(fei,
7492 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7493 2,
7494 &lb_o_10_10_10_1,
7495 &lb_o_10_10_10_2),
7496 "Recursive %U via both UP BFD adj-fibs post up session delete",
7497 format_fib_prefix, &pfx_200_0_0_0_s_24);
7498
7499 /*
7500 * cleaup
7501 */
7502 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
7503 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
7504 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
7505
7506 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
7507 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
7508
7509 adj_unlock(ai_10_10_10_1);
7510 /*
7511 * test no-one left behind
7512 */
7513 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7514 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7515
7516 /*
7517 * Single-hop BFD tests
7518 */
7519 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
7520 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
7521
7522 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7523
7524 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7525 VNET_LINK_IP4,
7526 &nh_10_10_10_1,
7527 tm->hw[0]->sw_if_index);
7528 /*
7529 * whilst the BFD session is not signalled, the adj is up
7530 */
7531 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
7532
7533 /*
7534 * bring the BFD session up
7535 */
7536 bfd_10_10_10_1.local_state = BFD_STATE_up;
7537 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7538 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
7539
7540 /*
7541 * bring the BFD session down
7542 */
7543 bfd_10_10_10_1.local_state = BFD_STATE_down;
7544 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7545 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
7546
7547
7548 /*
7549 * add an attached next hop FIB entry via the down adj
7550 */
7551 fib_prefix_t pfx_5_5_5_5_s_32 = {
7552 .fp_addr = {
7553 .ip4 = {
7554 .as_u32 = clib_host_to_net_u32(0x05050505),
7555 },
7556 },
7557 .fp_len = 32,
7558 .fp_proto = FIB_PROTOCOL_IP4,
7559 };
7560
7561 fei = fib_table_entry_path_add(0,
7562 &pfx_5_5_5_5_s_32,
7563 FIB_SOURCE_CLI,
7564 FIB_ENTRY_FLAG_NONE,
7565 FIB_PROTOCOL_IP4,
7566 &nh_10_10_10_1,
7567 tm->hw[0]->sw_if_index,
7568 ~0, // invalid fib index
7569 1,
7570 NULL,
7571 FIB_ROUTE_PATH_FLAG_NONE);
7572 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7573 "%U resolves via drop",
7574 format_fib_prefix, &pfx_5_5_5_5_s_32);
7575
7576 /*
7577 * Add a path via an ADJ that is up
7578 */
7579 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7580 VNET_LINK_IP4,
7581 &nh_10_10_10_2,
7582 tm->hw[0]->sw_if_index);
7583
7584 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
7585 .type = FT_LB_ADJ,
7586 .adj = {
7587 .adj = ai_10_10_10_2,
7588 },
7589 };
7590 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
7591
7592 fei = fib_table_entry_path_add(0,
7593 &pfx_5_5_5_5_s_32,
7594 FIB_SOURCE_CLI,
7595 FIB_ENTRY_FLAG_NONE,
7596 FIB_PROTOCOL_IP4,
7597 &nh_10_10_10_2,
7598 tm->hw[0]->sw_if_index,
7599 ~0, // invalid fib index
7600 1,
7601 NULL,
7602 FIB_ROUTE_PATH_FLAG_NONE);
7603
7604 FIB_TEST(fib_test_validate_entry(fei,
7605 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7606 1,
7607 &adj_o_10_10_10_2),
7608 "BFD sourced %U via %U",
7609 format_fib_prefix, &pfx_5_5_5_5_s_32,
7610 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
7611
7612 /*
7613 * Bring up the down session - should now LB
7614 */
7615 bfd_10_10_10_1.local_state = BFD_STATE_up;
7616 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7617 FIB_TEST(fib_test_validate_entry(fei,
7618 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7619 2,
7620 &adj_o_10_10_10_1,
7621 &adj_o_10_10_10_2),
7622 "BFD sourced %U via noth adjs",
7623 format_fib_prefix, &pfx_5_5_5_5_s_32);
7624
7625 /*
7626 * remove the BFD session state from the adj
7627 */
7628 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7629
7630 /*
7631 * clean-up
7632 */
7633 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
7634 adj_unlock(ai_10_10_10_1);
7635 adj_unlock(ai_10_10_10_2);
7636
7637 /*
7638 * test no-one left behind
7639 */
7640 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
7641 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
7642 return (0);
7643}
7644
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007645static int
7646lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007647{
7648 const mpls_label_t deag_label = 50;
7649 const u32 lfib_index = 0;
7650 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01007651 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007652 const dpo_id_t *dpo1;
7653 fib_node_index_t lfe;
7654 lookup_dpo_t *lkd;
7655 test_main_t *tm;
7656 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00007657 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007658
7659 tm = &test_main;
7660 lb_count = pool_elts(load_balance_pool);
7661
7662 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7663 adj_nbr_db_size());
7664
7665 /*
7666 * MPLS enable an interface so we get the MPLS table created
7667 */
7668 mpls_sw_interface_enable_disable(&mpls_main,
7669 tm->hw[0]->sw_if_index,
7670 1);
7671
Neale Rannsad422ed2016-11-02 14:20:04 +00007672 ip46_address_t nh_10_10_10_1 = {
7673 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7674 };
7675 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7676 VNET_LINK_MPLS,
7677 &nh_10_10_10_1,
7678 tm->hw[0]->sw_if_index);
7679
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007680 /*
7681 * Test the specials stack properly.
7682 */
7683 fib_prefix_t exp_null_v6_pfx = {
7684 .fp_proto = FIB_PROTOCOL_MPLS,
7685 .fp_eos = MPLS_EOS,
7686 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7687 .fp_payload_proto = DPO_PROTO_IP6,
7688 };
7689 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
7690 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
7691 "%U/%U present",
7692 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
7693 format_mpls_eos_bit, MPLS_EOS);
7694 fib_entry_contribute_forwarding(lfe,
7695 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7696 &dpo);
7697 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7698 lkd = lookup_dpo_get(dpo1->dpoi_index);
7699
7700 FIB_TEST((fib_index == lkd->lkd_fib_index),
7701 "%U/%U is deag in %d %U",
7702 format_mpls_unicast_label, deag_label,
7703 format_mpls_eos_bit, MPLS_EOS,
7704 lkd->lkd_fib_index,
7705 format_dpo_id, &dpo, 0);
7706 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7707 "%U/%U is dst deag",
7708 format_mpls_unicast_label, deag_label,
7709 format_mpls_eos_bit, MPLS_EOS);
7710 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
7711 "%U/%U is lookup in interface's table",
7712 format_mpls_unicast_label, deag_label,
7713 format_mpls_eos_bit, MPLS_EOS);
7714 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
7715 "%U/%U is %U dst deag",
7716 format_mpls_unicast_label, deag_label,
7717 format_mpls_eos_bit, MPLS_EOS,
7718 format_dpo_proto, lkd->lkd_proto);
7719
7720
7721 /*
7722 * A route deag route for EOS
7723 */
7724 fib_prefix_t pfx = {
7725 .fp_proto = FIB_PROTOCOL_MPLS,
7726 .fp_eos = MPLS_EOS,
7727 .fp_label = deag_label,
7728 .fp_payload_proto = DPO_PROTO_IP4,
7729 };
7730 lfe = fib_table_entry_path_add(lfib_index,
7731 &pfx,
7732 FIB_SOURCE_CLI,
7733 FIB_ENTRY_FLAG_NONE,
7734 FIB_PROTOCOL_IP4,
7735 &zero_addr,
7736 ~0,
7737 fib_index,
7738 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007739 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007740 FIB_ROUTE_PATH_FLAG_NONE);
7741
7742 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7743 "%U/%U present",
7744 format_mpls_unicast_label, deag_label,
7745 format_mpls_eos_bit, MPLS_EOS);
7746
7747 fib_entry_contribute_forwarding(lfe,
7748 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
7749 &dpo);
7750 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7751 lkd = lookup_dpo_get(dpo1->dpoi_index);
7752
7753 FIB_TEST((fib_index == lkd->lkd_fib_index),
7754 "%U/%U is deag in %d %U",
7755 format_mpls_unicast_label, deag_label,
7756 format_mpls_eos_bit, MPLS_EOS,
7757 lkd->lkd_fib_index,
7758 format_dpo_id, &dpo, 0);
7759 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7760 "%U/%U is dst deag",
7761 format_mpls_unicast_label, deag_label,
7762 format_mpls_eos_bit, MPLS_EOS);
7763 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
7764 "%U/%U is %U dst deag",
7765 format_mpls_unicast_label, deag_label,
7766 format_mpls_eos_bit, MPLS_EOS,
7767 format_dpo_proto, lkd->lkd_proto);
7768
7769 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7770
7771 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7772 &pfx)),
7773 "%U/%U not present",
7774 format_mpls_unicast_label, deag_label,
7775 format_mpls_eos_bit, MPLS_EOS);
7776
7777 /*
7778 * A route deag route for non-EOS
7779 */
7780 pfx.fp_eos = MPLS_NON_EOS;
7781 lfe = fib_table_entry_path_add(lfib_index,
7782 &pfx,
7783 FIB_SOURCE_CLI,
7784 FIB_ENTRY_FLAG_NONE,
7785 FIB_PROTOCOL_IP4,
7786 &zero_addr,
7787 ~0,
7788 lfib_index,
7789 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007790 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007791 FIB_ROUTE_PATH_FLAG_NONE);
7792
7793 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
7794 "%U/%U present",
7795 format_mpls_unicast_label, deag_label,
7796 format_mpls_eos_bit, MPLS_NON_EOS);
7797
7798 fib_entry_contribute_forwarding(lfe,
7799 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7800 &dpo);
7801 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
7802 lkd = lookup_dpo_get(dpo1->dpoi_index);
7803
7804 FIB_TEST((fib_index == lkd->lkd_fib_index),
7805 "%U/%U is deag in %d %U",
7806 format_mpls_unicast_label, deag_label,
7807 format_mpls_eos_bit, MPLS_NON_EOS,
7808 lkd->lkd_fib_index,
7809 format_dpo_id, &dpo, 0);
7810 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
7811 "%U/%U is dst deag",
7812 format_mpls_unicast_label, deag_label,
7813 format_mpls_eos_bit, MPLS_NON_EOS);
7814
7815 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
7816 "%U/%U is %U dst deag",
7817 format_mpls_unicast_label, deag_label,
7818 format_mpls_eos_bit, MPLS_NON_EOS,
7819 format_dpo_proto, lkd->lkd_proto);
7820
7821 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
7822
7823 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
7824 &pfx)),
7825 "%U/%U not present",
7826 format_mpls_unicast_label, deag_label,
7827 format_mpls_eos_bit, MPLS_EOS);
7828
Neale Rannsad422ed2016-11-02 14:20:04 +00007829 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007830
Neale Rannsad422ed2016-11-02 14:20:04 +00007831 /*
7832 * An MPLS x-connect
7833 */
7834 fib_prefix_t pfx_1200 = {
7835 .fp_len = 21,
7836 .fp_proto = FIB_PROTOCOL_MPLS,
7837 .fp_label = 1200,
7838 .fp_eos = MPLS_NON_EOS,
7839 };
7840 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
7841 .type = FT_LB_LABEL_STACK_O_ADJ,
7842 .label_stack_o_adj = {
7843 .adj = ai_mpls_10_10_10_1,
7844 .label_stack_size = 4,
7845 .label_stack = {
7846 200, 300, 400, 500,
7847 },
7848 .eos = MPLS_NON_EOS,
7849 },
7850 };
7851 dpo_id_t neos_1200 = DPO_INVALID;
7852 dpo_id_t ip_1200 = DPO_INVALID;
7853 mpls_label_t *l200 = NULL;
7854 vec_add1(l200, 200);
7855 vec_add1(l200, 300);
7856 vec_add1(l200, 400);
7857 vec_add1(l200, 500);
7858
7859 lfe = fib_table_entry_update_one_path(fib_index,
7860 &pfx_1200,
7861 FIB_SOURCE_API,
7862 FIB_ENTRY_FLAG_NONE,
7863 FIB_PROTOCOL_IP4,
7864 &nh_10_10_10_1,
7865 tm->hw[0]->sw_if_index,
7866 ~0, // invalid fib index
7867 1,
7868 l200,
7869 FIB_ROUTE_PATH_FLAG_NONE);
7870
7871 FIB_TEST(fib_test_validate_entry(lfe,
7872 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7873 1,
7874 &neos_o_10_10_10_1),
7875 "1200/0 LB 1 buckets via: "
7876 "adj 10.10.11.1");
7877
7878 /*
7879 * A recursive route via the MPLS x-connect
7880 */
7881 fib_prefix_t pfx_2_2_2_3_s_32 = {
7882 .fp_len = 32,
7883 .fp_proto = FIB_PROTOCOL_IP4,
7884 .fp_addr = {
7885 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7886 },
7887 };
7888 fib_route_path_t *rpaths = NULL, rpath = {
7889 .frp_proto = FIB_PROTOCOL_MPLS,
7890 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08007891 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00007892 .frp_sw_if_index = ~0, // recurive
7893 .frp_fib_index = 0, // Default MPLS fib
7894 .frp_weight = 1,
7895 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
7896 .frp_label_stack = NULL,
7897 };
7898 vec_add1(rpaths, rpath);
7899
7900 fib_table_entry_path_add2(fib_index,
7901 &pfx_2_2_2_3_s_32,
7902 FIB_SOURCE_API,
7903 FIB_ENTRY_FLAG_NONE,
7904 rpaths);
7905
7906 /*
7907 * A labelled recursive route via the MPLS x-connect
7908 */
7909 fib_prefix_t pfx_2_2_2_4_s_32 = {
7910 .fp_len = 32,
7911 .fp_proto = FIB_PROTOCOL_IP4,
7912 .fp_addr = {
7913 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7914 },
7915 };
7916 mpls_label_t *l999 = NULL;
7917 vec_add1(l999, 999);
7918 rpaths[0].frp_label_stack = l999,
7919
7920 fib_table_entry_path_add2(fib_index,
7921 &pfx_2_2_2_4_s_32,
7922 FIB_SOURCE_API,
7923 FIB_ENTRY_FLAG_NONE,
7924 rpaths);
7925
7926 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7927 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7928 &ip_1200);
7929 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7930 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7931 &neos_1200);
7932
7933 fib_test_lb_bucket_t ip_o_1200 = {
7934 .type = FT_LB_O_LB,
7935 .lb = {
7936 .lb = ip_1200.dpoi_index,
7937 },
7938 };
7939 fib_test_lb_bucket_t mpls_o_1200 = {
7940 .type = FT_LB_LABEL_O_LB,
7941 .label_o_lb = {
7942 .lb = neos_1200.dpoi_index,
7943 .label = 999,
7944 .eos = MPLS_EOS,
7945 },
7946 };
7947
7948 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7949 FIB_TEST(fib_test_validate_entry(lfe,
7950 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7951 1,
7952 &ip_o_1200),
7953 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
7954 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7955 FIB_TEST(fib_test_validate_entry(lfe,
7956 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7957 1,
7958 &mpls_o_1200),
7959 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
7960
7961 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
7962 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
7963 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7964
7965 dpo_reset(&neos_1200);
7966 dpo_reset(&ip_1200);
7967
7968 /*
7969 * A recursive via a label that does not exist
7970 */
7971 fib_test_lb_bucket_t bucket_drop = {
7972 .type = FT_LB_SPECIAL,
7973 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07007974 .adj = DPO_PROTO_IP4,
7975 },
7976 };
7977 fib_test_lb_bucket_t mpls_bucket_drop = {
7978 .type = FT_LB_SPECIAL,
7979 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00007980 .adj = DPO_PROTO_MPLS,
7981 },
7982 };
7983
7984 rpaths[0].frp_label_stack = NULL;
7985 lfe = fib_table_entry_path_add2(fib_index,
7986 &pfx_2_2_2_4_s_32,
7987 FIB_SOURCE_API,
7988 FIB_ENTRY_FLAG_NONE,
7989 rpaths);
7990
7991 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7992 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7993 &ip_1200);
7994 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7995
7996 FIB_TEST(fib_test_validate_entry(lfe,
7997 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7998 1,
7999 &ip_o_1200),
8000 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
8001 lfe = fib_table_lookup(fib_index, &pfx_1200);
8002 FIB_TEST(fib_test_validate_entry(lfe,
8003 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8004 1,
8005 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07008006 "1200/neos LB 1 buckets via: ip4-DROP");
8007 FIB_TEST(fib_test_validate_entry(lfe,
8008 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8009 1,
8010 &mpls_bucket_drop),
8011 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00008012
8013 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8014
8015 dpo_reset(&ip_1200);
8016
8017 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008018 * An rx-interface route.
8019 * like the tail of an mcast LSP
8020 */
8021 dpo_id_t idpo = DPO_INVALID;
8022
8023 interface_dpo_add_or_lock(DPO_PROTO_IP4,
8024 tm->hw[0]->sw_if_index,
8025 &idpo);
8026
8027 fib_prefix_t pfx_2500 = {
8028 .fp_len = 21,
8029 .fp_proto = FIB_PROTOCOL_MPLS,
8030 .fp_label = 2500,
8031 .fp_eos = MPLS_EOS,
8032 .fp_payload_proto = DPO_PROTO_IP4,
8033 };
8034 fib_test_lb_bucket_t rx_intf_0 = {
8035 .type = FT_LB_INTF,
8036 .adj = {
8037 .adj = idpo.dpoi_index,
8038 },
8039 };
8040
8041 lfe = fib_table_entry_update_one_path(fib_index,
8042 &pfx_2500,
8043 FIB_SOURCE_API,
8044 FIB_ENTRY_FLAG_NONE,
8045 FIB_PROTOCOL_IP4,
8046 NULL,
8047 tm->hw[0]->sw_if_index,
8048 ~0, // invalid fib index
8049 0,
8050 NULL,
8051 FIB_ROUTE_PATH_INTF_RX);
8052 FIB_TEST(fib_test_validate_entry(lfe,
8053 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8054 1,
8055 &rx_intf_0),
8056 "2500 rx-interface 0");
8057 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8058
8059 /*
8060 * An MPLS mulicast entry
8061 */
8062 fib_prefix_t pfx_3500 = {
8063 .fp_len = 21,
8064 .fp_proto = FIB_PROTOCOL_MPLS,
8065 .fp_label = 3500,
8066 .fp_eos = MPLS_EOS,
8067 .fp_payload_proto = DPO_PROTO_IP4,
8068 };
8069 fib_test_rep_bucket_t mc_0 = {
8070 .type = FT_REP_LABEL_O_ADJ,
8071 .label_o_adj = {
8072 .adj = ai_mpls_10_10_10_1,
8073 .label = 3300,
8074 .eos = MPLS_EOS,
8075 },
8076 };
8077 fib_test_rep_bucket_t mc_intf_0 = {
8078 .type = FT_REP_INTF,
8079 .adj = {
8080 .adj = idpo.dpoi_index,
8081 },
8082 };
8083 mpls_label_t *l3300 = NULL;
8084 vec_add1(l3300, 3300);
8085
8086 lfe = fib_table_entry_update_one_path(lfib_index,
8087 &pfx_3500,
8088 FIB_SOURCE_API,
8089 FIB_ENTRY_FLAG_MULTICAST,
8090 FIB_PROTOCOL_IP4,
8091 &nh_10_10_10_1,
8092 tm->hw[0]->sw_if_index,
8093 ~0, // invalid fib index
8094 1,
8095 l3300,
8096 FIB_ROUTE_PATH_FLAG_NONE);
8097 FIB_TEST(fib_test_validate_entry(lfe,
8098 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8099 1,
8100 &mc_0),
8101 "3500 via replicate over 10.10.10.1");
8102
8103 /*
8104 * MPLS Bud-node. Add a replication via an interface-receieve path
8105 */
8106 lfe = fib_table_entry_path_add(lfib_index,
8107 &pfx_3500,
8108 FIB_SOURCE_API,
8109 FIB_ENTRY_FLAG_MULTICAST,
8110 FIB_PROTOCOL_IP4,
8111 NULL,
8112 tm->hw[0]->sw_if_index,
8113 ~0, // invalid fib index
8114 0,
8115 NULL,
8116 FIB_ROUTE_PATH_INTF_RX);
8117 FIB_TEST(fib_test_validate_entry(lfe,
8118 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8119 2,
8120 &mc_0,
8121 &mc_intf_0),
8122 "3500 via replicate over 10.10.10.1 and interface-rx");
8123
8124 /*
8125 * Add a replication via an interface-free for-us path
8126 */
8127 fib_test_rep_bucket_t mc_disp = {
8128 .type = FT_REP_DISP_MFIB_LOOKUP,
8129 .adj = {
8130 .adj = idpo.dpoi_index,
8131 },
8132 };
8133 lfe = fib_table_entry_path_add(lfib_index,
8134 &pfx_3500,
8135 FIB_SOURCE_API,
8136 FIB_ENTRY_FLAG_MULTICAST,
8137 FIB_PROTOCOL_IP4,
8138 NULL,
8139 5, // rpf-id
8140 0, // default table
8141 0,
8142 NULL,
8143 FIB_ROUTE_PATH_RPF_ID);
8144 FIB_TEST(fib_test_validate_entry(lfe,
8145 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8146 3,
8147 &mc_0,
8148 &mc_disp,
8149 &mc_intf_0),
8150 "3500 via replicate over 10.10.10.1 and interface-rx");
8151
8152
8153
8154 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8155 dpo_reset(&idpo);
8156
8157 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008158 * cleanup
8159 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008160 mpls_sw_interface_enable_disable(&mpls_main,
8161 tm->hw[0]->sw_if_index,
8162 0);
8163
Neale Rannsad422ed2016-11-02 14:20:04 +00008164 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008165 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008166 lb_count, pool_elts(load_balance_pool));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008167 FIB_TEST(0 == pool_elts(interface_dpo_pool),
8168 "interface_dpo resources freed %d of %d",
8169 0, pool_elts(interface_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008170
8171 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008172}
8173
8174static clib_error_t *
8175fib_test (vlib_main_t * vm,
8176 unformat_input_t * input,
8177 vlib_cli_command_t * cmd_arg)
8178{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008179 int res;
8180
8181 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008182 fib_test_mk_intf(4);
8183
Neale Ranns88fc83e2017-04-05 08:11:14 -07008184 if (unformat (input, "debug"))
8185 {
8186 fib_test_do_debug = 1;
8187 }
8188
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008189 if (unformat (input, "ip"))
8190 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008191 res += fib_test_v4();
8192 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008193 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008194 else if (unformat (input, "label"))
8195 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008196 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008197 }
8198 else if (unformat (input, "ae"))
8199 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008200 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008201 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008202 else if (unformat (input, "lfib"))
8203 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008204 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008205 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008206 else if (unformat (input, "walk"))
8207 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008208 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008209 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008210 else if (unformat (input, "bfd"))
8211 {
8212 res += fib_test_bfd();
8213 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008214 else
8215 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008216 res += fib_test_v4();
8217 res += fib_test_v6();
8218 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008219 res += fib_test_bfd();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008220 res += fib_test_label();
8221 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008222
8223 /*
8224 * fib-walk process must be disabled in order for the walk tests to work
8225 */
8226 fib_walk_process_disable();
8227 res += fib_test_walk();
8228 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008229 }
8230
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008231 if (res)
8232 {
8233 return clib_error_return(0, "FIB Unit Test Failed");
8234 }
8235 else
8236 {
8237 return (NULL);
8238 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008239}
8240
8241VLIB_CLI_COMMAND (test_fib_command, static) = {
8242 .path = "test fib",
8243 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8244 .function = fib_test,
8245};
8246
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008247clib_error_t *
8248fib_test_init (vlib_main_t *vm)
8249{
8250 return 0;
8251}
8252
8253VLIB_INIT_FUNCTION (fib_test_init);