blob: 92141ddfce1161eb06b29f0f794651a9639bfbde [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/fib/ip6_fib.h>
17#include <vnet/fib/ip4_fib.h>
18#include <vnet/fib/mpls_fib.h>
19#include <vnet/adj/adj.h>
20#include <vnet/dpo/load_balance.h>
21#include <vnet/dpo/load_balance_map.h>
22#include <vnet/dpo/mpls_label_dpo.h>
23#include <vnet/dpo/lookup_dpo.h>
24#include <vnet/dpo/drop_dpo.h>
25#include <vnet/dpo/receive_dpo.h>
Neale Ranns948e00f2016-10-20 13:39:34 +010026#include <vnet/dpo/ip_null_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010027
28#include <vnet/mpls/mpls.h>
29
30#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000031#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010032#include <vnet/fib/fib_walk.h>
33#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010034#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035
36#define FIB_TEST_I(_cond, _comment, _args...) \
37({ \
38 int _evald = (_cond); \
39 if (!(_evald)) { \
40 fformat(stderr, "FAIL:%d: " _comment "\n", \
41 __LINE__, ##_args); \
42 } else { \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010043 } \
44 _evald; \
45})
46#define FIB_TEST(_cond, _comment, _args...) \
47{ \
48 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000049 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010050 ASSERT(!("FAIL: " _comment)); \
51 } \
52}
53
54/**
55 * A 'i'm not fussed is this is not efficient' store of test data
56 */
57typedef struct test_main_t_ {
58 /**
59 * HW if indicies
60 */
61 u32 hw_if_indicies[4];
62 /**
63 * HW interfaces
64 */
65 vnet_hw_interface_t * hw[4];
66
67} test_main_t;
68static test_main_t test_main;
69
70/* fake ethernet device class, distinct from "fake-ethX" */
71static u8 * format_test_interface_name (u8 * s, va_list * args)
72{
73 u32 dev_instance = va_arg (*args, u32);
74 return format (s, "test-eth%d", dev_instance);
75}
76
77static uword dummy_interface_tx (vlib_main_t * vm,
78 vlib_node_runtime_t * node,
79 vlib_frame_t * frame)
80{
81 clib_warning ("you shouldn't be here, leaking buffers...");
82 return frame->n_vectors;
83}
84
Neale Ranns8b37b872016-11-21 12:25:22 +000085static clib_error_t *
86test_interface_admin_up_down (vnet_main_t * vnm,
87 u32 hw_if_index,
88 u32 flags)
89{
90 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
91 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
92 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
93 return 0;
94}
95
Neale Ranns0bfe5d82016-08-25 15:29:12 +010096VNET_DEVICE_CLASS (test_interface_device_class,static) = {
97 .name = "Test interface",
98 .format_device_name = format_test_interface_name,
99 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000100 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100101};
102
103static u8 *hw_address;
104
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000105static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100106fib_test_mk_intf (u32 ninterfaces)
107{
108 clib_error_t * error = NULL;
109 test_main_t *tm = &test_main;
110 u8 byte;
111 u32 i;
112
113 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
114
115 for (i=0; i<6; i++)
116 {
117 byte = 0xd0+i;
118 vec_add1(hw_address, byte);
119 }
120
121 for (i = 0; i < ninterfaces; i++)
122 {
123 hw_address[5] = i;
124
125 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000126 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100127 i /* instance */,
128 hw_address,
129 &tm->hw_if_indicies[i],
130 /* flag change */ 0);
131
132 FIB_TEST((NULL == error), "ADD interface %d", i);
133
Neale Ranns8b37b872016-11-21 12:25:22 +0000134 error = vnet_hw_interface_set_flags(vnet_get_main(),
135 tm->hw_if_indicies[i],
136 VNET_HW_INTERFACE_FLAG_LINK_UP);
137 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100138 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000139 vec_validate (ip4_main.fib_index_by_sw_if_index,
140 tm->hw[i]->sw_if_index);
141 vec_validate (ip6_main.fib_index_by_sw_if_index,
142 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100143 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
144 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000145
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100146 error = vnet_sw_interface_set_flags(vnet_get_main(),
147 tm->hw[i]->sw_if_index,
148 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
149 FIB_TEST((NULL == error), "UP interface %d", i);
150 }
151 /*
152 * re-eval after the inevitable realloc
153 */
154 for (i = 0; i < ninterfaces; i++)
155 {
156 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
157 tm->hw_if_indicies[i]);
158 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000159
160 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100161}
162
Neale Ranns3ee44042016-10-03 13:05:48 +0100163#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100164{ \
165 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
166 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
167 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
168 fib_table_lookup(fib_index, (_via_prefix))); \
169 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100170 load_balance_get_bucket(_rec_dpo->dpoi_index, \
171 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100172 "%U is recursive via %U", \
173 format_fib_prefix, (_rec_prefix), \
174 format_fib_prefix, _via_prefix); \
175}
176
177#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
178{ \
179 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
180 fib_table_lookup_exact_match(fib_index, (_prefix))); \
181 const dpo_id_t *_dpo1 = \
182 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
183 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
184 format_dpo_type, _dpo1->dpoi_type); \
185 FIB_TEST((_ai == _dpo1->dpoi_index), \
186 "%U bucket %d resolves via %U", \
187 format_fib_prefix, (_prefix), \
188 _bucket, \
189 format_dpo_id, _dpo1, 0); \
190}
191
Neale Ranns3ee44042016-10-03 13:05:48 +0100192#define FIB_TEST_RPF(_cond, _comment, _args...) \
193{ \
194 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
195 return (0); \
196 } \
197}
198
199static int
200fib_test_urpf_is_equal (fib_node_index_t fei,
201 fib_forward_chain_type_t fct,
202 u32 num, ...)
203{
Neale Ranns948e00f2016-10-20 13:39:34 +0100204 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100205 fib_urpf_list_t *urpf;
206 index_t ui;
207 va_list ap;
208 int ii;
209
210 va_start(ap, num);
211
212 fib_entry_contribute_forwarding(fei, fct, &dpo);
213 ui = load_balance_get_urpf(dpo.dpoi_index);
214
215 urpf = fib_urpf_list_get(ui);
216
217 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
218 "RPF:%U len %d == %d",
219 format_fib_urpf_list, ui,
220 num, vec_len(urpf->furpf_itfs));
221 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
222 "RPF:%U check-size %d == %d",
223 format_fib_urpf_list, ui,
224 num, vec_len(urpf->furpf_itfs));
225
226 for (ii = 0; ii < num; ii++)
227 {
228 adj_index_t ai = va_arg(ap, adj_index_t);
229
230 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
231 "RPF:%d item:%d - %d == %d",
232 ui, ii, ai, urpf->furpf_itfs[ii]);
233 FIB_TEST_RPF(fib_urpf_check(ui, ai),
234 "RPF:%d %d found",
235 ui, ai);
236 }
237
238 dpo_reset(&dpo);
239
Neale Ranns5899fde2016-10-12 13:51:05 +0100240 va_end(ap);
241
Neale Ranns3ee44042016-10-03 13:05:48 +0100242 return (1);
243}
244
Neale Rannsb80c5362016-10-08 13:03:40 +0100245static u8*
246fib_test_build_rewrite (u8 *eth_addr)
247{
248 u8* rewrite = NULL;
249
250 vec_validate(rewrite, 13);
251
252 memcpy(rewrite, eth_addr, 6);
253 memcpy(rewrite+6, eth_addr, 6);
254
255 return (rewrite);
256}
257
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000258typedef enum fib_test_lb_bucket_type_t_ {
259 FT_LB_LABEL_O_ADJ,
Neale Rannsad422ed2016-11-02 14:20:04 +0000260 FT_LB_LABEL_STACK_O_ADJ,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000261 FT_LB_LABEL_O_LB,
262 FT_LB_O_LB,
263 FT_LB_SPECIAL,
264 FT_LB_ADJ,
265} fib_test_lb_bucket_type_t;
266
267typedef struct fib_test_lb_bucket_t_ {
268 fib_test_lb_bucket_type_t type;
269
270 union
271 {
272 struct
273 {
274 mpls_eos_bit_t eos;
275 mpls_label_t label;
276 u8 ttl;
277 adj_index_t adj;
278 } label_o_adj;
279 struct
280 {
281 mpls_eos_bit_t eos;
Neale Rannsad422ed2016-11-02 14:20:04 +0000282 mpls_label_t label_stack[8];
283 u8 label_stack_size;
284 u8 ttl;
285 adj_index_t adj;
286 } label_stack_o_adj;
287 struct
288 {
289 mpls_eos_bit_t eos;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000290 mpls_label_t label;
291 u8 ttl;
292 index_t lb;
293 } label_o_lb;
294 struct
295 {
296 index_t adj;
297 } adj;
298 struct
299 {
300 index_t lb;
301 } lb;
302 struct
303 {
304 index_t adj;
305 } special;
306 };
307} fib_test_lb_bucket_t;
308
309#define FIB_TEST_LB(_cond, _comment, _args...) \
310{ \
311 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
312 return (0); \
313 } \
314}
315
316static int
317fib_test_validate_lb_v (const load_balance_t *lb,
318 u16 n_buckets,
319 va_list ap)
320{
321 const dpo_id_t *dpo;
322 int bucket;
323
324 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
325
326 for (bucket = 0; bucket < n_buckets; bucket++)
327 {
328 const fib_test_lb_bucket_t *exp;
329
330 exp = va_arg(ap, fib_test_lb_bucket_t*);
331 dpo = load_balance_get_bucket_i(lb, bucket);
332
333 switch (exp->type)
334 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000335 case FT_LB_LABEL_STACK_O_ADJ:
336 {
337 const mpls_label_dpo_t *mld;
338 mpls_label_t hdr;
339 u32 ii;
340
341 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
342 "bucket %d stacks on %U",
343 bucket,
344 format_dpo_type, dpo->dpoi_type);
345
346 mld = mpls_label_dpo_get(dpo->dpoi_index);
347
348 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
349 "label stack size",
350 mld->mld_n_labels);
351
352 for (ii = 0; ii < mld->mld_n_labels; ii++)
353 {
354 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
355 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
356 exp->label_stack_o_adj.label_stack[ii]),
357 "bucket %d stacks on label %d",
358 bucket,
359 exp->label_stack_o_adj.label_stack[ii]);
360
361 if (ii == mld->mld_n_labels-1)
362 {
363 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
364 exp->label_o_adj.eos),
365 "bucket %d stacks on label %d %U!=%U",
366 bucket,
367 exp->label_stack_o_adj.label_stack[ii],
368 format_mpls_eos_bit, exp->label_o_adj.eos,
369 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
370 }
371 else
372 {
373 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
374 "bucket %d stacks on label %d %U",
375 bucket,
376 exp->label_stack_o_adj.label_stack[ii],
377 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
378 }
379 }
380
381 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
382 "bucket %d label stacks on %U",
383 bucket,
384 format_dpo_type, mld->mld_dpo.dpoi_type);
385
386 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
387 "bucket %d label stacks on adj %d",
388 bucket,
389 exp->label_stack_o_adj.adj);
390 }
391 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000392 case FT_LB_LABEL_O_ADJ:
393 {
394 const mpls_label_dpo_t *mld;
395 mpls_label_t hdr;
396 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
397 "bucket %d stacks on %U",
398 bucket,
399 format_dpo_type, dpo->dpoi_type);
400
401 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000402 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000403
404 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
405 exp->label_o_adj.label),
406 "bucket %d stacks on label %d",
407 bucket,
408 exp->label_o_adj.label);
409
410 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
411 exp->label_o_adj.eos),
412 "bucket %d stacks on label %d %U",
413 bucket,
414 exp->label_o_adj.label,
415 format_mpls_eos_bit, exp->label_o_adj.eos);
416
417 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
418 "bucket %d label stacks on %U",
419 bucket,
420 format_dpo_type, mld->mld_dpo.dpoi_type);
421
422 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
423 "bucket %d label stacks on adj %d",
424 bucket,
425 exp->label_o_adj.adj);
426 }
427 break;
428 case FT_LB_LABEL_O_LB:
429 {
430 const mpls_label_dpo_t *mld;
431 mpls_label_t hdr;
432
433 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
434 "bucket %d stacks on %U",
435 bucket,
436 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000437
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000438 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000439 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000440
Neale Rannsad422ed2016-11-02 14:20:04 +0000441 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
442 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000443 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
444 exp->label_o_lb.label),
445 "bucket %d stacks on label %d",
446 bucket,
447 exp->label_o_lb.label);
448
449 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
450 exp->label_o_lb.eos),
451 "bucket %d stacks on label %d %U",
452 bucket,
453 exp->label_o_lb.label,
454 format_mpls_eos_bit, exp->label_o_lb.eos);
455
456 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
457 "bucket %d label stacks on %U",
458 bucket,
459 format_dpo_type, mld->mld_dpo.dpoi_type);
460
461 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
462 "bucket %d label stacks on LB %d",
463 bucket,
464 exp->label_o_lb.lb);
465 }
466 break;
467 case FT_LB_ADJ:
468 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
469 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
470 "bucket %d stacks on %U",
471 bucket,
472 format_dpo_type, dpo->dpoi_type);
473 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
474 "bucket %d stacks on adj %d",
475 bucket,
476 exp->adj.adj);
477 break;
478 case FT_LB_O_LB:
479 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
480 "bucket %d stacks on %U",
481 bucket,
482 format_dpo_type, dpo->dpoi_type);
483 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
484 "bucket %d stacks on lb %d",
485 bucket,
486 exp->lb.lb);
487 break;
488 case FT_LB_SPECIAL:
489 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
490 "bucket %d stacks on %U",
491 bucket,
492 format_dpo_type, dpo->dpoi_type);
493 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
494 "bucket %d stacks on drop %d",
495 bucket,
496 exp->special.adj);
497 break;
498 }
499 }
500 return (!0);
501}
502
503static int
504fib_test_validate_entry (fib_node_index_t fei,
505 fib_forward_chain_type_t fct,
506 u16 n_buckets,
507 ...)
508{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000509 dpo_id_t dpo = DPO_INVALID;
Neale Rannsad422ed2016-11-02 14:20:04 +0000510 const load_balance_t *lb;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000511 fib_prefix_t pfx;
512 index_t fw_lbi;
513 u32 fib_index;
514 va_list ap;
515 int res;
516
517 va_start(ap, n_buckets);
518
519 fib_entry_get_prefix(fei, &pfx);
520 fib_index = fib_entry_get_fib_index(fei);
521 fib_entry_contribute_forwarding(fei, fct, &dpo);
522
523 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
524 "Entry links to %U",
525 format_dpo_type, dpo.dpoi_type);
526 lb = load_balance_get(dpo.dpoi_index);
527
528 res = fib_test_validate_lb_v(lb, n_buckets, ap);
529
530 /*
531 * ensure that the LB contributed by the entry is the
532 * same as the LB in the forwarding tables
533 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000534 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000535 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000536 switch (pfx.fp_proto)
537 {
538 case FIB_PROTOCOL_IP4:
539 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
540 break;
541 case FIB_PROTOCOL_IP6:
542 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
543 break;
544 case FIB_PROTOCOL_MPLS:
545 {
546 mpls_unicast_header_t hdr = {
547 .label_exp_s_ttl = 0,
548 };
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000549
Neale Rannsad422ed2016-11-02 14:20:04 +0000550 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
551 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
552 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000553
Neale Rannsad422ed2016-11-02 14:20:04 +0000554 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
555 break;
556 }
557 default:
558 fw_lbi = 0;
559 }
560 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
561 "Contributed LB = FW LB: %U\n %U",
562 format_load_balance, fw_lbi, 0,
563 format_load_balance, dpo.dpoi_index, 0);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000564 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000565
566 dpo_reset(&dpo);
567
568 va_end(ap);
569
570 return (res);
571}
572
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000573static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100574fib_test_v4 (void)
575{
576 /*
577 * In the default table check for the presence and correct forwarding
578 * of the special entries
579 */
580 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
581 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
582 const ip_adjacency_t *adj;
583 const load_balance_t *lb;
584 test_main_t *tm;
585 u32 fib_index;
586 int ii;
587
588 /* via 10.10.10.1 */
589 ip46_address_t nh_10_10_10_1 = {
590 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
591 };
592 /* via 10.10.10.2 */
593 ip46_address_t nh_10_10_10_2 = {
594 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
595 };
596
597 tm = &test_main;
598
599 /* Find or create FIB table 11 */
600 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
601
602 for (ii = 0; ii < 4; ii++)
603 {
604 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
605 }
606
607 fib_prefix_t pfx_0_0_0_0_s_0 = {
608 .fp_len = 0,
609 .fp_proto = FIB_PROTOCOL_IP4,
610 .fp_addr = {
611 .ip4 = {
612 {0}
613 },
614 },
615 };
616
617 fib_prefix_t pfx = {
618 .fp_len = 0,
619 .fp_proto = FIB_PROTOCOL_IP4,
620 .fp_addr = {
621 .ip4 = {
622 {0}
623 },
624 },
625 };
626
627 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
628
629 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
630 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
631 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
632 "Default route is DROP");
633
634 pfx.fp_len = 32;
635 fei = fib_table_lookup(fib_index, &pfx);
636 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
637 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
638 "all 0s route is DROP");
639
640 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
641 pfx.fp_len = 32;
642 fei = fib_table_lookup(fib_index, &pfx);
643 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
644 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
645 "all 1s route is DROP");
646
647 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
648 pfx.fp_len = 8;
649 fei = fib_table_lookup(fib_index, &pfx);
650 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
651 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
652 "all-mcast route is DROP");
653
654 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
655 pfx.fp_len = 8;
656 fei = fib_table_lookup(fib_index, &pfx);
657 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
658 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
659 "class-e route is DROP");
660
661 /*
662 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
663 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000664 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
665 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100666 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000667#define ENBR (5+5+2)
668#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100669 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000670 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100671 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000672 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100673 fib_entry_pool_size());
674
675 /*
676 * add interface routes.
677 * validate presence of /24 attached and /32 recieve.
678 * test for the presence of the receive address in the glean and local adj
679 */
680 fib_prefix_t local_pfx = {
681 .fp_len = 24,
682 .fp_proto = FIB_PROTOCOL_IP4,
683 .fp_addr = {
684 .ip4 = {
685 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
686 },
687 },
688 };
689
690 fib_table_entry_update_one_path(fib_index, &local_pfx,
691 FIB_SOURCE_INTERFACE,
692 (FIB_ENTRY_FLAG_CONNECTED |
693 FIB_ENTRY_FLAG_ATTACHED),
694 FIB_PROTOCOL_IP4,
695 NULL,
696 tm->hw[0]->sw_if_index,
697 ~0, // invalid fib index
698 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000699 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100700 FIB_ROUTE_PATH_FLAG_NONE);
701 fei = fib_table_lookup(fib_index, &local_pfx);
702 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
703 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
704 fib_entry_get_flags(fei)),
705 "Flags set on attached interface");
706
707 ai = fib_entry_get_adj(fei);
708 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
709 adj = adj_get(ai);
710 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
711 "attached interface adj is glean");
712 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
713 &adj->sub_type.glean.receive_addr)),
714 "attached interface adj is receive ok");
715
716 local_pfx.fp_len = 32;
717 fib_table_entry_update_one_path(fib_index, &local_pfx,
718 FIB_SOURCE_INTERFACE,
719 (FIB_ENTRY_FLAG_CONNECTED |
720 FIB_ENTRY_FLAG_LOCAL),
721 FIB_PROTOCOL_IP4,
722 NULL,
723 tm->hw[0]->sw_if_index,
724 ~0, // invalid fib index
725 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000726 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100727 FIB_ROUTE_PATH_FLAG_NONE);
728 fei = fib_table_lookup(fib_index, &local_pfx);
729 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
730 fib_entry_get_flags(fei)),
731 "Flags set on local interface");
732
733 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
734
735 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100736 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
737 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100738 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
739 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
740 "local interface adj is local");
741 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
742
743 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
744 &rd->rd_addr)),
745 "local interface adj is receive ok");
746
747 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
748 FIB_PROTOCOL_IP4,
749 FIB_SOURCE_INTERFACE)),
750 "2 Interface Source'd prefixes");
751
752 /*
753 * +2 interface routes +2 non-shared path-lists
754 */
755 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000756 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100757 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000758 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100759 fib_entry_pool_size());
760
761 /*
762 * Modify the default route to be via an adj not yet known.
763 * this sources the defalut route with the API source, which is
764 * a higher preference to the DEFAULT_ROUTE source
765 */
766 pfx.fp_addr.ip4.as_u32 = 0;
767 pfx.fp_len = 0;
768 fib_table_entry_path_add(fib_index, &pfx,
769 FIB_SOURCE_API,
770 FIB_ENTRY_FLAG_NONE,
771 FIB_PROTOCOL_IP4,
772 &nh_10_10_10_1,
773 tm->hw[0]->sw_if_index,
774 ~0, // invalid fib index
775 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000776 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100777 FIB_ROUTE_PATH_FLAG_NONE);
778 fei = fib_table_lookup(fib_index, &pfx);
779 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
780 "Flags set on API route");
781
782 FIB_TEST((fei == dfrt), "default route same index");
783 ai = fib_entry_get_adj(fei);
784 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
785 adj = adj_get(ai);
786 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
787 "adj is incomplete");
788 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
789 "adj nbr next-hop ok");
790 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
791 FIB_PROTOCOL_IP4,
792 FIB_SOURCE_API)),
793 "1 API Source'd prefixes");
794
795 /*
796 * find the adj in the shared db
797 */
798 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100799 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100800 &nh_10_10_10_1,
801 tm->hw[0]->sw_if_index);
802 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
803 adj_unlock(locked_ai);
804
805 /*
806 * +1 shared path-list
807 */
808 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
809 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000810 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100811 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000812 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100813 fib_entry_pool_size());
814
815 /*
816 * remove the API source from the default route. We expected
817 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
818 */
819 pfx.fp_addr.ip4.as_u32 = 0;
820 pfx.fp_len = 0;
821 fib_table_entry_path_remove(fib_index, &pfx,
822 FIB_SOURCE_API,
823 FIB_PROTOCOL_IP4,
824 &nh_10_10_10_1,
825 tm->hw[0]->sw_if_index,
826 ~0, // non-recursive path, so no FIB index
827 1,
828 FIB_ROUTE_PATH_FLAG_NONE);
829
830 fei = fib_table_lookup(fib_index, &pfx);
831
832 FIB_TEST((fei == dfrt), "default route same index");
833 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
834 "Default route is DROP");
835
836 /*
837 * -1 shared-path-list
838 */
839 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000840 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100841 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000842 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100843 fib_entry_pool_size());
844
845 /*
846 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
847 */
848 fib_prefix_t pfx_10_10_10_1_s_32 = {
849 .fp_len = 32,
850 .fp_proto = FIB_PROTOCOL_IP4,
851 .fp_addr = {
852 /* 10.10.10.1 */
853 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
854 },
855 };
856 fib_prefix_t pfx_10_10_10_2_s_32 = {
857 .fp_len = 32,
858 .fp_proto = FIB_PROTOCOL_IP4,
859 .fp_addr = {
860 /* 10.10.10.2 */
861 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
862 },
863 };
864 fib_prefix_t pfx_11_11_11_11_s_32 = {
865 .fp_len = 32,
866 .fp_proto = FIB_PROTOCOL_IP4,
867 .fp_addr = {
868 /* 11.11.11.11 */
869 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
870 },
871 };
872 u8 eth_addr[] = {
873 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
874 };
Neale Rannsb80c5362016-10-08 13:03:40 +0100875
Neale Ranns3ee44042016-10-03 13:05:48 +0100876 ip46_address_t nh_12_12_12_12 = {
877 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
878 };
879 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100880
881 /*
882 * Add a route via an incomplete ADJ. then complete the ADJ
883 * Expect the route LB is updated to use complete adj type.
884 */
885 fei = fib_table_entry_update_one_path(fib_index,
886 &pfx_11_11_11_11_s_32,
887 FIB_SOURCE_API,
888 FIB_ENTRY_FLAG_ATTACHED,
889 FIB_PROTOCOL_IP4,
890 &pfx_10_10_10_1_s_32.fp_addr,
891 tm->hw[0]->sw_if_index,
892 ~0, // invalid fib index
893 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000894 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100895 FIB_ROUTE_PATH_FLAG_NONE);
896
897 dpo = fib_entry_contribute_ip_forwarding(fei);
898 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
899 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
900 "11.11.11.11/32 via incomplete adj");
901
902 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100903 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100904 &pfx_10_10_10_1_s_32.fp_addr,
905 tm->hw[0]->sw_if_index);
906 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
907 adj = adj_get(ai_01);
908 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
909 "adj is incomplete");
910 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
911 &adj->sub_type.nbr.next_hop)),
912 "adj nbr next-hop ok");
913
Neale Rannsb80c5362016-10-08 13:03:40 +0100914 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
915 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100916 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
917 "adj is complete");
918 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
919 &adj->sub_type.nbr.next_hop)),
920 "adj nbr next-hop ok");
921 ai = fib_entry_get_adj(fei);
922 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
923
924 dpo = fib_entry_contribute_ip_forwarding(fei);
925 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
926 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
927 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +0100928 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
929 tm->hw[0]->sw_if_index),
930 "RPF list for adj-fib contains adj");
931
932 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100933 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +0100934 &nh_12_12_12_12,
935 tm->hw[1]->sw_if_index);
936 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
937 adj = adj_get(ai_12_12_12_12);
938 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
939 "adj is incomplete");
940 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
941 &adj->sub_type.nbr.next_hop)),
942 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +0100943 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
944 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +0100945 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
946 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100947
948 /*
949 * add the adj fib
950 */
951 fei = fib_table_entry_update_one_path(fib_index,
952 &pfx_10_10_10_1_s_32,
953 FIB_SOURCE_ADJ,
954 FIB_ENTRY_FLAG_ATTACHED,
955 FIB_PROTOCOL_IP4,
956 &pfx_10_10_10_1_s_32.fp_addr,
957 tm->hw[0]->sw_if_index,
958 ~0, // invalid fib index
959 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000960 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100961 FIB_ROUTE_PATH_FLAG_NONE);
962 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
963 "Flags set on adj-fib");
964 ai = fib_entry_get_adj(fei);
965 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
966
967 fib_table_entry_path_remove(fib_index,
968 &pfx_11_11_11_11_s_32,
969 FIB_SOURCE_API,
970 FIB_PROTOCOL_IP4,
971 &pfx_10_10_10_1_s_32.fp_addr,
972 tm->hw[0]->sw_if_index,
973 ~0, // invalid fib index
974 1,
975 FIB_ROUTE_PATH_FLAG_NONE);
976
977 eth_addr[5] = 0xb2;
978
979 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100980 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100981 &pfx_10_10_10_2_s_32.fp_addr,
982 tm->hw[0]->sw_if_index);
983 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
984 adj = adj_get(ai_02);
985 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
986 "adj is incomplete");
987 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
988 &adj->sub_type.nbr.next_hop)),
989 "adj nbr next-hop ok");
990
Neale Rannsb80c5362016-10-08 13:03:40 +0100991 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
992 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100993 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
994 "adj is complete");
995 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
996 &adj->sub_type.nbr.next_hop)),
997 "adj nbr next-hop ok");
998 FIB_TEST((ai_01 != ai_02), "ADJs are different");
999
1000 fib_table_entry_update_one_path(fib_index,
1001 &pfx_10_10_10_2_s_32,
1002 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00001003 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001004 FIB_PROTOCOL_IP4,
1005 &pfx_10_10_10_2_s_32.fp_addr,
1006 tm->hw[0]->sw_if_index,
1007 ~0, // invalid fib index
1008 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001009 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001010 FIB_ROUTE_PATH_FLAG_NONE);
1011
1012 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1013 ai = fib_entry_get_adj(fei);
1014 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1015
1016 /*
1017 * +2 adj-fibs, and their non-shared path-lists
1018 */
1019 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001020 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001021 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001022 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001023 fib_entry_pool_size());
1024
1025 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001026 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001027 */
1028 fib_prefix_t pfx_1_1_1_1_s_32 = {
1029 .fp_len = 32,
1030 .fp_proto = FIB_PROTOCOL_IP4,
1031 .fp_addr = {
1032 /* 1.1.1.1/32 */
1033 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1034 },
1035 };
1036
1037 fib_table_entry_path_add(fib_index,
1038 &pfx_1_1_1_1_s_32,
1039 FIB_SOURCE_API,
1040 FIB_ENTRY_FLAG_NONE,
1041 FIB_PROTOCOL_IP4,
1042 &nh_10_10_10_1,
1043 tm->hw[0]->sw_if_index,
1044 ~0, // invalid fib index
1045 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001046 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001047 FIB_ROUTE_PATH_FLAG_NONE);
1048 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1049 ai = fib_entry_get_adj(fei);
1050 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1051
1052 /*
1053 * +1 entry and a shared path-list
1054 */
1055 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001056 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001057 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001058 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001059 fib_entry_pool_size());
1060
1061 /* 1.1.2.0/24 */
1062 fib_prefix_t pfx_1_1_2_0_s_24 = {
1063 .fp_len = 24,
1064 .fp_proto = FIB_PROTOCOL_IP4,
1065 .fp_addr = {
1066 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1067 }
1068 };
1069
1070 fib_table_entry_path_add(fib_index,
1071 &pfx_1_1_2_0_s_24,
1072 FIB_SOURCE_API,
1073 FIB_ENTRY_FLAG_NONE,
1074 FIB_PROTOCOL_IP4,
1075 &nh_10_10_10_1,
1076 tm->hw[0]->sw_if_index,
1077 ~0, // invalid fib index
1078 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001079 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001080 FIB_ROUTE_PATH_FLAG_NONE);
1081 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1082 ai = fib_entry_get_adj(fei);
1083 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1084
1085 /*
1086 * +1 entry only
1087 */
1088 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001089 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001090 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001091 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001092 fib_entry_pool_size());
1093
1094 /*
1095 * modify 1.1.2.0/24 to use multipath.
1096 */
1097 fib_table_entry_path_add(fib_index,
1098 &pfx_1_1_2_0_s_24,
1099 FIB_SOURCE_API,
1100 FIB_ENTRY_FLAG_NONE,
1101 FIB_PROTOCOL_IP4,
1102 &nh_10_10_10_2,
1103 tm->hw[0]->sw_if_index,
1104 ~0, // invalid fib index
1105 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001106 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001107 FIB_ROUTE_PATH_FLAG_NONE);
1108 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1109 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001110 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1111 1, tm->hw[0]->sw_if_index),
1112 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001113
1114 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1115 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1116 FIB_TEST((ai_01 == dpo1->dpoi_index),
1117 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1118 ai_01, dpo1->dpoi_index);
1119
1120 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1121 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1122 FIB_TEST((ai_02 == dpo1->dpoi_index),
1123 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1124
1125 /*
1126 * +1 shared-pathlist
1127 */
1128 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001129 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001130 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001131 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001132 fib_entry_pool_size());
1133
1134 /*
1135 * revert the modify
1136 */
1137 fib_table_entry_path_remove(fib_index,
1138 &pfx_1_1_2_0_s_24,
1139 FIB_SOURCE_API,
1140 FIB_PROTOCOL_IP4,
1141 &nh_10_10_10_2,
1142 tm->hw[0]->sw_if_index,
1143 ~0,
1144 1,
1145 FIB_ROUTE_PATH_FLAG_NONE);
1146 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001147 dpo = fib_entry_contribute_ip_forwarding(fei);
1148 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1149 1, tm->hw[0]->sw_if_index),
1150 "RPF list for 1.1.2.0/24 contains one adj");
1151
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001152 ai = fib_entry_get_adj(fei);
1153 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1154
1155 /*
1156 * +1 shared-pathlist
1157 */
1158 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1159 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001160 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001161 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001162 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001163 fib_entry_pool_size());
1164
1165 /*
1166 * Add 2 recursive routes:
1167 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1168 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1169 */
1170 fib_prefix_t bgp_100_pfx = {
1171 .fp_len = 32,
1172 .fp_proto = FIB_PROTOCOL_IP4,
1173 .fp_addr = {
1174 /* 100.100.100.100/32 */
1175 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1176 },
1177 };
1178 /* via 1.1.1.1 */
1179 ip46_address_t nh_1_1_1_1 = {
1180 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1181 };
1182
Neale Ranns3ee44042016-10-03 13:05:48 +01001183 fei = fib_table_entry_path_add(fib_index,
1184 &bgp_100_pfx,
1185 FIB_SOURCE_API,
1186 FIB_ENTRY_FLAG_NONE,
1187 FIB_PROTOCOL_IP4,
1188 &nh_1_1_1_1,
1189 ~0, // no index provided.
1190 fib_index, // nexthop in same fib as route
1191 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001192 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001193 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001194
Neale Ranns3ee44042016-10-03 13:05:48 +01001195 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1196 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1197 tm->hw[0]->sw_if_index),
1198 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001199
1200 /*
1201 * +1 entry and +1 shared-path-list
1202 */
1203 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1204 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001205 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001206 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001207 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001208 fib_entry_pool_size());
1209
1210 fib_prefix_t bgp_101_pfx = {
1211 .fp_len = 32,
1212 .fp_proto = FIB_PROTOCOL_IP4,
1213 .fp_addr = {
1214 /* 100.100.100.101/32 */
1215 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1216 },
1217 };
1218
1219 fib_table_entry_path_add(fib_index,
1220 &bgp_101_pfx,
1221 FIB_SOURCE_API,
1222 FIB_ENTRY_FLAG_NONE,
1223 FIB_PROTOCOL_IP4,
1224 &nh_1_1_1_1,
1225 ~0, // no index provided.
1226 fib_index, // nexthop in same fib as route
1227 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001228 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001229 FIB_ROUTE_PATH_FLAG_NONE);
1230
Neale Ranns3ee44042016-10-03 13:05:48 +01001231 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1232 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1233 tm->hw[0]->sw_if_index),
1234 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001235
1236 /*
1237 * +1 entry, but the recursive path-list is shared.
1238 */
1239 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1240 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001241 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001242 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001243 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001244 fib_entry_pool_size());
1245
1246 /*
1247 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1248 * adjacency through which the route will resovle
1249 */
1250 fib_prefix_t ex_pfx = {
1251 .fp_len = 32,
1252 .fp_proto = FIB_PROTOCOL_IP4,
1253 .fp_addr = {
1254 /* 4.4.4.4/32 */
1255 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1256 },
1257 };
1258
1259 fib_table_entry_special_add(fib_index,
1260 &ex_pfx,
1261 FIB_SOURCE_SPECIAL,
1262 FIB_ENTRY_FLAG_EXCLUSIVE,
1263 locked_ai);
1264 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1265 FIB_TEST((ai == fib_entry_get_adj(fei)),
1266 "Exclusive route links to user adj");
1267
1268 fib_table_entry_special_remove(fib_index,
1269 &ex_pfx,
1270 FIB_SOURCE_SPECIAL);
1271 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1272 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1273 "Exclusive reoute removed");
1274
1275 /*
1276 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1277 * adjacency through which the route will resovle
1278 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001279 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001280
1281 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1282 DPO_PROTO_IP4,
1283 LOOKUP_INPUT_DST_ADDR,
1284 LOOKUP_TABLE_FROM_CONFIG,
1285 &ex_dpo);
1286
1287 fib_table_entry_special_dpo_add(fib_index,
1288 &ex_pfx,
1289 FIB_SOURCE_SPECIAL,
1290 FIB_ENTRY_FLAG_EXCLUSIVE,
1291 &ex_dpo);
1292 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1293 dpo = fib_entry_contribute_ip_forwarding(fei);
1294 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1295 "exclusive remote uses lookup DPO");
1296
Neale Ranns948e00f2016-10-20 13:39:34 +01001297 /*
1298 * update the exclusive to use a different DPO
1299 */
Neale Ranns450cd302016-11-09 17:49:42 +00001300 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001301 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1302 &ex_dpo);
1303 fib_table_entry_special_dpo_update(fib_index,
1304 &ex_pfx,
1305 FIB_SOURCE_SPECIAL,
1306 FIB_ENTRY_FLAG_EXCLUSIVE,
1307 &ex_dpo);
1308 dpo = fib_entry_contribute_ip_forwarding(fei);
1309 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1310 "exclusive remote uses now uses NULL DPO");
1311
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001312 fib_table_entry_special_remove(fib_index,
1313 &ex_pfx,
1314 FIB_SOURCE_SPECIAL);
1315 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1316 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1317 "Exclusive reoute removed");
1318 dpo_reset(&ex_dpo);
1319
1320 /*
1321 * Add a recursive route:
1322 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1323 */
1324 fib_prefix_t bgp_200_pfx = {
1325 .fp_len = 32,
1326 .fp_proto = FIB_PROTOCOL_IP4,
1327 .fp_addr = {
1328 /* 200.200.200.200/32 */
1329 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1330 },
1331 };
1332 /* via 1.1.1.2 */
1333 fib_prefix_t pfx_1_1_1_2_s_32 = {
1334 .fp_len = 32,
1335 .fp_proto = FIB_PROTOCOL_IP4,
1336 .fp_addr = {
1337 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1338 },
1339 };
1340
1341 fib_table_entry_path_add(fib_index,
1342 &bgp_200_pfx,
1343 FIB_SOURCE_API,
1344 FIB_ENTRY_FLAG_NONE,
1345 FIB_PROTOCOL_IP4,
1346 &pfx_1_1_1_2_s_32.fp_addr,
1347 ~0, // no index provided.
1348 fib_index, // nexthop in same fib as route
1349 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001350 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001351 FIB_ROUTE_PATH_FLAG_NONE);
1352
Neale Ranns3ee44042016-10-03 13:05:48 +01001353 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001354
1355 /*
1356 * the adj should be recursive via drop, since the route resolves via
1357 * the default route, which is itself a DROP
1358 */
1359 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1360 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1361 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001362 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1363 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001364
1365 /*
1366 * +2 entry and +1 shared-path-list
1367 */
1368 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1369 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001370 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001371 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001372 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001373 fib_entry_pool_size());
1374
1375 /*
1376 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001377 * The paths are sort by NH first. in this case the the path with greater
1378 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001379 */
1380 fib_prefix_t pfx_1_2_3_4_s_32 = {
1381 .fp_len = 32,
1382 .fp_proto = FIB_PROTOCOL_IP4,
1383 .fp_addr = {
1384 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1385 },
1386 };
1387 fib_table_entry_path_add(fib_index,
1388 &pfx_1_2_3_4_s_32,
1389 FIB_SOURCE_API,
1390 FIB_ENTRY_FLAG_NONE,
1391 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001392 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001393 tm->hw[0]->sw_if_index,
1394 ~0,
1395 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001396 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001397 FIB_ROUTE_PATH_FLAG_NONE);
1398 fei = fib_table_entry_path_add(fib_index,
1399 &pfx_1_2_3_4_s_32,
1400 FIB_SOURCE_API,
1401 FIB_ENTRY_FLAG_NONE,
1402 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001403 &nh_12_12_12_12,
1404 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001405 ~0,
1406 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001407 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001408 FIB_ROUTE_PATH_FLAG_NONE);
1409
1410 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1411 dpo = fib_entry_contribute_ip_forwarding(fei);
1412 lb = load_balance_get(dpo->dpoi_index);
1413 FIB_TEST((lb->lb_n_buckets == 4),
1414 "1.2.3.4/32 LB has %d bucket",
1415 lb->lb_n_buckets);
1416
Neale Ranns3ee44042016-10-03 13:05:48 +01001417 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1418 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1419 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1420 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001421
Neale Ranns3ee44042016-10-03 13:05:48 +01001422 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1423 tm->hw[0]->sw_if_index,
1424 tm->hw[1]->sw_if_index),
1425 "RPF list for 1.2.3.4/32 contains both adjs");
1426
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001427
1428 /*
1429 * Unequal Cost load-balance. 4:1 ratio.
1430 * fits in a 16 bucket LB with ratio 13:3
1431 */
1432 fib_prefix_t pfx_1_2_3_5_s_32 = {
1433 .fp_len = 32,
1434 .fp_proto = FIB_PROTOCOL_IP4,
1435 .fp_addr = {
1436 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1437 },
1438 };
1439 fib_table_entry_path_add(fib_index,
1440 &pfx_1_2_3_5_s_32,
1441 FIB_SOURCE_API,
1442 FIB_ENTRY_FLAG_NONE,
1443 FIB_PROTOCOL_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001444 &nh_12_12_12_12,
1445 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001446 ~0,
1447 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001448 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001449 FIB_ROUTE_PATH_FLAG_NONE);
1450 fei = fib_table_entry_path_add(fib_index,
1451 &pfx_1_2_3_5_s_32,
1452 FIB_SOURCE_API,
1453 FIB_ENTRY_FLAG_NONE,
1454 FIB_PROTOCOL_IP4,
1455 &nh_10_10_10_1,
1456 tm->hw[0]->sw_if_index,
1457 ~0,
1458 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001459 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001460 FIB_ROUTE_PATH_FLAG_NONE);
1461
1462 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1463 dpo = fib_entry_contribute_ip_forwarding(fei);
1464 lb = load_balance_get(dpo->dpoi_index);
1465 FIB_TEST((lb->lb_n_buckets == 16),
1466 "1.2.3.5/32 LB has %d bucket",
1467 lb->lb_n_buckets);
1468
1469 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1470 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1471 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1472 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1473 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1474 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1475 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1476 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1477 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1478 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1479 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1480 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1481 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001482 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1483 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1484 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1485
1486 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1487 tm->hw[0]->sw_if_index,
1488 tm->hw[1]->sw_if_index),
1489 "RPF list for 1.2.3.4/32 contains both adjs");
1490
1491 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001492 * Test UCMP with a large weight skew - this produces load-balance objects with large
1493 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1494 * laso testing the LB in placce modify code when number of buckets is large.
1495 */
1496 fib_prefix_t pfx_6_6_6_6_s_32 = {
1497 .fp_len = 32,
1498 .fp_proto = FIB_PROTOCOL_IP4,
1499 .fp_addr = {
1500 /* 1.1.1.1/32 */
1501 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1502 },
1503 };
1504 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
1505 .type = FT_LB_ADJ,
1506 .adj = {
1507 .adj = ai_01,
1508 },
1509 };
1510 fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
1511 .type = FT_LB_ADJ,
1512 .adj = {
1513 .adj = ai_02,
1514 },
1515 };
1516 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1517 .type = FT_LB_ADJ,
1518 .adj = {
1519 .adj = ai_12_12_12_12,
1520 },
1521 };
1522 fib_table_entry_update_one_path(fib_index,
1523 &pfx_6_6_6_6_s_32,
1524 FIB_SOURCE_API,
1525 FIB_ENTRY_FLAG_NONE,
1526 FIB_PROTOCOL_IP4,
1527 &nh_10_10_10_1,
1528 tm->hw[0]->sw_if_index,
1529 ~0, // invalid fib index
1530 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001531 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001532 FIB_ROUTE_PATH_FLAG_NONE);
1533
1534 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1535 FIB_TEST(fib_test_validate_entry(fei,
1536 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1537 1,
1538 &ip_6_6_6_6_o_10_10_10_1),
1539 "6.6.6.6/32 via 10.10.10.1");
1540
1541 fib_table_entry_path_add(fib_index,
1542 &pfx_6_6_6_6_s_32,
1543 FIB_SOURCE_API,
1544 FIB_ENTRY_FLAG_NONE,
1545 FIB_PROTOCOL_IP4,
1546 &nh_10_10_10_2,
1547 tm->hw[0]->sw_if_index,
1548 ~0, // invalid fib index
1549 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001550 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001551 FIB_ROUTE_PATH_FLAG_NONE);
1552
1553 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1554 FIB_TEST(fib_test_validate_entry(fei,
1555 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1556 64,
1557 &ip_6_6_6_6_o_10_10_10_2,
1558 &ip_6_6_6_6_o_10_10_10_2,
1559 &ip_6_6_6_6_o_10_10_10_2,
1560 &ip_6_6_6_6_o_10_10_10_2,
1561 &ip_6_6_6_6_o_10_10_10_2,
1562 &ip_6_6_6_6_o_10_10_10_2,
1563 &ip_6_6_6_6_o_10_10_10_2,
1564 &ip_6_6_6_6_o_10_10_10_2,
1565 &ip_6_6_6_6_o_10_10_10_2,
1566 &ip_6_6_6_6_o_10_10_10_2,
1567 &ip_6_6_6_6_o_10_10_10_2,
1568 &ip_6_6_6_6_o_10_10_10_2,
1569 &ip_6_6_6_6_o_10_10_10_2,
1570 &ip_6_6_6_6_o_10_10_10_2,
1571 &ip_6_6_6_6_o_10_10_10_2,
1572 &ip_6_6_6_6_o_10_10_10_2,
1573 &ip_6_6_6_6_o_10_10_10_2,
1574 &ip_6_6_6_6_o_10_10_10_2,
1575 &ip_6_6_6_6_o_10_10_10_2,
1576 &ip_6_6_6_6_o_10_10_10_2,
1577 &ip_6_6_6_6_o_10_10_10_2,
1578 &ip_6_6_6_6_o_10_10_10_2,
1579 &ip_6_6_6_6_o_10_10_10_2,
1580 &ip_6_6_6_6_o_10_10_10_2,
1581 &ip_6_6_6_6_o_10_10_10_2,
1582 &ip_6_6_6_6_o_10_10_10_2,
1583 &ip_6_6_6_6_o_10_10_10_2,
1584 &ip_6_6_6_6_o_10_10_10_2,
1585 &ip_6_6_6_6_o_10_10_10_2,
1586 &ip_6_6_6_6_o_10_10_10_2,
1587 &ip_6_6_6_6_o_10_10_10_2,
1588 &ip_6_6_6_6_o_10_10_10_2,
1589 &ip_6_6_6_6_o_10_10_10_2,
1590 &ip_6_6_6_6_o_10_10_10_2,
1591 &ip_6_6_6_6_o_10_10_10_2,
1592 &ip_6_6_6_6_o_10_10_10_2,
1593 &ip_6_6_6_6_o_10_10_10_2,
1594 &ip_6_6_6_6_o_10_10_10_2,
1595 &ip_6_6_6_6_o_10_10_10_2,
1596 &ip_6_6_6_6_o_10_10_10_2,
1597 &ip_6_6_6_6_o_10_10_10_2,
1598 &ip_6_6_6_6_o_10_10_10_2,
1599 &ip_6_6_6_6_o_10_10_10_2,
1600 &ip_6_6_6_6_o_10_10_10_2,
1601 &ip_6_6_6_6_o_10_10_10_2,
1602 &ip_6_6_6_6_o_10_10_10_2,
1603 &ip_6_6_6_6_o_10_10_10_2,
1604 &ip_6_6_6_6_o_10_10_10_2,
1605 &ip_6_6_6_6_o_10_10_10_2,
1606 &ip_6_6_6_6_o_10_10_10_2,
1607 &ip_6_6_6_6_o_10_10_10_2,
1608 &ip_6_6_6_6_o_10_10_10_2,
1609 &ip_6_6_6_6_o_10_10_10_2,
1610 &ip_6_6_6_6_o_10_10_10_2,
1611 &ip_6_6_6_6_o_10_10_10_2,
1612 &ip_6_6_6_6_o_10_10_10_2,
1613 &ip_6_6_6_6_o_10_10_10_2,
1614 &ip_6_6_6_6_o_10_10_10_2,
1615 &ip_6_6_6_6_o_10_10_10_2,
1616 &ip_6_6_6_6_o_10_10_10_2,
1617 &ip_6_6_6_6_o_10_10_10_2,
1618 &ip_6_6_6_6_o_10_10_10_2,
1619 &ip_6_6_6_6_o_10_10_10_2,
1620 &ip_6_6_6_6_o_10_10_10_1),
1621 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1622
1623 fib_table_entry_path_add(fib_index,
1624 &pfx_6_6_6_6_s_32,
1625 FIB_SOURCE_API,
1626 FIB_ENTRY_FLAG_NONE,
1627 FIB_PROTOCOL_IP4,
1628 &nh_12_12_12_12,
1629 tm->hw[1]->sw_if_index,
1630 ~0, // invalid fib index
1631 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001632 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001633 FIB_ROUTE_PATH_FLAG_NONE);
1634
1635 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1636 FIB_TEST(fib_test_validate_entry(fei,
1637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1638 128,
1639 &ip_6_6_6_6_o_10_10_10_1,
1640 &ip_6_6_6_6_o_10_10_10_2,
1641 &ip_6_6_6_6_o_10_10_10_2,
1642 &ip_6_6_6_6_o_10_10_10_2,
1643 &ip_6_6_6_6_o_10_10_10_2,
1644 &ip_6_6_6_6_o_10_10_10_2,
1645 &ip_6_6_6_6_o_10_10_10_2,
1646 &ip_6_6_6_6_o_10_10_10_2,
1647 &ip_6_6_6_6_o_10_10_10_2,
1648 &ip_6_6_6_6_o_10_10_10_2,
1649 &ip_6_6_6_6_o_10_10_10_2,
1650 &ip_6_6_6_6_o_10_10_10_2,
1651 &ip_6_6_6_6_o_10_10_10_2,
1652 &ip_6_6_6_6_o_10_10_10_2,
1653 &ip_6_6_6_6_o_10_10_10_2,
1654 &ip_6_6_6_6_o_10_10_10_2,
1655 &ip_6_6_6_6_o_10_10_10_2,
1656 &ip_6_6_6_6_o_10_10_10_2,
1657 &ip_6_6_6_6_o_10_10_10_2,
1658 &ip_6_6_6_6_o_10_10_10_2,
1659 &ip_6_6_6_6_o_10_10_10_2,
1660 &ip_6_6_6_6_o_10_10_10_2,
1661 &ip_6_6_6_6_o_10_10_10_2,
1662 &ip_6_6_6_6_o_10_10_10_2,
1663 &ip_6_6_6_6_o_10_10_10_2,
1664 &ip_6_6_6_6_o_10_10_10_2,
1665 &ip_6_6_6_6_o_10_10_10_2,
1666 &ip_6_6_6_6_o_10_10_10_2,
1667 &ip_6_6_6_6_o_10_10_10_2,
1668 &ip_6_6_6_6_o_10_10_10_2,
1669 &ip_6_6_6_6_o_10_10_10_2,
1670 &ip_6_6_6_6_o_10_10_10_2,
1671 &ip_6_6_6_6_o_10_10_10_2,
1672 &ip_6_6_6_6_o_10_10_10_2,
1673 &ip_6_6_6_6_o_10_10_10_2,
1674 &ip_6_6_6_6_o_10_10_10_2,
1675 &ip_6_6_6_6_o_10_10_10_2,
1676 &ip_6_6_6_6_o_10_10_10_2,
1677 &ip_6_6_6_6_o_10_10_10_2,
1678 &ip_6_6_6_6_o_10_10_10_2,
1679 &ip_6_6_6_6_o_10_10_10_2,
1680 &ip_6_6_6_6_o_10_10_10_2,
1681 &ip_6_6_6_6_o_10_10_10_2,
1682 &ip_6_6_6_6_o_10_10_10_2,
1683 &ip_6_6_6_6_o_10_10_10_2,
1684 &ip_6_6_6_6_o_10_10_10_2,
1685 &ip_6_6_6_6_o_10_10_10_2,
1686 &ip_6_6_6_6_o_10_10_10_2,
1687 &ip_6_6_6_6_o_10_10_10_2,
1688 &ip_6_6_6_6_o_10_10_10_2,
1689 &ip_6_6_6_6_o_10_10_10_2,
1690 &ip_6_6_6_6_o_10_10_10_2,
1691 &ip_6_6_6_6_o_10_10_10_2,
1692 &ip_6_6_6_6_o_10_10_10_2,
1693 &ip_6_6_6_6_o_10_10_10_2,
1694 &ip_6_6_6_6_o_10_10_10_2,
1695 &ip_6_6_6_6_o_10_10_10_2,
1696 &ip_6_6_6_6_o_10_10_10_2,
1697 &ip_6_6_6_6_o_10_10_10_2,
1698 &ip_6_6_6_6_o_10_10_10_2,
1699 &ip_6_6_6_6_o_10_10_10_2,
1700 &ip_6_6_6_6_o_10_10_10_2,
1701 &ip_6_6_6_6_o_10_10_10_2,
1702 &ip_6_6_6_6_o_10_10_10_2,
1703 &ip_6_6_6_6_o_10_10_10_2,
1704 &ip_6_6_6_6_o_12_12_12_12,
1705 &ip_6_6_6_6_o_12_12_12_12,
1706 &ip_6_6_6_6_o_12_12_12_12,
1707 &ip_6_6_6_6_o_12_12_12_12,
1708 &ip_6_6_6_6_o_12_12_12_12,
1709 &ip_6_6_6_6_o_12_12_12_12,
1710 &ip_6_6_6_6_o_12_12_12_12,
1711 &ip_6_6_6_6_o_12_12_12_12,
1712 &ip_6_6_6_6_o_12_12_12_12,
1713 &ip_6_6_6_6_o_12_12_12_12,
1714 &ip_6_6_6_6_o_12_12_12_12,
1715 &ip_6_6_6_6_o_12_12_12_12,
1716 &ip_6_6_6_6_o_12_12_12_12,
1717 &ip_6_6_6_6_o_12_12_12_12,
1718 &ip_6_6_6_6_o_12_12_12_12,
1719 &ip_6_6_6_6_o_12_12_12_12,
1720 &ip_6_6_6_6_o_12_12_12_12,
1721 &ip_6_6_6_6_o_12_12_12_12,
1722 &ip_6_6_6_6_o_12_12_12_12,
1723 &ip_6_6_6_6_o_12_12_12_12,
1724 &ip_6_6_6_6_o_12_12_12_12,
1725 &ip_6_6_6_6_o_12_12_12_12,
1726 &ip_6_6_6_6_o_12_12_12_12,
1727 &ip_6_6_6_6_o_12_12_12_12,
1728 &ip_6_6_6_6_o_12_12_12_12,
1729 &ip_6_6_6_6_o_12_12_12_12,
1730 &ip_6_6_6_6_o_12_12_12_12,
1731 &ip_6_6_6_6_o_12_12_12_12,
1732 &ip_6_6_6_6_o_12_12_12_12,
1733 &ip_6_6_6_6_o_12_12_12_12,
1734 &ip_6_6_6_6_o_12_12_12_12,
1735 &ip_6_6_6_6_o_12_12_12_12,
1736 &ip_6_6_6_6_o_12_12_12_12,
1737 &ip_6_6_6_6_o_12_12_12_12,
1738 &ip_6_6_6_6_o_12_12_12_12,
1739 &ip_6_6_6_6_o_12_12_12_12,
1740 &ip_6_6_6_6_o_12_12_12_12,
1741 &ip_6_6_6_6_o_12_12_12_12,
1742 &ip_6_6_6_6_o_12_12_12_12,
1743 &ip_6_6_6_6_o_12_12_12_12,
1744 &ip_6_6_6_6_o_12_12_12_12,
1745 &ip_6_6_6_6_o_12_12_12_12,
1746 &ip_6_6_6_6_o_12_12_12_12,
1747 &ip_6_6_6_6_o_12_12_12_12,
1748 &ip_6_6_6_6_o_12_12_12_12,
1749 &ip_6_6_6_6_o_12_12_12_12,
1750 &ip_6_6_6_6_o_12_12_12_12,
1751 &ip_6_6_6_6_o_12_12_12_12,
1752 &ip_6_6_6_6_o_12_12_12_12,
1753 &ip_6_6_6_6_o_12_12_12_12,
1754 &ip_6_6_6_6_o_12_12_12_12,
1755 &ip_6_6_6_6_o_12_12_12_12,
1756 &ip_6_6_6_6_o_12_12_12_12,
1757 &ip_6_6_6_6_o_12_12_12_12,
1758 &ip_6_6_6_6_o_12_12_12_12,
1759 &ip_6_6_6_6_o_12_12_12_12,
1760 &ip_6_6_6_6_o_12_12_12_12,
1761 &ip_6_6_6_6_o_12_12_12_12,
1762 &ip_6_6_6_6_o_12_12_12_12,
1763 &ip_6_6_6_6_o_12_12_12_12,
1764 &ip_6_6_6_6_o_12_12_12_12,
1765 &ip_6_6_6_6_o_12_12_12_12,
1766 &ip_6_6_6_6_o_12_12_12_12),
1767 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1768
1769 fib_table_entry_path_remove(fib_index,
1770 &pfx_6_6_6_6_s_32,
1771 FIB_SOURCE_API,
1772 FIB_PROTOCOL_IP4,
1773 &nh_12_12_12_12,
1774 tm->hw[1]->sw_if_index,
1775 ~0, // invalid fib index
1776 100,
1777 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 64,
1783 &ip_6_6_6_6_o_10_10_10_2,
1784 &ip_6_6_6_6_o_10_10_10_2,
1785 &ip_6_6_6_6_o_10_10_10_2,
1786 &ip_6_6_6_6_o_10_10_10_2,
1787 &ip_6_6_6_6_o_10_10_10_2,
1788 &ip_6_6_6_6_o_10_10_10_2,
1789 &ip_6_6_6_6_o_10_10_10_2,
1790 &ip_6_6_6_6_o_10_10_10_2,
1791 &ip_6_6_6_6_o_10_10_10_2,
1792 &ip_6_6_6_6_o_10_10_10_2,
1793 &ip_6_6_6_6_o_10_10_10_2,
1794 &ip_6_6_6_6_o_10_10_10_2,
1795 &ip_6_6_6_6_o_10_10_10_2,
1796 &ip_6_6_6_6_o_10_10_10_2,
1797 &ip_6_6_6_6_o_10_10_10_2,
1798 &ip_6_6_6_6_o_10_10_10_2,
1799 &ip_6_6_6_6_o_10_10_10_2,
1800 &ip_6_6_6_6_o_10_10_10_2,
1801 &ip_6_6_6_6_o_10_10_10_2,
1802 &ip_6_6_6_6_o_10_10_10_2,
1803 &ip_6_6_6_6_o_10_10_10_2,
1804 &ip_6_6_6_6_o_10_10_10_2,
1805 &ip_6_6_6_6_o_10_10_10_2,
1806 &ip_6_6_6_6_o_10_10_10_2,
1807 &ip_6_6_6_6_o_10_10_10_2,
1808 &ip_6_6_6_6_o_10_10_10_2,
1809 &ip_6_6_6_6_o_10_10_10_2,
1810 &ip_6_6_6_6_o_10_10_10_2,
1811 &ip_6_6_6_6_o_10_10_10_2,
1812 &ip_6_6_6_6_o_10_10_10_2,
1813 &ip_6_6_6_6_o_10_10_10_2,
1814 &ip_6_6_6_6_o_10_10_10_2,
1815 &ip_6_6_6_6_o_10_10_10_2,
1816 &ip_6_6_6_6_o_10_10_10_2,
1817 &ip_6_6_6_6_o_10_10_10_2,
1818 &ip_6_6_6_6_o_10_10_10_2,
1819 &ip_6_6_6_6_o_10_10_10_2,
1820 &ip_6_6_6_6_o_10_10_10_2,
1821 &ip_6_6_6_6_o_10_10_10_2,
1822 &ip_6_6_6_6_o_10_10_10_2,
1823 &ip_6_6_6_6_o_10_10_10_2,
1824 &ip_6_6_6_6_o_10_10_10_2,
1825 &ip_6_6_6_6_o_10_10_10_2,
1826 &ip_6_6_6_6_o_10_10_10_2,
1827 &ip_6_6_6_6_o_10_10_10_2,
1828 &ip_6_6_6_6_o_10_10_10_2,
1829 &ip_6_6_6_6_o_10_10_10_2,
1830 &ip_6_6_6_6_o_10_10_10_2,
1831 &ip_6_6_6_6_o_10_10_10_2,
1832 &ip_6_6_6_6_o_10_10_10_2,
1833 &ip_6_6_6_6_o_10_10_10_2,
1834 &ip_6_6_6_6_o_10_10_10_2,
1835 &ip_6_6_6_6_o_10_10_10_2,
1836 &ip_6_6_6_6_o_10_10_10_2,
1837 &ip_6_6_6_6_o_10_10_10_2,
1838 &ip_6_6_6_6_o_10_10_10_2,
1839 &ip_6_6_6_6_o_10_10_10_2,
1840 &ip_6_6_6_6_o_10_10_10_2,
1841 &ip_6_6_6_6_o_10_10_10_2,
1842 &ip_6_6_6_6_o_10_10_10_2,
1843 &ip_6_6_6_6_o_10_10_10_2,
1844 &ip_6_6_6_6_o_10_10_10_2,
1845 &ip_6_6_6_6_o_10_10_10_2,
1846 &ip_6_6_6_6_o_10_10_10_1),
1847 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1848
1849 fib_table_entry_path_remove(fib_index,
1850 &pfx_6_6_6_6_s_32,
1851 FIB_SOURCE_API,
1852 FIB_PROTOCOL_IP4,
1853 &nh_10_10_10_2,
1854 tm->hw[0]->sw_if_index,
1855 ~0, // invalid fib index
1856 100,
1857 FIB_ROUTE_PATH_FLAG_NONE);
1858
1859 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1860 FIB_TEST(fib_test_validate_entry(fei,
1861 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1862 1,
1863 &ip_6_6_6_6_o_10_10_10_1),
1864 "6.6.6.6/32 via 10.10.10.1");
1865
1866 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1867
1868 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001869 * A recursive via the two unequal cost entries
1870 */
1871 fib_prefix_t bgp_44_s_32 = {
1872 .fp_len = 32,
1873 .fp_proto = FIB_PROTOCOL_IP4,
1874 .fp_addr = {
1875 /* 200.200.200.201/32 */
1876 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1877 },
1878 };
1879 fei = fib_table_entry_path_add(fib_index,
1880 &bgp_44_s_32,
1881 FIB_SOURCE_API,
1882 FIB_ENTRY_FLAG_NONE,
1883 FIB_PROTOCOL_IP4,
1884 &pfx_1_2_3_4_s_32.fp_addr,
1885 ~0,
1886 fib_index,
1887 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001888 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001889 FIB_ROUTE_PATH_FLAG_NONE);
1890 fei = fib_table_entry_path_add(fib_index,
1891 &bgp_44_s_32,
1892 FIB_SOURCE_API,
1893 FIB_ENTRY_FLAG_NONE,
1894 FIB_PROTOCOL_IP4,
1895 &pfx_1_2_3_5_s_32.fp_addr,
1896 ~0,
1897 fib_index,
1898 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001899 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001900 FIB_ROUTE_PATH_FLAG_NONE);
1901
1902 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
1903 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
1904 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1905 tm->hw[0]->sw_if_index,
1906 tm->hw[1]->sw_if_index),
1907 "RPF list for 1.2.3.4/32 contains both adjs");
1908
1909 /*
1910 * test the uRPF check functions
1911 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001912 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01001913 index_t urpfi;
1914
1915 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
1916 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
1917
1918 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
1919 "uRPF check for 68.68.68.68/32 on %d OK",
1920 tm->hw[0]->sw_if_index);
1921 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
1922 "uRPF check for 68.68.68.68/32 on %d OK",
1923 tm->hw[1]->sw_if_index);
1924 FIB_TEST(!fib_urpf_check(urpfi, 99),
1925 "uRPF check for 68.68.68.68/32 on 99 not-OK",
1926 99);
1927 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001928
1929 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01001930 &bgp_44_s_32,
1931 FIB_SOURCE_API);
1932 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001933 &pfx_1_2_3_5_s_32,
1934 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01001935 fib_table_entry_delete(fib_index,
1936 &pfx_1_2_3_4_s_32,
1937 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001938
1939 /*
1940 * Add a recursive route:
1941 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
1942 */
1943 fib_prefix_t bgp_201_pfx = {
1944 .fp_len = 32,
1945 .fp_proto = FIB_PROTOCOL_IP4,
1946 .fp_addr = {
1947 /* 200.200.200.201/32 */
1948 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
1949 },
1950 };
1951 /* via 1.1.1.200 */
1952 fib_prefix_t pfx_1_1_1_200_s_32 = {
1953 .fp_len = 32,
1954 .fp_proto = FIB_PROTOCOL_IP4,
1955 .fp_addr = {
1956 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
1957 },
1958 };
1959
1960 fib_table_entry_path_add(fib_index,
1961 &bgp_201_pfx,
1962 FIB_SOURCE_API,
1963 FIB_ENTRY_FLAG_NONE,
1964 FIB_PROTOCOL_IP4,
1965 &pfx_1_1_1_200_s_32.fp_addr,
1966 ~0, // no index provided.
1967 fib_index, // nexthop in same fib as route
1968 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001969 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001970 FIB_ROUTE_PATH_FLAG_NONE);
1971
Neale Ranns3ee44042016-10-03 13:05:48 +01001972 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001973
1974 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
1975 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
1976 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01001977 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1978 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001979
1980 /*
1981 * +2 entry (BGP & RR) and +1 shared-path-list
1982 */
1983 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
1984 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001985 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001986 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001987 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001988 fib_entry_pool_size());
1989
1990 /*
1991 * insert a route that covers the missing 1.1.1.2/32. we epxect
1992 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
1993 */
1994 fib_prefix_t pfx_1_1_1_0_s_24 = {
1995 .fp_len = 24,
1996 .fp_proto = FIB_PROTOCOL_IP4,
1997 .fp_addr = {
1998 /* 1.1.1.0/24 */
1999 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2000 },
2001 };
2002
2003 fib_table_entry_path_add(fib_index,
2004 &pfx_1_1_1_0_s_24,
2005 FIB_SOURCE_API,
2006 FIB_ENTRY_FLAG_NONE,
2007 FIB_PROTOCOL_IP4,
2008 &nh_10_10_10_1,
2009 tm->hw[0]->sw_if_index,
2010 ~0, // invalid fib index
2011 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002012 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002013 FIB_ROUTE_PATH_FLAG_NONE);
2014 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2015 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2016 ai = fib_entry_get_adj(fei);
2017 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2018 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2019 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2020 ai = fib_entry_get_adj(fei);
2021 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2022 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2023 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2024 ai = fib_entry_get_adj(fei);
2025 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2026
2027 /*
2028 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2029 */
2030 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2031 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002032 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002033 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002034 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002035 fib_entry_pool_size());
2036
2037 /*
2038 * the recursive adj for 200.200.200.200 should be updated.
2039 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002040 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2041 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2042 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2043 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2044 tm->hw[0]->sw_if_index),
2045 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002046
2047 /*
2048 * insert a more specific route than 1.1.1.0/24 that also covers the
2049 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2050 * 200.200.200.200 to resolve through it.
2051 */
2052 fib_prefix_t pfx_1_1_1_0_s_28 = {
2053 .fp_len = 28,
2054 .fp_proto = FIB_PROTOCOL_IP4,
2055 .fp_addr = {
2056 /* 1.1.1.0/24 */
2057 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2058 },
2059 };
2060
2061 fib_table_entry_path_add(fib_index,
2062 &pfx_1_1_1_0_s_28,
2063 FIB_SOURCE_API,
2064 FIB_ENTRY_FLAG_NONE,
2065 FIB_PROTOCOL_IP4,
2066 &nh_10_10_10_2,
2067 tm->hw[0]->sw_if_index,
2068 ~0, // invalid fib index
2069 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002070 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002071 FIB_ROUTE_PATH_FLAG_NONE);
2072 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2073 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2074 ai = fib_entry_get_adj(fei);
2075 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2076
2077 /*
2078 * +1 entry. +1 shared path-list
2079 */
2080 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2081 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002082 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002083 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002084 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002085 fib_entry_pool_size());
2086
2087 /*
2088 * the recursive adj for 200.200.200.200 should be updated.
2089 * 200.200.200.201 remains unchanged.
2090 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002091 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2092 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002093
2094 /*
2095 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2096 */
2097 fib_table_entry_path_remove(fib_index,
2098 &pfx_1_1_1_0_s_28,
2099 FIB_SOURCE_API,
2100 FIB_PROTOCOL_IP4,
2101 &nh_10_10_10_2,
2102 tm->hw[0]->sw_if_index,
2103 ~0,
2104 1,
2105 FIB_ROUTE_PATH_FLAG_NONE);
2106 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2107 FIB_NODE_INDEX_INVALID),
2108 "1.1.1.0/28 removed");
2109 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2110 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2111 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002112 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2113 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002114
2115 /*
2116 * -1 entry. -1 shared path-list
2117 */
2118 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2119 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002120 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002121 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002122 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002123 fib_entry_pool_size());
2124
2125 /*
2126 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2127 */
2128 fib_table_entry_path_remove(fib_index,
2129 &pfx_1_1_1_0_s_24,
2130 FIB_SOURCE_API,
2131 FIB_PROTOCOL_IP4,
2132 &nh_10_10_10_1,
2133 tm->hw[0]->sw_if_index,
2134 ~0,
2135 1,
2136 FIB_ROUTE_PATH_FLAG_NONE);
2137 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2138 FIB_NODE_INDEX_INVALID),
2139 "1.1.1.0/24 removed");
2140
2141 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2142 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2143 "1.1.1.2/32 route is DROP");
2144 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2145 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2146 "1.1.1.200/32 route is DROP");
2147
Neale Ranns3ee44042016-10-03 13:05:48 +01002148 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2149 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002150
2151 /*
2152 * -1 entry
2153 */
2154 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2155 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002156 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002157 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002158 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002159 fib_entry_pool_size());
2160
2161 /*
2162 * insert the missing 1.1.1.2/32
2163 */
2164 fei = fib_table_entry_path_add(fib_index,
2165 &pfx_1_1_1_2_s_32,
2166 FIB_SOURCE_API,
2167 FIB_ENTRY_FLAG_NONE,
2168 FIB_PROTOCOL_IP4,
2169 &nh_10_10_10_1,
2170 tm->hw[0]->sw_if_index,
2171 ~0, // invalid fib index
2172 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002173 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002174 FIB_ROUTE_PATH_FLAG_NONE);
2175 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2176 ai = fib_entry_get_adj(fei);
2177 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2178
Neale Ranns3ee44042016-10-03 13:05:48 +01002179 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2180 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002181
2182 /*
2183 * no change. 1.1.1.2/32 was already there RR sourced.
2184 */
2185 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2186 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002187 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002188 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002189 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002190 fib_entry_pool_size());
2191
2192 /*
2193 * remove 200.200.200.201/32 which does not have a valid via FIB
2194 */
2195 fib_table_entry_path_remove(fib_index,
2196 &bgp_201_pfx,
2197 FIB_SOURCE_API,
2198 FIB_PROTOCOL_IP4,
2199 &pfx_1_1_1_200_s_32.fp_addr,
2200 ~0, // no index provided.
2201 fib_index,
2202 1,
2203 FIB_ROUTE_PATH_FLAG_NONE);
2204
2205 /*
2206 * -2 entries (BGP and RR). -1 shared path-list;
2207 */
2208 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2209 FIB_NODE_INDEX_INVALID),
2210 "200.200.200.201/32 removed");
2211 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2212 FIB_NODE_INDEX_INVALID),
2213 "1.1.1.200/32 removed");
2214
2215 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2216 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002217 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002218 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002219 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002220 fib_entry_pool_size());
2221
2222 /*
2223 * remove 200.200.200.200/32 which does have a valid via FIB
2224 */
2225 fib_table_entry_path_remove(fib_index,
2226 &bgp_200_pfx,
2227 FIB_SOURCE_API,
2228 FIB_PROTOCOL_IP4,
2229 &pfx_1_1_1_2_s_32.fp_addr,
2230 ~0, // no index provided.
2231 fib_index,
2232 1,
2233 FIB_ROUTE_PATH_FLAG_NONE);
2234
2235 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2236 FIB_NODE_INDEX_INVALID),
2237 "200.200.200.200/32 removed");
2238 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2239 FIB_NODE_INDEX_INVALID),
2240 "1.1.1.2/32 still present");
2241
2242 /*
2243 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2244 */
2245 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2246 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002247 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002248 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002249 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002250 fib_entry_pool_size());
2251
2252 /*
2253 * A recursive prefix that has a 2 path load-balance.
2254 * It also shares a next-hop with other BGP prefixes and hence
2255 * test the ref counting of RR sourced prefixes and 2 level LB.
2256 */
2257 const fib_prefix_t bgp_102 = {
2258 .fp_len = 32,
2259 .fp_proto = FIB_PROTOCOL_IP4,
2260 .fp_addr = {
2261 /* 100.100.100.101/32 */
2262 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2263 },
2264 };
2265 fib_table_entry_path_add(fib_index,
2266 &bgp_102,
2267 FIB_SOURCE_API,
2268 FIB_ENTRY_FLAG_NONE,
2269 FIB_PROTOCOL_IP4,
2270 &pfx_1_1_1_1_s_32.fp_addr,
2271 ~0, // no index provided.
2272 fib_index, // same as route
2273 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002274 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002275 FIB_ROUTE_PATH_FLAG_NONE);
2276 fib_table_entry_path_add(fib_index,
2277 &bgp_102,
2278 FIB_SOURCE_API,
2279 FIB_ENTRY_FLAG_NONE,
2280 FIB_PROTOCOL_IP4,
2281 &pfx_1_1_1_2_s_32.fp_addr,
2282 ~0, // no index provided.
2283 fib_index, // same as route's FIB
2284 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002285 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002286 FIB_ROUTE_PATH_FLAG_NONE);
2287 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2288 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2289 dpo = fib_entry_contribute_ip_forwarding(fei);
2290
2291 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2292 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2293 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2294 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2295
2296 lb = load_balance_get(dpo->dpoi_index);
2297 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2298 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2299 "First via 10.10.10.1");
2300 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2301 "Second via 10.10.10.1");
2302
2303 fib_table_entry_path_remove(fib_index,
2304 &bgp_102,
2305 FIB_SOURCE_API,
2306 FIB_PROTOCOL_IP4,
2307 &pfx_1_1_1_1_s_32.fp_addr,
2308 ~0, // no index provided.
2309 fib_index, // same as route's FIB
2310 1,
2311 FIB_ROUTE_PATH_FLAG_NONE);
2312 fib_table_entry_path_remove(fib_index,
2313 &bgp_102,
2314 FIB_SOURCE_API,
2315 FIB_PROTOCOL_IP4,
2316 &pfx_1_1_1_2_s_32.fp_addr,
2317 ~0, // no index provided.
2318 fib_index, // same as route's FIB
2319 1,
2320 FIB_ROUTE_PATH_FLAG_NONE);
2321 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2322 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2323
2324 /*
2325 * remove the remaining recursives
2326 */
2327 fib_table_entry_path_remove(fib_index,
2328 &bgp_100_pfx,
2329 FIB_SOURCE_API,
2330 FIB_PROTOCOL_IP4,
2331 &pfx_1_1_1_1_s_32.fp_addr,
2332 ~0, // no index provided.
2333 fib_index, // same as route's FIB
2334 1,
2335 FIB_ROUTE_PATH_FLAG_NONE);
2336 fib_table_entry_path_remove(fib_index,
2337 &bgp_101_pfx,
2338 FIB_SOURCE_API,
2339 FIB_PROTOCOL_IP4,
2340 &pfx_1_1_1_1_s_32.fp_addr,
2341 ~0, // no index provided.
2342 fib_index, // same as route's FIB
2343 1,
2344 FIB_ROUTE_PATH_FLAG_NONE);
2345 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2346 FIB_NODE_INDEX_INVALID),
2347 "100.100.100.100/32 removed");
2348 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2349 FIB_NODE_INDEX_INVALID),
2350 "100.100.100.101/32 removed");
2351
2352 /*
2353 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2354 */
2355 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2356 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002357 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002358 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002359 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002360 fib_entry_pool_size());
2361
2362 /*
2363 * Add a recursive route via a connected cover, using an adj-fib that does exist
2364 */
2365 fib_table_entry_path_add(fib_index,
2366 &bgp_200_pfx,
2367 FIB_SOURCE_API,
2368 FIB_ENTRY_FLAG_NONE,
2369 FIB_PROTOCOL_IP4,
2370 &nh_10_10_10_1,
2371 ~0, // no index provided.
2372 fib_index, // Same as route's FIB
2373 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002374 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002375 FIB_ROUTE_PATH_FLAG_NONE);
2376
2377 /*
2378 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2379 */
2380 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2381 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002382 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002383 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002384 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002385 fib_entry_pool_size());
2386
2387 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2388 dpo = fib_entry_contribute_ip_forwarding(fei);
2389
2390 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2391 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2392
2393 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2394 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2395
2396 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2397 "Flags set on RR via existing attached");
2398
2399 /*
2400 * Add a recursive route via a connected cover, using and adj-fib that does
2401 * not exist
2402 */
2403 ip46_address_t nh_10_10_10_3 = {
2404 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2405 };
2406 fib_prefix_t pfx_10_10_10_3 = {
2407 .fp_len = 32,
2408 .fp_proto = FIB_PROTOCOL_IP4,
2409 .fp_addr = nh_10_10_10_3,
2410 };
2411
2412 fib_table_entry_path_add(fib_index,
2413 &bgp_201_pfx,
2414 FIB_SOURCE_API,
2415 FIB_ENTRY_FLAG_NONE,
2416 FIB_PROTOCOL_IP4,
2417 &nh_10_10_10_3,
2418 ~0, // no index provided.
2419 fib_index,
2420 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002421 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002422 FIB_ROUTE_PATH_FLAG_NONE);
2423
2424 /*
2425 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2426 * one unshared non-recursive via 10.10.10.3
2427 */
2428 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2429 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002430 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002431 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002432 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002433 fib_entry_pool_size());
2434
2435 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002436 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002437 &nh_10_10_10_3,
2438 tm->hw[0]->sw_if_index);
2439
2440 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2441 dpo = fib_entry_contribute_ip_forwarding(fei);
2442 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2443 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2444
2445 ai = fib_entry_get_adj(fei);
2446 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2447 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2448 fib_entry_get_flags(fei)),
2449 "Flags set on RR via non-existing attached");
2450
2451 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2452 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2453
2454 adj_unlock(ai_03);
2455
2456 /*
2457 * remove the recursives
2458 */
2459 fib_table_entry_path_remove(fib_index,
2460 &bgp_200_pfx,
2461 FIB_SOURCE_API,
2462 FIB_PROTOCOL_IP4,
2463 &nh_10_10_10_1,
2464 ~0, // no index provided.
2465 fib_index, // same as route's FIB
2466 1,
2467 FIB_ROUTE_PATH_FLAG_NONE);
2468 fib_table_entry_path_remove(fib_index,
2469 &bgp_201_pfx,
2470 FIB_SOURCE_API,
2471 FIB_PROTOCOL_IP4,
2472 &nh_10_10_10_3,
2473 ~0, // no index provided.
2474 fib_index, // same as route's FIB
2475 1,
2476 FIB_ROUTE_PATH_FLAG_NONE);
2477
2478 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2479 FIB_NODE_INDEX_INVALID),
2480 "200.200.200.201/32 removed");
2481 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2482 FIB_NODE_INDEX_INVALID),
2483 "200.200.200.200/32 removed");
2484 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2485 FIB_NODE_INDEX_INVALID),
2486 "10.10.10.3/32 removed");
2487
2488 /*
2489 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2490 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2491 */
2492 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2493 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002494 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002495 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002496 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002497 fib_entry_pool_size());
2498
2499
2500 /*
2501 * RECURSION LOOPS
2502 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2503 */
2504 fib_prefix_t pfx_5_5_5_5_s_32 = {
2505 .fp_len = 32,
2506 .fp_proto = FIB_PROTOCOL_IP4,
2507 .fp_addr = {
2508 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2509 },
2510 };
2511 fib_prefix_t pfx_5_5_5_6_s_32 = {
2512 .fp_len = 32,
2513 .fp_proto = FIB_PROTOCOL_IP4,
2514 .fp_addr = {
2515 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2516 },
2517 };
2518 fib_prefix_t pfx_5_5_5_7_s_32 = {
2519 .fp_len = 32,
2520 .fp_proto = FIB_PROTOCOL_IP4,
2521 .fp_addr = {
2522 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2523 },
2524 };
2525
2526 fib_table_entry_path_add(fib_index,
2527 &pfx_5_5_5_5_s_32,
2528 FIB_SOURCE_API,
2529 FIB_ENTRY_FLAG_NONE,
2530 FIB_PROTOCOL_IP4,
2531 &pfx_5_5_5_6_s_32.fp_addr,
2532 ~0, // no index provided.
2533 fib_index,
2534 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002535 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002536 FIB_ROUTE_PATH_FLAG_NONE);
2537 fib_table_entry_path_add(fib_index,
2538 &pfx_5_5_5_6_s_32,
2539 FIB_SOURCE_API,
2540 FIB_ENTRY_FLAG_NONE,
2541 FIB_PROTOCOL_IP4,
2542 &pfx_5_5_5_7_s_32.fp_addr,
2543 ~0, // no index provided.
2544 fib_index,
2545 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002546 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002547 FIB_ROUTE_PATH_FLAG_NONE);
2548 fib_table_entry_path_add(fib_index,
2549 &pfx_5_5_5_7_s_32,
2550 FIB_SOURCE_API,
2551 FIB_ENTRY_FLAG_NONE,
2552 FIB_PROTOCOL_IP4,
2553 &pfx_5_5_5_5_s_32.fp_addr,
2554 ~0, // no index provided.
2555 fib_index,
2556 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002557 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002558 FIB_ROUTE_PATH_FLAG_NONE);
2559 /*
2560 * +3 entries, +3 shared path-list
2561 */
2562 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2563 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002564 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002565 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002566 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002567 fib_entry_pool_size());
2568
2569 /*
2570 * All the entries have only looped paths, so they are all drop
2571 */
2572 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2573 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2574 "LB for 5.5.5.7/32 is via adj for DROP");
2575 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2576 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2577 "LB for 5.5.5.5/32 is via adj for DROP");
2578 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2579 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2580 "LB for 5.5.5.6/32 is via adj for DROP");
2581
2582 /*
2583 * provide 5.5.5.6/32 with alternate path.
2584 * this will allow only 5.5.5.6/32 to forward with this path, the others
2585 * are still drop since the loop is still present.
2586 */
2587 fib_table_entry_path_add(fib_index,
2588 &pfx_5_5_5_6_s_32,
2589 FIB_SOURCE_API,
2590 FIB_ENTRY_FLAG_NONE,
2591 FIB_PROTOCOL_IP4,
2592 &nh_10_10_10_1,
2593 tm->hw[0]->sw_if_index,
2594 ~0,
2595 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002596 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002597 FIB_ROUTE_PATH_FLAG_NONE);
2598
2599
2600 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2601 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2602
2603 lb = load_balance_get(dpo1->dpoi_index);
2604 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2605
2606 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2607 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2608 FIB_TEST((ai_01 == dpo2->dpoi_index),
2609 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2610
2611 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2612 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2613 "LB for 5.5.5.7/32 is via adj for DROP");
2614 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2615 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2616 "LB for 5.5.5.5/32 is via adj for DROP");
2617
2618 /*
2619 * remove the alternate path for 5.5.5.6/32
2620 * back to all drop
2621 */
2622 fib_table_entry_path_remove(fib_index,
2623 &pfx_5_5_5_6_s_32,
2624 FIB_SOURCE_API,
2625 FIB_PROTOCOL_IP4,
2626 &nh_10_10_10_1,
2627 tm->hw[0]->sw_if_index,
2628 ~0,
2629 1,
2630 FIB_ROUTE_PATH_FLAG_NONE);
2631
2632 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2633 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2634 "LB for 5.5.5.7/32 is via adj for DROP");
2635 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2636 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2637 "LB for 5.5.5.5/32 is via adj for DROP");
2638 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2639 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2640 "LB for 5.5.5.6/32 is via adj for DROP");
2641
2642 /*
2643 * break the loop by giving 5.5.5.5/32 a new set of paths
2644 * expect all to forward via this new path.
2645 */
2646 fib_table_entry_update_one_path(fib_index,
2647 &pfx_5_5_5_5_s_32,
2648 FIB_SOURCE_API,
2649 FIB_ENTRY_FLAG_NONE,
2650 FIB_PROTOCOL_IP4,
2651 &nh_10_10_10_1,
2652 tm->hw[0]->sw_if_index,
2653 ~0, // invalid fib index
2654 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002655 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002656 FIB_ROUTE_PATH_FLAG_NONE);
2657
2658 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2659 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2660 lb = load_balance_get(dpo1->dpoi_index);
2661 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2662
2663 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2664 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2665 FIB_TEST((ai_01 == dpo2->dpoi_index),
2666 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2667
2668 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2669 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2670
2671 lb = load_balance_get(dpo2->dpoi_index);
2672 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2673 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2674 "5.5.5.5.7 via 5.5.5.5");
2675
2676 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2677 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2678
2679 lb = load_balance_get(dpo1->dpoi_index);
2680 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2681 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2682 "5.5.5.5.6 via 5.5.5.7");
2683
2684 /*
2685 * revert back to the loop. so we can remove the prefixes with
2686 * the loop intact
2687 */
2688 fib_table_entry_update_one_path(fib_index,
2689 &pfx_5_5_5_5_s_32,
2690 FIB_SOURCE_API,
2691 FIB_ENTRY_FLAG_NONE,
2692 FIB_PROTOCOL_IP4,
2693 &pfx_5_5_5_6_s_32.fp_addr,
2694 ~0, // no index provided.
2695 fib_index,
2696 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002697 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002698 FIB_ROUTE_PATH_FLAG_NONE);
2699
2700 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2701 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2702 "LB for 5.5.5.7/32 is via adj for DROP");
2703 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2704 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2705 "LB for 5.5.5.5/32 is via adj for DROP");
2706 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2707 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2708 "LB for 5.5.5.6/32 is via adj for DROP");
2709
2710 /*
2711 * remove all the 5.5.5.x/32 prefixes
2712 */
2713 fib_table_entry_path_remove(fib_index,
2714 &pfx_5_5_5_5_s_32,
2715 FIB_SOURCE_API,
2716 FIB_PROTOCOL_IP4,
2717 &pfx_5_5_5_6_s_32.fp_addr,
2718 ~0, // no index provided.
2719 fib_index, // same as route's FIB
2720 1,
2721 FIB_ROUTE_PATH_FLAG_NONE);
2722 fib_table_entry_path_remove(fib_index,
2723 &pfx_5_5_5_6_s_32,
2724 FIB_SOURCE_API,
2725 FIB_PROTOCOL_IP4,
2726 &pfx_5_5_5_7_s_32.fp_addr,
2727 ~0, // no index provided.
2728 fib_index, // same as route's FIB
2729 1,
2730 FIB_ROUTE_PATH_FLAG_NONE);
2731 fib_table_entry_path_remove(fib_index,
2732 &pfx_5_5_5_7_s_32,
2733 FIB_SOURCE_API,
2734 FIB_PROTOCOL_IP4,
2735 &pfx_5_5_5_5_s_32.fp_addr,
2736 ~0, // no index provided.
2737 fib_index, // same as route's FIB
2738 1,
2739 FIB_ROUTE_PATH_FLAG_NONE);
2740 fib_table_entry_path_remove(fib_index,
2741 &pfx_5_5_5_6_s_32,
2742 FIB_SOURCE_API,
2743 FIB_PROTOCOL_IP4,
2744 &nh_10_10_10_2,
2745 ~0, // no index provided.
2746 fib_index, // same as route's FIB
2747 1,
2748 FIB_ROUTE_PATH_FLAG_NONE);
2749
2750 /*
2751 * -3 entries, -3 shared path-list
2752 */
2753 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2754 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002755 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002756 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002757 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002758 fib_entry_pool_size());
2759
2760 /*
2761 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2762 */
2763 fib_table_entry_path_add(fib_index,
2764 &pfx_5_5_5_6_s_32,
2765 FIB_SOURCE_API,
2766 FIB_ENTRY_FLAG_NONE,
2767 FIB_PROTOCOL_IP4,
2768 &pfx_5_5_5_6_s_32.fp_addr,
2769 ~0, // no index provided.
2770 fib_index,
2771 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002772 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002773 FIB_ROUTE_PATH_FLAG_NONE);
2774 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2775 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2776 "1-level 5.5.5.6/32 loop is via adj for DROP");
2777
2778 fib_table_entry_path_remove(fib_index,
2779 &pfx_5_5_5_6_s_32,
2780 FIB_SOURCE_API,
2781 FIB_PROTOCOL_IP4,
2782 &pfx_5_5_5_6_s_32.fp_addr,
2783 ~0, // no index provided.
2784 fib_index, // same as route's FIB
2785 1,
2786 FIB_ROUTE_PATH_FLAG_NONE);
2787 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2788 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2789 "1-level 5.5.5.6/32 loop is removed");
2790
2791 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002792 * A recursive route whose next-hop is covered by the prefix.
2793 * This would mean the via-fib, which inherits forwarding from its
2794 * cover, thus picks up forwarding from the prfix, which is via the
2795 * via-fib, and we have a loop.
2796 */
2797 fib_prefix_t pfx_23_23_23_0_s_24 = {
2798 .fp_len = 24,
2799 .fp_proto = FIB_PROTOCOL_IP4,
2800 .fp_addr = {
2801 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2802 },
2803 };
2804 fib_prefix_t pfx_23_23_23_23_s_32 = {
2805 .fp_len = 32,
2806 .fp_proto = FIB_PROTOCOL_IP4,
2807 .fp_addr = {
2808 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2809 },
2810 };
2811 fei = fib_table_entry_path_add(fib_index,
2812 &pfx_23_23_23_0_s_24,
2813 FIB_SOURCE_API,
2814 FIB_ENTRY_FLAG_NONE,
2815 FIB_PROTOCOL_IP4,
2816 &pfx_23_23_23_23_s_32.fp_addr,
2817 ~0, // recursive
2818 fib_index,
2819 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002820 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002821 FIB_ROUTE_PATH_FLAG_NONE);
2822 dpo = fib_entry_contribute_ip_forwarding(fei);
2823 FIB_TEST(load_balance_is_drop(dpo),
2824 "23.23.23.0/24 via covered is DROP");
2825 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2826
2827 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002828 * add-remove test. no change.
2829 */
2830 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2831 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002832 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002833 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002834 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002835 fib_entry_pool_size());
2836
2837 /*
2838 * A recursive route with recursion constraints.
2839 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2840 */
2841 fib_table_entry_path_add(fib_index,
2842 &bgp_200_pfx,
2843 FIB_SOURCE_API,
2844 FIB_ENTRY_FLAG_NONE,
2845 FIB_PROTOCOL_IP4,
2846 &nh_1_1_1_1,
2847 ~0,
2848 fib_index,
2849 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002850 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002851 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2852
2853 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2854 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2855
2856 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2857 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2858
2859 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2860 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2861
2862 /*
2863 * save the load-balance. we expect it to be inplace modified
2864 */
2865 lb = load_balance_get(dpo1->dpoi_index);
2866
2867 /*
2868 * add a covering prefix for the via fib that would otherwise serve
2869 * as the resolving route when the host is removed
2870 */
2871 fib_table_entry_path_add(fib_index,
2872 &pfx_1_1_1_0_s_28,
2873 FIB_SOURCE_API,
2874 FIB_ENTRY_FLAG_NONE,
2875 FIB_PROTOCOL_IP4,
2876 &nh_10_10_10_1,
2877 tm->hw[0]->sw_if_index,
2878 ~0, // invalid fib index
2879 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002880 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002881 FIB_ROUTE_PATH_FLAG_NONE);
2882 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
2883 ai = fib_entry_get_adj(fei);
2884 FIB_TEST((ai == ai_01),
2885 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
2886
2887 /*
2888 * remove the host via FIB - expect the BGP prefix to be drop
2889 */
2890 fib_table_entry_path_remove(fib_index,
2891 &pfx_1_1_1_1_s_32,
2892 FIB_SOURCE_API,
2893 FIB_PROTOCOL_IP4,
2894 &nh_10_10_10_1,
2895 tm->hw[0]->sw_if_index,
2896 ~0, // invalid fib index
2897 1,
2898 FIB_ROUTE_PATH_FLAG_NONE);
2899
2900 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2901 "adj for 200.200.200.200/32 is recursive via adj for DROP");
2902
2903 /*
2904 * add the via-entry host reoute back. expect to resolve again
2905 */
2906 fib_table_entry_path_add(fib_index,
2907 &pfx_1_1_1_1_s_32,
2908 FIB_SOURCE_API,
2909 FIB_ENTRY_FLAG_NONE,
2910 FIB_PROTOCOL_IP4,
2911 &nh_10_10_10_1,
2912 tm->hw[0]->sw_if_index,
2913 ~0, // invalid 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 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2918 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2919
2920 /*
2921 * add another path for the recursive. it will then have 2.
2922 */
2923 fib_prefix_t pfx_1_1_1_3_s_32 = {
2924 .fp_len = 32,
2925 .fp_proto = FIB_PROTOCOL_IP4,
2926 .fp_addr = {
2927 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
2928 },
2929 };
2930 fib_table_entry_path_add(fib_index,
2931 &pfx_1_1_1_3_s_32,
2932 FIB_SOURCE_API,
2933 FIB_ENTRY_FLAG_NONE,
2934 FIB_PROTOCOL_IP4,
2935 &nh_10_10_10_2,
2936 tm->hw[0]->sw_if_index,
2937 ~0, // invalid fib index
2938 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002939 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002940 FIB_ROUTE_PATH_FLAG_NONE);
2941
2942 fib_table_entry_path_add(fib_index,
2943 &bgp_200_pfx,
2944 FIB_SOURCE_API,
2945 FIB_ENTRY_FLAG_NONE,
2946 FIB_PROTOCOL_IP4,
2947 &pfx_1_1_1_3_s_32.fp_addr,
2948 ~0,
2949 fib_index,
2950 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002951 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002952 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2953
2954 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2955 dpo = fib_entry_contribute_ip_forwarding(fei);
2956
2957 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2958 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2959 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
2960 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
2961 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
2962 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2963 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
2964 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
2965
2966 /*
2967 * expect the lb-map used by the recursive's load-balance is using both buckets
2968 */
2969 load_balance_map_t *lbm;
2970 index_t lbmi;
2971
2972 lb = load_balance_get(dpo->dpoi_index);
2973 lbmi = lb->lb_map;
2974 load_balance_map_lock(lbmi);
2975 lbm = load_balance_map_get(lbmi);
2976
2977 FIB_TEST(lbm->lbm_buckets[0] == 0,
2978 "LB maps's bucket 0 is %d",
2979 lbm->lbm_buckets[0]);
2980 FIB_TEST(lbm->lbm_buckets[1] == 1,
2981 "LB maps's bucket 1 is %d",
2982 lbm->lbm_buckets[1]);
2983
2984 /*
2985 * withdraw one of the /32 via-entrys.
2986 * that ECMP path will be unresolved and forwarding should continue on the
2987 * other available path. this is an iBGP PIC edge failover.
2988 * Test the forwarding changes without re-fetching the adj from the
2989 * recursive entry. this ensures its the same one that is updated; i.e. an
2990 * inplace-modify.
2991 */
2992 fib_table_entry_path_remove(fib_index,
2993 &pfx_1_1_1_1_s_32,
2994 FIB_SOURCE_API,
2995 FIB_PROTOCOL_IP4,
2996 &nh_10_10_10_1,
2997 tm->hw[0]->sw_if_index,
2998 ~0, // invalid fib index
2999 1,
3000 FIB_ROUTE_PATH_FLAG_NONE);
3001
3002 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3003 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3004 "post PIC 200.200.200.200/32 was inplace modified");
3005
3006 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3007 "post PIC adj for 200.200.200.200/32 is recursive"
3008 " via adj for 1.1.1.3");
3009
3010 /*
3011 * the LB maps that was locked above should have been modified to remove
3012 * the path that was down, and thus its bucket points to a path that is
3013 * still up.
3014 */
3015 FIB_TEST(lbm->lbm_buckets[0] == 1,
3016 "LB maps's bucket 0 is %d",
3017 lbm->lbm_buckets[0]);
3018 FIB_TEST(lbm->lbm_buckets[1] == 1,
3019 "LB maps's bucket 1 is %d",
3020 lbm->lbm_buckets[1]);
3021
3022 load_balance_map_unlock(lb->lb_map);
3023
3024 /*
3025 * add it back. again
3026 */
3027 fib_table_entry_path_add(fib_index,
3028 &pfx_1_1_1_1_s_32,
3029 FIB_SOURCE_API,
3030 FIB_ENTRY_FLAG_NONE,
3031 FIB_PROTOCOL_IP4,
3032 &nh_10_10_10_1,
3033 tm->hw[0]->sw_if_index,
3034 ~0, // invalid fib index
3035 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003036 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003037 FIB_ROUTE_PATH_FLAG_NONE);
3038
3039 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3040 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3041 "via adj for 1.1.1.1");
3042 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3043 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3044 "via adj for 1.1.1.3");
3045
3046 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3047 dpo = fib_entry_contribute_ip_forwarding(fei);
3048 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3049 "post PIC 200.200.200.200/32 was inplace modified");
3050
3051 /*
3052 * add a 3rd path. this makes the LB 16 buckets.
3053 */
3054 fib_table_entry_path_add(fib_index,
3055 &bgp_200_pfx,
3056 FIB_SOURCE_API,
3057 FIB_ENTRY_FLAG_NONE,
3058 FIB_PROTOCOL_IP4,
3059 &pfx_1_1_1_2_s_32.fp_addr,
3060 ~0,
3061 fib_index,
3062 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003063 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003064 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3065
3066 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3067 dpo = fib_entry_contribute_ip_forwarding(fei);
3068 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3069 "200.200.200.200/32 was inplace modified for 3rd path");
3070 FIB_TEST(16 == lb->lb_n_buckets,
3071 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3072
3073 lbmi = lb->lb_map;
3074 load_balance_map_lock(lbmi);
3075 lbm = load_balance_map_get(lbmi);
3076
3077 for (ii = 0; ii < 16; ii++)
3078 {
3079 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3080 "LB Map for 200.200.200.200/32 at %d is %d",
3081 ii, lbm->lbm_buckets[ii]);
3082 }
3083
3084 /*
3085 * trigger PIC by removing the first via-entry
3086 * the first 6 buckets of the map should map to the next 6
3087 */
3088 fib_table_entry_path_remove(fib_index,
3089 &pfx_1_1_1_1_s_32,
3090 FIB_SOURCE_API,
3091 FIB_PROTOCOL_IP4,
3092 &nh_10_10_10_1,
3093 tm->hw[0]->sw_if_index,
3094 ~0,
3095 1,
3096 FIB_ROUTE_PATH_FLAG_NONE);
3097
3098 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3099 dpo = fib_entry_contribute_ip_forwarding(fei);
3100 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3101 "200.200.200.200/32 was inplace modified for 3rd path");
3102 FIB_TEST(2 == lb->lb_n_buckets,
3103 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3104
3105 for (ii = 0; ii < 6; ii++)
3106 {
3107 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3108 "LB Map for 200.200.200.200/32 at %d is %d",
3109 ii, lbm->lbm_buckets[ii]);
3110 }
3111 for (ii = 6; ii < 16; ii++)
3112 {
3113 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3114 "LB Map for 200.200.200.200/32 at %d is %d",
3115 ii, lbm->lbm_buckets[ii]);
3116 }
3117
3118
3119 /*
3120 * tidy up
3121 */
3122 fib_table_entry_path_add(fib_index,
3123 &pfx_1_1_1_1_s_32,
3124 FIB_SOURCE_API,
3125 FIB_ENTRY_FLAG_NONE,
3126 FIB_PROTOCOL_IP4,
3127 &nh_10_10_10_1,
3128 tm->hw[0]->sw_if_index,
3129 ~0,
3130 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003131 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003132 FIB_ROUTE_PATH_FLAG_NONE);
3133
3134 fib_table_entry_path_remove(fib_index,
3135 &bgp_200_pfx,
3136 FIB_SOURCE_API,
3137 FIB_PROTOCOL_IP4,
3138 &pfx_1_1_1_2_s_32.fp_addr,
3139 ~0,
3140 fib_index,
3141 1,
3142 MPLS_LABEL_INVALID);
3143 fib_table_entry_path_remove(fib_index,
3144 &bgp_200_pfx,
3145 FIB_SOURCE_API,
3146 FIB_PROTOCOL_IP4,
3147 &nh_1_1_1_1,
3148 ~0,
3149 fib_index,
3150 1,
3151 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3152 fib_table_entry_path_remove(fib_index,
3153 &bgp_200_pfx,
3154 FIB_SOURCE_API,
3155 FIB_PROTOCOL_IP4,
3156 &pfx_1_1_1_3_s_32.fp_addr,
3157 ~0,
3158 fib_index,
3159 1,
3160 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3161 fib_table_entry_delete(fib_index,
3162 &pfx_1_1_1_3_s_32,
3163 FIB_SOURCE_API);
3164 fib_table_entry_delete(fib_index,
3165 &pfx_1_1_1_0_s_28,
3166 FIB_SOURCE_API);
3167 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3168 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3169 "1.1.1.1/28 removed");
3170 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3171 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3172 "1.1.1.3/32 removed");
3173 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3174 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3175 "200.200.200.200/32 removed");
3176
3177 /*
3178 * add-remove test. no change.
3179 */
3180 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3181 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003182 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003183 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003184 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003185 fib_entry_pool_size());
3186
3187 /*
3188 * A route whose paths are built up iteratively and then removed
3189 * all at once
3190 */
3191 fib_prefix_t pfx_4_4_4_4_s_32 = {
3192 .fp_len = 32,
3193 .fp_proto = FIB_PROTOCOL_IP4,
3194 .fp_addr = {
3195 /* 4.4.4.4/32 */
3196 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3197 },
3198 };
3199
3200 fib_table_entry_path_add(fib_index,
3201 &pfx_4_4_4_4_s_32,
3202 FIB_SOURCE_API,
3203 FIB_ENTRY_FLAG_NONE,
3204 FIB_PROTOCOL_IP4,
3205 &nh_10_10_10_1,
3206 tm->hw[0]->sw_if_index,
3207 ~0,
3208 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003209 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003210 FIB_ROUTE_PATH_FLAG_NONE);
3211 fib_table_entry_path_add(fib_index,
3212 &pfx_4_4_4_4_s_32,
3213 FIB_SOURCE_API,
3214 FIB_ENTRY_FLAG_NONE,
3215 FIB_PROTOCOL_IP4,
3216 &nh_10_10_10_2,
3217 tm->hw[0]->sw_if_index,
3218 ~0,
3219 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003220 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003221 FIB_ROUTE_PATH_FLAG_NONE);
3222 fib_table_entry_path_add(fib_index,
3223 &pfx_4_4_4_4_s_32,
3224 FIB_SOURCE_API,
3225 FIB_ENTRY_FLAG_NONE,
3226 FIB_PROTOCOL_IP4,
3227 &nh_10_10_10_3,
3228 tm->hw[0]->sw_if_index,
3229 ~0,
3230 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003231 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003232 FIB_ROUTE_PATH_FLAG_NONE);
3233 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3234 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3235 "4.4.4.4/32 present");
3236
3237 fib_table_entry_delete(fib_index,
3238 &pfx_4_4_4_4_s_32,
3239 FIB_SOURCE_API);
3240 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3241 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3242 "4.4.4.4/32 removed");
3243
3244 /*
3245 * add-remove test. no change.
3246 */
3247 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3248 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003249 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003250 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003251 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003252 fib_entry_pool_size());
3253
3254 /*
3255 * A route with multiple paths at once
3256 */
3257 fib_route_path_t *r_paths = NULL;
3258
3259 for (ii = 0; ii < 4; ii++)
3260 {
3261 fib_route_path_t r_path = {
3262 .frp_proto = FIB_PROTOCOL_IP4,
3263 .frp_addr = {
3264 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3265 },
3266 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3267 .frp_weight = 1,
3268 .frp_fib_index = ~0,
3269 };
3270 vec_add1(r_paths, r_path);
3271 }
3272
3273 fib_table_entry_update(fib_index,
3274 &pfx_4_4_4_4_s_32,
3275 FIB_SOURCE_API,
3276 FIB_ENTRY_FLAG_NONE,
3277 r_paths);
3278
3279 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3280 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3281 dpo = fib_entry_contribute_ip_forwarding(fei);
3282
3283 lb = load_balance_get(dpo->dpoi_index);
3284 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3285
3286 fib_table_entry_delete(fib_index,
3287 &pfx_4_4_4_4_s_32,
3288 FIB_SOURCE_API);
3289 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3290 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3291 "4.4.4.4/32 removed");
3292 vec_free(r_paths);
3293
3294 /*
3295 * add-remove test. no change.
3296 */
3297 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3298 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003299 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003300 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003301 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003302 fib_entry_pool_size());
3303
3304 /*
3305 * A route deag route
3306 */
3307 fib_table_entry_path_add(fib_index,
3308 &pfx_4_4_4_4_s_32,
3309 FIB_SOURCE_API,
3310 FIB_ENTRY_FLAG_NONE,
3311 FIB_PROTOCOL_IP4,
3312 &zero_addr,
3313 ~0,
3314 fib_index,
3315 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003316 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003317 FIB_ROUTE_PATH_FLAG_NONE);
3318
3319 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3320 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3321
3322 dpo = fib_entry_contribute_ip_forwarding(fei);
3323 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3324 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3325
3326 FIB_TEST((fib_index == lkd->lkd_fib_index),
3327 "4.4.4.4/32 is deag in %d %U",
3328 lkd->lkd_fib_index,
3329 format_dpo_id, dpo, 0);
3330
3331 fib_table_entry_delete(fib_index,
3332 &pfx_4_4_4_4_s_32,
3333 FIB_SOURCE_API);
3334 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3335 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3336 "4.4.4.4/32 removed");
3337 vec_free(r_paths);
3338
3339 /*
3340 * add-remove test. no change.
3341 */
3342 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3343 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003344 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003345 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003346 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003347 fib_entry_pool_size());
3348
3349 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003350 * Duplicate paths:
3351 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3352 */
3353 fib_prefix_t pfx_34_1_1_1_s_32 = {
3354 .fp_len = 32,
3355 .fp_proto = FIB_PROTOCOL_IP4,
3356 .fp_addr = {
3357 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3358 },
3359 };
3360 fib_prefix_t pfx_34_34_1_1_s_32 = {
3361 .fp_len = 32,
3362 .fp_proto = FIB_PROTOCOL_IP4,
3363 .fp_addr = {
3364 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3365 },
3366 };
3367 fei = fib_table_entry_path_add(fib_index,
3368 &pfx_34_1_1_1_s_32,
3369 FIB_SOURCE_API,
3370 FIB_ENTRY_FLAG_NONE,
3371 FIB_PROTOCOL_IP4,
3372 &pfx_34_34_1_1_s_32.fp_addr,
3373 ~0,
3374 fib_index,
3375 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003376 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003377 FIB_ROUTE_PATH_FLAG_NONE);
3378 fei = fib_table_entry_path_add(fib_index,
3379 &pfx_34_1_1_1_s_32,
3380 FIB_SOURCE_API,
3381 FIB_ENTRY_FLAG_NONE,
3382 FIB_PROTOCOL_IP4,
3383 &pfx_34_34_1_1_s_32.fp_addr,
3384 ~0,
3385 fib_index,
3386 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003387 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003388 FIB_ROUTE_PATH_FLAG_NONE);
3389 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3390 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
3391
3392 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003393 * CLEANUP
3394 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3395 * all of which are via 10.10.10.1, Itf1
3396 */
3397 fib_table_entry_path_remove(fib_index,
3398 &pfx_1_1_1_2_s_32,
3399 FIB_SOURCE_API,
3400 FIB_PROTOCOL_IP4,
3401 &nh_10_10_10_1,
3402 tm->hw[0]->sw_if_index,
3403 ~0,
3404 1,
3405 FIB_ROUTE_PATH_FLAG_NONE);
3406 fib_table_entry_path_remove(fib_index,
3407 &pfx_1_1_1_1_s_32,
3408 FIB_SOURCE_API,
3409 FIB_PROTOCOL_IP4,
3410 &nh_10_10_10_1,
3411 tm->hw[0]->sw_if_index,
3412 ~0,
3413 1,
3414 FIB_ROUTE_PATH_FLAG_NONE);
3415 fib_table_entry_path_remove(fib_index,
3416 &pfx_1_1_2_0_s_24,
3417 FIB_SOURCE_API,
3418 FIB_PROTOCOL_IP4,
3419 &nh_10_10_10_1,
3420 tm->hw[0]->sw_if_index,
3421 ~0,
3422 1,
3423 FIB_ROUTE_PATH_FLAG_NONE);
3424
3425 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3426 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3427 "1.1.1.1/32 removed");
3428 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3429 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3430 "1.1.1.2/32 removed");
3431 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3432 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3433 "1.1.2.0/24 removed");
3434
3435 /*
3436 * -3 entries and -1 shared path-list
3437 */
3438 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3439 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003440 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003441 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003442 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003443 fib_entry_pool_size());
3444
3445 /*
3446 * An attached-host route. Expect to link to the incomplete adj
3447 */
3448 fib_prefix_t pfx_4_1_1_1_s_32 = {
3449 .fp_len = 32,
3450 .fp_proto = FIB_PROTOCOL_IP4,
3451 .fp_addr = {
3452 /* 4.1.1.1/32 */
3453 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3454 },
3455 };
3456 fib_table_entry_path_add(fib_index,
3457 &pfx_4_1_1_1_s_32,
3458 FIB_SOURCE_API,
3459 FIB_ENTRY_FLAG_NONE,
3460 FIB_PROTOCOL_IP4,
3461 &zero_addr,
3462 tm->hw[0]->sw_if_index,
3463 fib_index,
3464 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003465 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003466 FIB_ROUTE_PATH_FLAG_NONE);
3467
3468 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3469 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3470 ai = fib_entry_get_adj(fei);
3471
3472 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003473 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003474 &pfx_4_1_1_1_s_32.fp_addr,
3475 tm->hw[0]->sw_if_index);
3476 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3477 adj_unlock(ai2);
3478
3479 /*
3480 * +1 entry and +1 shared path-list
3481 */
3482 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3483 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003484 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003485 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003486 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003487 fib_entry_pool_size());
3488
3489 fib_table_entry_delete(fib_index,
3490 &pfx_4_1_1_1_s_32,
3491 FIB_SOURCE_API);
3492
3493 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3494 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003495 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003496 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003497 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003498 fib_entry_pool_size());
3499
3500 /*
3501 * add a v6 prefix via v4 next-hops
3502 */
3503 fib_prefix_t pfx_2001_s_64 = {
3504 .fp_len = 64,
3505 .fp_proto = FIB_PROTOCOL_IP6,
3506 .fp_addr = {
3507 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3508 },
3509 };
3510 fei = fib_table_entry_path_add(0, //default v6 table
3511 &pfx_2001_s_64,
3512 FIB_SOURCE_API,
3513 FIB_ENTRY_FLAG_NONE,
3514 FIB_PROTOCOL_IP4,
3515 &nh_10_10_10_1,
3516 tm->hw[0]->sw_if_index,
3517 fib_index,
3518 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003519 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003520 FIB_ROUTE_PATH_FLAG_NONE);
3521
3522 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3523 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3524 ai = fib_entry_get_adj(fei);
3525 adj = adj_get(ai);
3526 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3527 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003528 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003529 "2001::/64 is link type v6");
3530 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3531 "2001::/64 ADJ-adj is NH proto v4");
3532 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3533
Neale Ranns3ee44042016-10-03 13:05:48 +01003534 /*
3535 * add a uRPF exempt prefix:
3536 * test:
3537 * - it's forwarding is drop
3538 * - it's uRPF list is not empty
3539 * - the uRPF list for the default route (it's cover) is empty
3540 */
3541 fei = fib_table_entry_special_add(fib_index,
3542 &pfx_4_1_1_1_s_32,
3543 FIB_SOURCE_URPF_EXEMPT,
3544 FIB_ENTRY_FLAG_DROP,
3545 ADJ_INDEX_INVALID);
3546 dpo = fib_entry_contribute_ip_forwarding(fei);
3547 FIB_TEST(load_balance_is_drop(dpo),
3548 "uRPF exempt 4.1.1.1/32 DROP");
3549 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3550 "uRPF list for exempt prefix has itf index 0");
3551 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3552 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3553 "uRPF list for 0.0.0.0/0 empty");
3554
3555 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003556
3557 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003558 * An adj-fib that fails the refinement criteria - no connected cover
3559 */
3560 fib_prefix_t pfx_12_10_10_2_s_32 = {
3561 .fp_len = 32,
3562 .fp_proto = FIB_PROTOCOL_IP4,
3563 .fp_addr = {
3564 /* 12.10.10.2 */
3565 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3566 },
3567 };
3568
3569 fib_table_entry_update_one_path(fib_index,
3570 &pfx_12_10_10_2_s_32,
3571 FIB_SOURCE_ADJ,
3572 FIB_ENTRY_FLAG_ATTACHED,
3573 FIB_PROTOCOL_IP4,
3574 &pfx_12_10_10_2_s_32.fp_addr,
3575 tm->hw[0]->sw_if_index,
3576 ~0, // invalid fib index
3577 1,
3578 NULL,
3579 FIB_ROUTE_PATH_FLAG_NONE);
3580
3581 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3582 dpo = fib_entry_contribute_ip_forwarding(fei);
3583 FIB_TEST(!dpo_id_is_valid(dpo),
3584 "no connected cover adj-fib fails refinement");
3585
3586 fib_table_entry_delete(fib_index,
3587 &pfx_12_10_10_2_s_32,
3588 FIB_SOURCE_ADJ);
3589
3590 /*
3591 * An adj-fib that fails the refinement criteria - cover is connected
3592 * but on a different interface
3593 */
3594 fib_prefix_t pfx_10_10_10_127_s_32 = {
3595 .fp_len = 32,
3596 .fp_proto = FIB_PROTOCOL_IP4,
3597 .fp_addr = {
3598 /* 10.10.10.127 */
3599 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3600 },
3601 };
3602
3603 fib_table_entry_update_one_path(fib_index,
3604 &pfx_10_10_10_127_s_32,
3605 FIB_SOURCE_ADJ,
3606 FIB_ENTRY_FLAG_ATTACHED,
3607 FIB_PROTOCOL_IP4,
3608 &pfx_10_10_10_127_s_32.fp_addr,
3609 tm->hw[1]->sw_if_index,
3610 ~0, // invalid fib index
3611 1,
3612 NULL,
3613 FIB_ROUTE_PATH_FLAG_NONE);
3614
3615 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3616 dpo = fib_entry_contribute_ip_forwarding(fei);
3617 FIB_TEST(!dpo_id_is_valid(dpo),
3618 "wrong interface adj-fib fails refinement");
3619
3620 fib_table_entry_delete(fib_index,
3621 &pfx_10_10_10_127_s_32,
3622 FIB_SOURCE_ADJ);
3623
3624 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003625 * CLEANUP
3626 * remove adj-fibs:
3627 */
3628 fib_table_entry_delete(fib_index,
3629 &pfx_10_10_10_1_s_32,
3630 FIB_SOURCE_ADJ);
3631 fib_table_entry_delete(fib_index,
3632 &pfx_10_10_10_2_s_32,
3633 FIB_SOURCE_ADJ);
3634 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3635 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
3636 "10.10.10.1/32 adj-fib removed");
3637 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3638 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
3639 "10.10.10.2/32 adj-fib removed");
3640
3641 /*
3642 * -2 entries and -2 non-shared path-list
3643 */
3644 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3645 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003646 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003647 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003648 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003649 fib_entry_pool_size());
3650
3651 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01003652 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003653 * These are the last locks on these adjs. they should thus go away.
3654 */
3655 adj_unlock(ai_02);
3656 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01003657 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003658
3659 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3660 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00003661
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003662 /*
3663 * CLEANUP
3664 * remove the interface prefixes
3665 */
3666 local_pfx.fp_len = 32;
3667 fib_table_entry_special_remove(fib_index, &local_pfx,
3668 FIB_SOURCE_INTERFACE);
3669 fei = fib_table_lookup(fib_index, &local_pfx);
3670
3671 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3672 fib_table_lookup_exact_match(fib_index, &local_pfx),
3673 "10.10.10.10/32 adj-fib removed");
3674
3675 local_pfx.fp_len = 24;
3676 fib_table_entry_delete(fib_index, &local_pfx,
3677 FIB_SOURCE_INTERFACE);
3678
3679 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3680 fib_table_lookup_exact_match(fib_index, &local_pfx),
3681 "10.10.10.10/24 adj-fib removed");
3682
3683 /*
3684 * -2 entries and -2 non-shared path-list
3685 */
3686 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3687 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003688 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003689 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003690 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003691 fib_entry_pool_size());
3692
3693 /*
3694 * Last but not least, remove the VRF
3695 */
3696 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3697 FIB_PROTOCOL_IP4,
3698 FIB_SOURCE_API)),
3699 "NO API Source'd prefixes");
3700 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3701 FIB_PROTOCOL_IP4,
3702 FIB_SOURCE_RR)),
3703 "NO RR Source'd prefixes");
3704 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
3705 FIB_PROTOCOL_IP4,
3706 FIB_SOURCE_INTERFACE)),
3707 "NO INterface Source'd prefixes");
3708
3709 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
3710
3711 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3712 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003713 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003714 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003715 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003716 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003717 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01003718 pool_elts(fib_urpf_list_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003719
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003720 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003721}
3722
Neale Ranns0ebe8d72016-12-08 19:48:11 +00003723static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003724fib_test_v6 (void)
3725{
3726 /*
3727 * In the default table check for the presence and correct forwarding
3728 * of the special entries
3729 */
3730 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
3731 const dpo_id_t *dpo, *dpo_drop;
3732 const ip_adjacency_t *adj;
3733 const receive_dpo_t *rd;
3734 test_main_t *tm;
3735 u32 fib_index;
3736 int ii;
3737
3738 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
3739 adj_nbr_db_size());
3740
3741 /* via 2001:0:0:1::2 */
3742 ip46_address_t nh_2001_2 = {
3743 .ip6 = {
3744 .as_u64 = {
3745 [0] = clib_host_to_net_u64(0x2001000000000001),
3746 [1] = clib_host_to_net_u64(0x0000000000000002),
3747 },
3748 },
3749 };
3750
3751 tm = &test_main;
3752
3753 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
3754
3755 /* Find or create FIB table 11 */
3756 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
3757
3758 for (ii = 0; ii < 4; ii++)
3759 {
3760 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
3761 }
3762
3763 fib_prefix_t pfx_0_0 = {
3764 .fp_len = 0,
3765 .fp_proto = FIB_PROTOCOL_IP6,
3766 .fp_addr = {
3767 .ip6 = {
3768 {0, 0},
3769 },
3770 },
3771 };
3772
3773 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
3774 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
3775 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3776 "Default route is DROP");
3777
3778 dpo = fib_entry_contribute_ip_forwarding(dfrt);
3779 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3780 &ip6_main,
3781 1,
3782 &pfx_0_0.fp_addr.ip6)),
3783 "default-route; fwd and non-fwd tables match");
3784
3785 // FIXME - check specials.
3786
3787 /*
3788 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00003789 * each with 2 entries and a v6 mfib with 4 path-lists.
3790 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003791 */
Neale Ranns32e1c012016-11-22 17:07:28 +00003792#define ENPS (5+4)
3793#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003794 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00003795 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003796 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003797 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003798 fib_entry_pool_size());
3799
3800 /*
3801 * add interface routes.
3802 * validate presence of /64 attached and /128 recieve.
3803 * test for the presence of the receive address in the glean and local adj
3804 *
3805 * receive on 2001:0:0:1::1/128
3806 */
3807 fib_prefix_t local_pfx = {
3808 .fp_len = 64,
3809 .fp_proto = FIB_PROTOCOL_IP6,
3810 .fp_addr = {
3811 .ip6 = {
3812 .as_u64 = {
3813 [0] = clib_host_to_net_u64(0x2001000000000001),
3814 [1] = clib_host_to_net_u64(0x0000000000000001),
3815 },
3816 },
3817 }
3818 };
3819
3820 fib_table_entry_update_one_path(fib_index, &local_pfx,
3821 FIB_SOURCE_INTERFACE,
3822 (FIB_ENTRY_FLAG_CONNECTED |
3823 FIB_ENTRY_FLAG_ATTACHED),
3824 FIB_PROTOCOL_IP6,
3825 NULL,
3826 tm->hw[0]->sw_if_index,
3827 ~0,
3828 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003829 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003830 FIB_ROUTE_PATH_FLAG_NONE);
3831 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
3832
3833 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
3834
3835 ai = fib_entry_get_adj(fei);
3836 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
3837 adj = adj_get(ai);
3838 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
3839 "attached interface adj is glean");
3840 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3841 &adj->sub_type.glean.receive_addr)),
3842 "attached interface adj is receive ok");
3843 dpo = fib_entry_contribute_ip_forwarding(fei);
3844 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3845 &ip6_main,
3846 1,
3847 &local_pfx.fp_addr.ip6)),
3848 "attached-route; fwd and non-fwd tables match");
3849
3850 local_pfx.fp_len = 128;
3851 fib_table_entry_update_one_path(fib_index, &local_pfx,
3852 FIB_SOURCE_INTERFACE,
3853 (FIB_ENTRY_FLAG_CONNECTED |
3854 FIB_ENTRY_FLAG_LOCAL),
3855 FIB_PROTOCOL_IP6,
3856 NULL,
3857 tm->hw[0]->sw_if_index,
3858 ~0, // invalid fib index
3859 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003860 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003861 FIB_ROUTE_PATH_FLAG_NONE);
3862 fei = fib_table_lookup(fib_index, &local_pfx);
3863
3864 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
3865
3866 dpo = fib_entry_contribute_ip_forwarding(fei);
3867 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3868 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
3869 "local interface adj is local");
3870 rd = receive_dpo_get(dpo->dpoi_index);
3871
3872 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
3873 &rd->rd_addr)),
3874 "local interface adj is receive ok");
3875
3876 dpo = fib_entry_contribute_ip_forwarding(fei);
3877 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
3878 &ip6_main,
3879 1,
3880 &local_pfx.fp_addr.ip6)),
3881 "local-route; fwd and non-fwd tables match");
3882
3883 /*
3884 * +2 entries. +2 unshared path-lists
3885 */
3886 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00003887 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003888 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003889 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003890 fib_entry_pool_size());
3891
3892 /*
3893 * Modify the default route to be via an adj not yet known.
3894 * this sources the defalut route with the API source, which is
3895 * a higher preference to the DEFAULT_ROUTE source
3896 */
3897 fib_table_entry_path_add(fib_index, &pfx_0_0,
3898 FIB_SOURCE_API,
3899 FIB_ENTRY_FLAG_NONE,
3900 FIB_PROTOCOL_IP6,
3901 &nh_2001_2,
3902 tm->hw[0]->sw_if_index,
3903 ~0,
3904 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003905 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003906 FIB_ROUTE_PATH_FLAG_NONE);
3907 fei = fib_table_lookup(fib_index, &pfx_0_0);
3908
3909 FIB_TEST((fei == dfrt), "default route same index");
3910 ai = fib_entry_get_adj(fei);
3911 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
3912 adj = adj_get(ai);
3913 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
3914 "adj is incomplete");
3915 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
3916 "adj nbr next-hop ok");
3917
3918 /*
3919 * find the adj in the shared db
3920 */
3921 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003922 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003923 &nh_2001_2,
3924 tm->hw[0]->sw_if_index);
3925 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
3926 adj_unlock(locked_ai);
3927
3928 /*
3929 * no more entires. +1 shared path-list
3930 */
3931 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3932 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003933 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003934 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003935 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003936 fib_entry_pool_size());
3937
3938 /*
3939 * remove the API source from the default route. We expected
3940 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
3941 */
3942 fib_table_entry_path_remove(fib_index, &pfx_0_0,
3943 FIB_SOURCE_API,
3944 FIB_PROTOCOL_IP6,
3945 &nh_2001_2,
3946 tm->hw[0]->sw_if_index,
3947 ~0,
3948 1,
3949 FIB_ROUTE_PATH_FLAG_NONE);
3950 fei = fib_table_lookup(fib_index, &pfx_0_0);
3951
3952 FIB_TEST((fei == dfrt), "default route same index");
3953 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
3954 "Default route is DROP");
3955
3956 /*
3957 * no more entires. -1 shared path-list
3958 */
3959 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3960 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003961 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003962 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003963 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003964 fib_entry_pool_size());
3965
3966 /*
3967 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
3968 */
3969 fib_prefix_t pfx_2001_1_2_s_128 = {
3970 .fp_len = 128,
3971 .fp_proto = FIB_PROTOCOL_IP6,
3972 .fp_addr = {
3973 .ip6 = {
3974 .as_u64 = {
3975 [0] = clib_host_to_net_u64(0x2001000000000001),
3976 [1] = clib_host_to_net_u64(0x0000000000000002),
3977 },
3978 },
3979 }
3980 };
3981 fib_prefix_t pfx_2001_1_3_s_128 = {
3982 .fp_len = 128,
3983 .fp_proto = FIB_PROTOCOL_IP6,
3984 .fp_addr = {
3985 .ip6 = {
3986 .as_u64 = {
3987 [0] = clib_host_to_net_u64(0x2001000000000001),
3988 [1] = clib_host_to_net_u64(0x0000000000000003),
3989 },
3990 },
3991 }
3992 };
3993 u8 eth_addr[] = {
3994 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
3995 };
3996
3997 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01003998 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003999 &pfx_2001_1_2_s_128.fp_addr,
4000 tm->hw[0]->sw_if_index);
4001 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4002 adj = adj_get(ai_01);
4003 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4004 "adj is incomplete");
4005 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4006 &adj->sub_type.nbr.next_hop)),
4007 "adj nbr next-hop ok");
4008
Neale Rannsb80c5362016-10-08 13:03:40 +01004009 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4010 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004011 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4012 "adj is complete");
4013 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4014 &adj->sub_type.nbr.next_hop)),
4015 "adj nbr next-hop ok");
4016
4017 fib_table_entry_update_one_path(fib_index,
4018 &pfx_2001_1_2_s_128,
4019 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004020 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004021 FIB_PROTOCOL_IP6,
4022 &pfx_2001_1_2_s_128.fp_addr,
4023 tm->hw[0]->sw_if_index,
4024 ~0,
4025 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004026 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004027 FIB_ROUTE_PATH_FLAG_NONE);
4028
4029 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4030 ai = fib_entry_get_adj(fei);
4031 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4032
4033 eth_addr[5] = 0xb2;
4034
4035 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004036 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004037 &pfx_2001_1_3_s_128.fp_addr,
4038 tm->hw[0]->sw_if_index);
4039 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4040 adj = adj_get(ai_02);
4041 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4042 "adj is incomplete");
4043 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4044 &adj->sub_type.nbr.next_hop)),
4045 "adj nbr next-hop ok");
4046
Neale Rannsb80c5362016-10-08 13:03:40 +01004047 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4048 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004049 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4050 "adj is complete");
4051 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4052 &adj->sub_type.nbr.next_hop)),
4053 "adj nbr next-hop ok");
4054 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4055
4056 fib_table_entry_update_one_path(fib_index,
4057 &pfx_2001_1_3_s_128,
4058 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004059 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004060 FIB_PROTOCOL_IP6,
4061 &pfx_2001_1_3_s_128.fp_addr,
4062 tm->hw[0]->sw_if_index,
4063 ~0,
4064 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004065 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004066 FIB_ROUTE_PATH_FLAG_NONE);
4067
4068 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4069 ai = fib_entry_get_adj(fei);
4070 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4071
4072 /*
4073 * +2 entries, +2 unshread path-lists.
4074 */
4075 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4076 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004077 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004078 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004079 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004080 fib_entry_pool_size());
4081
4082 /*
4083 * Add a 2 routes via the first ADJ. ensure path-list sharing
4084 */
4085 fib_prefix_t pfx_2001_a_s_64 = {
4086 .fp_len = 64,
4087 .fp_proto = FIB_PROTOCOL_IP6,
4088 .fp_addr = {
4089 .ip6 = {
4090 .as_u64 = {
4091 [0] = clib_host_to_net_u64(0x200100000000000a),
4092 [1] = clib_host_to_net_u64(0x0000000000000000),
4093 },
4094 },
4095 }
4096 };
4097 fib_prefix_t pfx_2001_b_s_64 = {
4098 .fp_len = 64,
4099 .fp_proto = FIB_PROTOCOL_IP6,
4100 .fp_addr = {
4101 .ip6 = {
4102 .as_u64 = {
4103 [0] = clib_host_to_net_u64(0x200100000000000b),
4104 [1] = clib_host_to_net_u64(0x0000000000000000),
4105 },
4106 },
4107 }
4108 };
4109
4110 fib_table_entry_path_add(fib_index,
4111 &pfx_2001_a_s_64,
4112 FIB_SOURCE_API,
4113 FIB_ENTRY_FLAG_NONE,
4114 FIB_PROTOCOL_IP6,
4115 &nh_2001_2,
4116 tm->hw[0]->sw_if_index,
4117 ~0,
4118 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004119 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004120 FIB_ROUTE_PATH_FLAG_NONE);
4121 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4122 ai = fib_entry_get_adj(fei);
4123 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4124 fib_table_entry_path_add(fib_index,
4125 &pfx_2001_b_s_64,
4126 FIB_SOURCE_API,
4127 FIB_ENTRY_FLAG_NONE,
4128 FIB_PROTOCOL_IP6,
4129 &nh_2001_2,
4130 tm->hw[0]->sw_if_index,
4131 ~0,
4132 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004133 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004134 FIB_ROUTE_PATH_FLAG_NONE);
4135 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4136 ai = fib_entry_get_adj(fei);
4137 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4138
4139 /*
4140 * +2 entries, +1 shared path-list.
4141 */
4142 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4143 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004144 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004145 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004146 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004147 fib_entry_pool_size());
4148
4149 /*
4150 * add a v4 prefix via a v6 next-hop
4151 */
4152 fib_prefix_t pfx_1_1_1_1_s_32 = {
4153 .fp_len = 32,
4154 .fp_proto = FIB_PROTOCOL_IP4,
4155 .fp_addr = {
4156 .ip4.as_u32 = 0x01010101,
4157 },
4158 };
4159 fei = fib_table_entry_path_add(0, // default table
4160 &pfx_1_1_1_1_s_32,
4161 FIB_SOURCE_API,
4162 FIB_ENTRY_FLAG_NONE,
4163 FIB_PROTOCOL_IP6,
4164 &nh_2001_2,
4165 tm->hw[0]->sw_if_index,
4166 ~0,
4167 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004168 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004169 FIB_ROUTE_PATH_FLAG_NONE);
4170 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4171 "1.1.1.1/32 o v6 route present");
4172 ai = fib_entry_get_adj(fei);
4173 adj = adj_get(ai);
4174 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4175 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004176 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004177 "1.1.1.1/32 ADJ-adj is link type v4");
4178 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4179 "1.1.1.1/32 ADJ-adj is NH proto v6");
4180 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4181
4182 /*
4183 * An attached route
4184 */
4185 fib_prefix_t pfx_2001_c_s_64 = {
4186 .fp_len = 64,
4187 .fp_proto = FIB_PROTOCOL_IP6,
4188 .fp_addr = {
4189 .ip6 = {
4190 .as_u64 = {
4191 [0] = clib_host_to_net_u64(0x200100000000000c),
4192 [1] = clib_host_to_net_u64(0x0000000000000000),
4193 },
4194 },
4195 }
4196 };
4197 fib_table_entry_path_add(fib_index,
4198 &pfx_2001_c_s_64,
4199 FIB_SOURCE_CLI,
4200 FIB_ENTRY_FLAG_ATTACHED,
4201 FIB_PROTOCOL_IP6,
4202 NULL,
4203 tm->hw[0]->sw_if_index,
4204 ~0,
4205 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004206 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004207 FIB_ROUTE_PATH_FLAG_NONE);
4208 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4209 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4210 ai = fib_entry_get_adj(fei);
4211 adj = adj_get(ai);
4212 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4213 "2001:0:0:c/64 attached resolves via glean");
4214
4215 fib_table_entry_path_remove(fib_index,
4216 &pfx_2001_c_s_64,
4217 FIB_SOURCE_CLI,
4218 FIB_PROTOCOL_IP6,
4219 NULL,
4220 tm->hw[0]->sw_if_index,
4221 ~0,
4222 1,
4223 FIB_ROUTE_PATH_FLAG_NONE);
4224 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4225 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4226
4227 /*
4228 * Shutdown the interface on which we have a connected and through
4229 * which the routes are reachable.
4230 * This will result in the connected, adj-fibs, and routes linking to drop
4231 * The local/for-us prefix continues to receive.
4232 */
4233 clib_error_t * error;
4234
4235 error = vnet_sw_interface_set_flags(vnet_get_main(),
4236 tm->hw[0]->sw_if_index,
4237 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4238 FIB_TEST((NULL == error), "Interface shutdown OK");
4239
4240 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4241 dpo = fib_entry_contribute_ip_forwarding(fei);
4242 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4243 "2001::b/64 resolves via drop");
4244
4245 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4246 dpo = fib_entry_contribute_ip_forwarding(fei);
4247 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4248 "2001::a/64 resolves via drop");
4249 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4250 dpo = fib_entry_contribute_ip_forwarding(fei);
4251 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4252 "2001:0:0:1::3/64 resolves via drop");
4253 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4254 dpo = fib_entry_contribute_ip_forwarding(fei);
4255 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4256 "2001:0:0:1::2/64 resolves via drop");
4257 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4258 dpo = fib_entry_contribute_ip_forwarding(fei);
4259 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4260 "2001:0:0:1::1/128 not drop");
4261 local_pfx.fp_len = 64;
4262 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4263 dpo = fib_entry_contribute_ip_forwarding(fei);
4264 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4265 "2001:0:0:1/64 resolves via drop");
4266
4267 /*
4268 * no change
4269 */
4270 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4271 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004272 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004273 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004274 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004275 fib_entry_pool_size());
4276
4277 /*
4278 * shutdown one of the other interfaces, then add a connected.
4279 * and swap one of the routes to it.
4280 */
4281 error = vnet_sw_interface_set_flags(vnet_get_main(),
4282 tm->hw[1]->sw_if_index,
4283 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4284 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4285
4286 fib_prefix_t connected_pfx = {
4287 .fp_len = 64,
4288 .fp_proto = FIB_PROTOCOL_IP6,
4289 .fp_addr = {
4290 .ip6 = {
4291 /* 2001:0:0:2::1/64 */
4292 .as_u64 = {
4293 [0] = clib_host_to_net_u64(0x2001000000000002),
4294 [1] = clib_host_to_net_u64(0x0000000000000001),
4295 },
4296 },
4297 }
4298 };
4299 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4300 FIB_SOURCE_INTERFACE,
4301 (FIB_ENTRY_FLAG_CONNECTED |
4302 FIB_ENTRY_FLAG_ATTACHED),
4303 FIB_PROTOCOL_IP6,
4304 NULL,
4305 tm->hw[1]->sw_if_index,
4306 ~0,
4307 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004308 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004309 FIB_ROUTE_PATH_FLAG_NONE);
4310 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4311 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4312 dpo = fib_entry_contribute_ip_forwarding(fei);
4313 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4314 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4315 "2001:0:0:2/64 not resolves via drop");
4316
4317 connected_pfx.fp_len = 128;
4318 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4319 FIB_SOURCE_INTERFACE,
4320 (FIB_ENTRY_FLAG_CONNECTED |
4321 FIB_ENTRY_FLAG_LOCAL),
4322 FIB_PROTOCOL_IP6,
4323 NULL,
4324 tm->hw[0]->sw_if_index,
4325 ~0, // invalid fib index
4326 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004327 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004328 FIB_ROUTE_PATH_FLAG_NONE);
4329 fei = fib_table_lookup(fib_index, &connected_pfx);
4330
4331 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4332 dpo = fib_entry_contribute_ip_forwarding(fei);
4333 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4334 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4335 "local interface adj is local");
4336 rd = receive_dpo_get(dpo->dpoi_index);
4337 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4338 &rd->rd_addr)),
4339 "local interface adj is receive ok");
4340
4341 /*
4342 * +2 entries, +2 unshared path-lists
4343 */
4344 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4345 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004346 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004347 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004348 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004349 fib_entry_pool_size());
4350
4351
4352 /*
4353 * bring the interface back up. we expected the routes to return
4354 * to normal forwarding.
4355 */
4356 error = vnet_sw_interface_set_flags(vnet_get_main(),
4357 tm->hw[0]->sw_if_index,
4358 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4359 FIB_TEST((NULL == error), "Interface bring-up OK");
4360 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4361 ai = fib_entry_get_adj(fei);
4362 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4363 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4364 ai = fib_entry_get_adj(fei);
4365 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4366 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4367 ai = fib_entry_get_adj(fei);
4368 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4369 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4370 ai = fib_entry_get_adj(fei);
4371 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4372 local_pfx.fp_len = 64;
4373 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4374 ai = fib_entry_get_adj(fei);
4375 adj = adj_get(ai);
4376 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4377 "attached interface adj is glean");
4378
4379 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004380 * Same test as above, but this time the HW interface goes down
4381 */
4382 error = vnet_hw_interface_set_flags(vnet_get_main(),
4383 tm->hw_if_indicies[0],
4384 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4385 FIB_TEST((NULL == error), "Interface shutdown OK");
4386
4387 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4388 dpo = fib_entry_contribute_ip_forwarding(fei);
4389 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4390 "2001::b/64 resolves via drop");
4391 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4392 dpo = fib_entry_contribute_ip_forwarding(fei);
4393 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4394 "2001::a/64 resolves via drop");
4395 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4396 dpo = fib_entry_contribute_ip_forwarding(fei);
4397 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4398 "2001:0:0:1::3/128 resolves via drop");
4399 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4400 dpo = fib_entry_contribute_ip_forwarding(fei);
4401 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4402 "2001:0:0:1::2/128 resolves via drop");
4403 local_pfx.fp_len = 128;
4404 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4405 dpo = fib_entry_contribute_ip_forwarding(fei);
4406 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4407 "2001:0:0:1::1/128 not drop");
4408 local_pfx.fp_len = 64;
4409 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4410 dpo = fib_entry_contribute_ip_forwarding(fei);
4411 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4412 "2001:0:0:1/64 resolves via drop");
4413
4414 error = vnet_hw_interface_set_flags(vnet_get_main(),
4415 tm->hw_if_indicies[0],
4416 VNET_HW_INTERFACE_FLAG_LINK_UP);
4417 FIB_TEST((NULL == error), "Interface bring-up OK");
4418 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4419 ai = fib_entry_get_adj(fei);
4420 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4421 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4422 ai = fib_entry_get_adj(fei);
4423 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4424 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4425 ai = fib_entry_get_adj(fei);
4426 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4427 fei = fib_table_lookup_exact_match(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 local_pfx.fp_len = 64;
4431 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4432 ai = fib_entry_get_adj(fei);
4433 adj = adj_get(ai);
4434 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4435 "attached interface adj is glean");
4436
4437 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004438 * Delete the interface that the routes reolve through.
4439 * Again no routes are removed. They all point to drop.
4440 *
4441 * This is considered an error case. The control plane should
4442 * not remove interfaces through which routes resolve, but
4443 * such things can happen. ALL affected routes will drop.
4444 */
4445 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4446
4447 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4448 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4449 "2001::b/64 resolves via drop");
4450 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4451 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4452 "2001::b/64 resolves via drop");
4453 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4454 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4455 "2001:0:0:1::3/64 resolves via drop");
4456 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4457 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4458 "2001:0:0:1::2/64 resolves via drop");
4459 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4460 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4461 "2001:0:0:1::1/128 is drop");
4462 local_pfx.fp_len = 64;
4463 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4464 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4465 "2001:0:0:1/64 resolves via drop");
4466
4467 /*
4468 * no change
4469 */
4470 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4471 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004472 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004473 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004474 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004475 fib_entry_pool_size());
4476
4477 /*
4478 * Add the interface back. routes stay unresolved.
4479 */
4480 error = ethernet_register_interface(vnet_get_main(),
4481 test_interface_device_class.index,
4482 0 /* instance */,
4483 hw_address,
4484 &tm->hw_if_indicies[0],
4485 /* flag change */ 0);
4486
4487 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4488 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4489 "2001::b/64 resolves via drop");
4490 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4491 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4492 "2001::b/64 resolves via drop");
4493 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4494 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4495 "2001:0:0:1::3/64 resolves via drop");
4496 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4497 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4498 "2001:0:0:1::2/64 resolves via drop");
4499 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4500 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4501 "2001:0:0:1::1/128 is drop");
4502 local_pfx.fp_len = 64;
4503 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4504 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4505 "2001:0:0:1/64 resolves via drop");
4506
4507 /*
4508 * CLEANUP ALL the routes
4509 */
4510 fib_table_entry_delete(fib_index,
4511 &pfx_2001_c_s_64,
4512 FIB_SOURCE_API);
4513 fib_table_entry_delete(fib_index,
4514 &pfx_2001_a_s_64,
4515 FIB_SOURCE_API);
4516 fib_table_entry_delete(fib_index,
4517 &pfx_2001_b_s_64,
4518 FIB_SOURCE_API);
4519 fib_table_entry_delete(fib_index,
4520 &pfx_2001_1_3_s_128,
4521 FIB_SOURCE_ADJ);
4522 fib_table_entry_delete(fib_index,
4523 &pfx_2001_1_2_s_128,
4524 FIB_SOURCE_ADJ);
4525 local_pfx.fp_len = 64;
4526 fib_table_entry_delete(fib_index, &local_pfx,
4527 FIB_SOURCE_INTERFACE);
4528 local_pfx.fp_len = 128;
4529 fib_table_entry_special_remove(fib_index, &local_pfx,
4530 FIB_SOURCE_INTERFACE);
4531 connected_pfx.fp_len = 64;
4532 fib_table_entry_delete(fib_index, &connected_pfx,
4533 FIB_SOURCE_INTERFACE);
4534 connected_pfx.fp_len = 128;
4535 fib_table_entry_special_remove(fib_index, &connected_pfx,
4536 FIB_SOURCE_INTERFACE);
4537
4538 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4539 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
4540 "2001::a/64 removed");
4541 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4542 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
4543 "2001::b/64 removed");
4544 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4545 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
4546 "2001:0:0:1::3/128 removed");
4547 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4548 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
4549 "2001:0:0:1::3/128 removed");
4550 local_pfx.fp_len = 64;
4551 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4552 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4553 "2001:0:0:1/64 removed");
4554 local_pfx.fp_len = 128;
4555 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4556 fib_table_lookup_exact_match(fib_index, &local_pfx)),
4557 "2001:0:0:1::1/128 removed");
4558 connected_pfx.fp_len = 64;
4559 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4560 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4561 "2001:0:0:2/64 removed");
4562 connected_pfx.fp_len = 128;
4563 FIB_TEST((FIB_NODE_INDEX_INVALID ==
4564 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
4565 "2001:0:0:2::1/128 removed");
4566
4567 /*
4568 * -8 entries. -7 path-lists (1 was shared).
4569 */
4570 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4571 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004572 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004573 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004574 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004575 fib_entry_pool_size());
4576
4577 /*
4578 * now remove the VRF
4579 */
4580 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
4581
4582 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4583 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004584 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004585 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004586 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004587 fib_entry_pool_size());
4588
4589 adj_unlock(ai_02);
4590 adj_unlock(ai_01);
4591
4592 /*
4593 * return the interfaces to up state
4594 */
4595 error = vnet_sw_interface_set_flags(vnet_get_main(),
4596 tm->hw[0]->sw_if_index,
4597 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4598 error = vnet_sw_interface_set_flags(vnet_get_main(),
4599 tm->hw[1]->sw_if_index,
4600 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4601
4602 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4603 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004604
4605 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004606}
4607
4608/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004609 * Test Attached Exports
4610 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004611static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004612fib_test_ae (void)
4613{
4614 const dpo_id_t *dpo, *dpo_drop;
4615 const u32 fib_index = 0;
4616 fib_node_index_t fei;
4617 test_main_t *tm;
4618 ip4_main_t *im;
4619
4620 tm = &test_main;
4621 im = &ip4_main;
4622
4623 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4624 adj_nbr_db_size());
4625
4626 /*
4627 * add interface routes. We'll assume this works. It's more rigorously
4628 * tested elsewhere.
4629 */
4630 fib_prefix_t local_pfx = {
4631 .fp_len = 24,
4632 .fp_proto = FIB_PROTOCOL_IP4,
4633 .fp_addr = {
4634 .ip4 = {
4635 /* 10.10.10.10 */
4636 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
4637 },
4638 },
4639 };
4640
4641 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
4642 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
4643
4644 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
4645
4646 fib_table_entry_update_one_path(fib_index, &local_pfx,
4647 FIB_SOURCE_INTERFACE,
4648 (FIB_ENTRY_FLAG_CONNECTED |
4649 FIB_ENTRY_FLAG_ATTACHED),
4650 FIB_PROTOCOL_IP4,
4651 NULL,
4652 tm->hw[0]->sw_if_index,
4653 ~0,
4654 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004655 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004656 FIB_ROUTE_PATH_FLAG_NONE);
4657 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4658 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4659 "attached interface route present");
4660
4661 local_pfx.fp_len = 32;
4662 fib_table_entry_update_one_path(fib_index, &local_pfx,
4663 FIB_SOURCE_INTERFACE,
4664 (FIB_ENTRY_FLAG_CONNECTED |
4665 FIB_ENTRY_FLAG_LOCAL),
4666 FIB_PROTOCOL_IP4,
4667 NULL,
4668 tm->hw[0]->sw_if_index,
4669 ~0, // invalid fib index
4670 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004671 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004672 FIB_ROUTE_PATH_FLAG_NONE);
4673 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4674
4675 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
4676 "local interface route present");
4677
4678 /*
4679 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4680 */
4681 fib_prefix_t pfx_10_10_10_1_s_32 = {
4682 .fp_len = 32,
4683 .fp_proto = FIB_PROTOCOL_IP4,
4684 .fp_addr = {
4685 /* 10.10.10.1 */
4686 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
4687 },
4688 };
4689 fib_node_index_t ai;
4690
4691 fib_table_entry_update_one_path(fib_index,
4692 &pfx_10_10_10_1_s_32,
4693 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004694 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004695 FIB_PROTOCOL_IP4,
4696 &pfx_10_10_10_1_s_32.fp_addr,
4697 tm->hw[0]->sw_if_index,
4698 ~0, // invalid fib index
4699 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004700 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004701 FIB_ROUTE_PATH_FLAG_NONE);
4702
4703 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
4704 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
4705 ai = fib_entry_get_adj(fei);
4706
4707 /*
4708 * create another FIB table into which routes will be imported
4709 */
4710 u32 import_fib_index1;
4711
4712 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
4713
4714 /*
4715 * Add an attached route in the import FIB
4716 */
4717 local_pfx.fp_len = 24;
4718 fib_table_entry_update_one_path(import_fib_index1,
4719 &local_pfx,
4720 FIB_SOURCE_API,
4721 FIB_ENTRY_FLAG_NONE,
4722 FIB_PROTOCOL_IP4,
4723 NULL,
4724 tm->hw[0]->sw_if_index,
4725 ~0, // invalid fib index
4726 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004727 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004728 FIB_ROUTE_PATH_FLAG_NONE);
4729 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4730 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4731
4732 /*
4733 * check for the presence of the adj-fibs in the import table
4734 */
4735 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4736 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4737 FIB_TEST((ai == fib_entry_get_adj(fei)),
4738 "adj-fib1 Import uses same adj as export");
4739
4740 /*
4741 * check for the presence of the local in the import table
4742 */
4743 local_pfx.fp_len = 32;
4744 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4745 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4746
4747 /*
4748 * Add another adj-fin in the export table. Expect this
4749 * to get magically exported;
4750 */
4751 fib_prefix_t pfx_10_10_10_2_s_32 = {
4752 .fp_len = 32,
4753 .fp_proto = FIB_PROTOCOL_IP4,
4754 .fp_addr = {
4755 /* 10.10.10.2 */
4756 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
4757 },
4758 };
4759
4760 fib_table_entry_update_one_path(fib_index,
4761 &pfx_10_10_10_2_s_32,
4762 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004763 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004764 FIB_PROTOCOL_IP4,
4765 &pfx_10_10_10_2_s_32.fp_addr,
4766 tm->hw[0]->sw_if_index,
4767 ~0, // invalid fib index
4768 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004769 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004770 FIB_ROUTE_PATH_FLAG_NONE);
4771 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
4772 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
4773 ai = fib_entry_get_adj(fei);
4774
4775 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4776 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4777 FIB_TEST((ai == fib_entry_get_adj(fei)),
4778 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00004779 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
4780 "ADJ-fib2 imported flags %d",
4781 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004782
4783 /*
4784 * create a 2nd FIB table into which routes will be imported
4785 */
4786 u32 import_fib_index2;
4787
4788 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
4789
4790 /*
4791 * Add an attached route in the import FIB
4792 */
4793 local_pfx.fp_len = 24;
4794 fib_table_entry_update_one_path(import_fib_index2,
4795 &local_pfx,
4796 FIB_SOURCE_API,
4797 FIB_ENTRY_FLAG_NONE,
4798 FIB_PROTOCOL_IP4,
4799 NULL,
4800 tm->hw[0]->sw_if_index,
4801 ~0, // invalid fib index
4802 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004803 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004804 FIB_ROUTE_PATH_FLAG_NONE);
4805 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4806 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
4807
4808 /*
4809 * check for the presence of all the adj-fibs and local in the import table
4810 */
4811 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4812 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
4813 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4814 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
4815 local_pfx.fp_len = 32;
4816 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4817 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
4818
4819 /*
4820 * add a 3rd adj-fib. expect it to be exported to both tables.
4821 */
4822 fib_prefix_t pfx_10_10_10_3_s_32 = {
4823 .fp_len = 32,
4824 .fp_proto = FIB_PROTOCOL_IP4,
4825 .fp_addr = {
4826 /* 10.10.10.3 */
4827 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
4828 },
4829 };
4830
4831 fib_table_entry_update_one_path(fib_index,
4832 &pfx_10_10_10_3_s_32,
4833 FIB_SOURCE_ADJ,
Neale Rannsfa0fb582016-12-10 21:59:14 +00004834 FIB_ENTRY_FLAG_ATTACHED,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004835 FIB_PROTOCOL_IP4,
4836 &pfx_10_10_10_3_s_32.fp_addr,
4837 tm->hw[0]->sw_if_index,
4838 ~0, // invalid fib index
4839 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004840 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004841 FIB_ROUTE_PATH_FLAG_NONE);
4842 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4843 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
4844 ai = fib_entry_get_adj(fei);
4845
4846 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4847 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
4848 FIB_TEST((ai == fib_entry_get_adj(fei)),
4849 "Import uses same adj as export");
4850 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4851 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
4852 FIB_TEST((ai == fib_entry_get_adj(fei)),
4853 "Import uses same adj as export");
4854
4855 /*
4856 * remove the 3rd adj fib. we expect it to be removed from both FIBs
4857 */
4858 fib_table_entry_delete(fib_index,
4859 &pfx_10_10_10_3_s_32,
4860 FIB_SOURCE_ADJ);
4861
4862 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4863 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
4864
4865 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
4866 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
4867
4868 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
4869 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
4870
4871 /*
4872 * remove the attached route from the 2nd FIB. expect the imported
4873 * entires to be removed
4874 */
4875 local_pfx.fp_len = 24;
4876 fib_table_entry_delete(import_fib_index2,
4877 &local_pfx,
4878 FIB_SOURCE_API);
4879 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4880 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
4881
4882 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
4883 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
4884 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
4885 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
4886 local_pfx.fp_len = 32;
4887 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
4888 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
4889
4890 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4891 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
4892 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4893 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
4894 local_pfx.fp_len = 32;
4895 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4896 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
4897
4898 /*
4899 * modify the route in FIB1 so it is no longer attached. expect the imported
4900 * entires to be removed
4901 */
4902 local_pfx.fp_len = 24;
4903 fib_table_entry_update_one_path(import_fib_index1,
4904 &local_pfx,
4905 FIB_SOURCE_API,
4906 FIB_ENTRY_FLAG_NONE,
4907 FIB_PROTOCOL_IP4,
4908 &pfx_10_10_10_2_s_32.fp_addr,
4909 tm->hw[0]->sw_if_index,
4910 ~0, // invalid fib index
4911 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004912 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004913 FIB_ROUTE_PATH_FLAG_NONE);
4914 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4915 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
4916 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4917 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4918 local_pfx.fp_len = 32;
4919 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4920 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4921
4922 /*
4923 * modify it back to attached. expect the adj-fibs back
4924 */
4925 local_pfx.fp_len = 24;
4926 fib_table_entry_update_one_path(import_fib_index1,
4927 &local_pfx,
4928 FIB_SOURCE_API,
4929 FIB_ENTRY_FLAG_NONE,
4930 FIB_PROTOCOL_IP4,
4931 NULL,
4932 tm->hw[0]->sw_if_index,
4933 ~0, // invalid fib index
4934 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004935 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004936 FIB_ROUTE_PATH_FLAG_NONE);
4937 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4938 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
4939 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4940 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
4941 local_pfx.fp_len = 32;
4942 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4943 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
4944
4945 /*
4946 * add a covering attached next-hop for the interface address, so we have
4947 * a valid adj to find when we check the forwarding tables
4948 */
4949 fib_prefix_t pfx_10_0_0_0_s_8 = {
4950 .fp_len = 8,
4951 .fp_proto = FIB_PROTOCOL_IP4,
4952 .fp_addr = {
4953 /* 10.0.0.0 */
4954 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
4955 },
4956 };
4957
4958 fei = fib_table_entry_update_one_path(fib_index,
4959 &pfx_10_0_0_0_s_8,
4960 FIB_SOURCE_API,
4961 FIB_ENTRY_FLAG_NONE,
4962 FIB_PROTOCOL_IP4,
4963 &pfx_10_10_10_3_s_32.fp_addr,
4964 tm->hw[0]->sw_if_index,
4965 ~0, // invalid fib index
4966 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004967 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004968 FIB_ROUTE_PATH_FLAG_NONE);
4969 dpo = fib_entry_contribute_ip_forwarding(fei);
4970
4971 /*
4972 * remove the route in the export fib. expect the adj-fibs to be removed
4973 */
4974 local_pfx.fp_len = 24;
4975 fib_table_entry_delete(fib_index,
4976 &local_pfx,
4977 FIB_SOURCE_INTERFACE);
4978
4979 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
4980 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
4981 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
4982 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
4983 local_pfx.fp_len = 32;
4984 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
4985 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
4986
4987 /*
4988 * the adj-fibs in the export VRF are present in the FIB table,
4989 * but not installed in forwarding, since they have no attached cover.
4990 * Consequently a lookup in the MTRIE gives the adj for the covering
4991 * route 10.0.0.0/8.
4992 */
4993 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4994 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
4995
4996 index_t lbi;
4997 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
4998 FIB_TEST(lbi == dpo->dpoi_index,
4999 "10.10.10.1 forwards on \n%U not \n%U",
5000 format_load_balance, lbi, 0,
5001 format_dpo_id, dpo, 0);
5002 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5003 FIB_TEST(lbi == dpo->dpoi_index,
5004 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5005 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5006 FIB_TEST(lbi == dpo->dpoi_index,
5007 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5008
5009 /*
5010 * add the export prefix back, but not as attached.
5011 * No adj-fibs in export nor import tables
5012 */
5013 local_pfx.fp_len = 24;
5014 fei = fib_table_entry_update_one_path(fib_index,
5015 &local_pfx,
5016 FIB_SOURCE_API,
5017 FIB_ENTRY_FLAG_NONE,
5018 FIB_PROTOCOL_IP4,
5019 &pfx_10_10_10_1_s_32.fp_addr,
5020 tm->hw[0]->sw_if_index,
5021 ~0, // invalid fib index
5022 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005023 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005024 FIB_ROUTE_PATH_FLAG_NONE);
5025 dpo = fib_entry_contribute_ip_forwarding(fei);
5026
5027 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5028 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5029 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5030 FIB_TEST(lbi == dpo->dpoi_index,
5031 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5032 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5033 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5034 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5035 FIB_TEST(lbi == dpo->dpoi_index,
5036 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5037
5038 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5039 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5040 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5041 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5042 local_pfx.fp_len = 32;
5043 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5044 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5045
5046 /*
5047 * modify the export prefix so it is attached. expect all covereds to return
5048 */
5049 local_pfx.fp_len = 24;
5050 fib_table_entry_update_one_path(fib_index,
5051 &local_pfx,
5052 FIB_SOURCE_API,
5053 FIB_ENTRY_FLAG_NONE,
5054 FIB_PROTOCOL_IP4,
5055 NULL,
5056 tm->hw[0]->sw_if_index,
5057 ~0, // invalid fib index
5058 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005059 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005060 FIB_ROUTE_PATH_FLAG_NONE);
5061
5062 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5063 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5064 dpo = fib_entry_contribute_ip_forwarding(fei);
5065 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5066 "Adj-fib1 is not drop in export");
5067 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5068 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5069 local_pfx.fp_len = 32;
5070 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5071 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5072 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5073 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5074 dpo = fib_entry_contribute_ip_forwarding(fei);
5075 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5076 "Adj-fib1 is not drop in export");
5077 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5078 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5079 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5080 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5081 local_pfx.fp_len = 32;
5082 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5083 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5084
5085 /*
5086 * modify the export prefix so connected. no change.
5087 */
5088 local_pfx.fp_len = 24;
5089 fib_table_entry_update_one_path(fib_index, &local_pfx,
5090 FIB_SOURCE_INTERFACE,
5091 (FIB_ENTRY_FLAG_CONNECTED |
5092 FIB_ENTRY_FLAG_ATTACHED),
5093 FIB_PROTOCOL_IP4,
5094 NULL,
5095 tm->hw[0]->sw_if_index,
5096 ~0,
5097 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005098 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005099 FIB_ROUTE_PATH_FLAG_NONE);
5100
5101 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5102 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5103 dpo = fib_entry_contribute_ip_forwarding(fei);
5104 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5105 "Adj-fib1 is not drop in export");
5106 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5107 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5108 local_pfx.fp_len = 32;
5109 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5110 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5111 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5112 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5113 dpo = fib_entry_contribute_ip_forwarding(fei);
5114 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5115 "Adj-fib1 is not drop in export");
5116 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5117 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5118 local_pfx.fp_len = 32;
5119 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5120 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5121
5122 /*
5123 * CLEANUP
5124 */
5125 fib_table_entry_delete(fib_index,
5126 &pfx_10_0_0_0_s_8,
5127 FIB_SOURCE_API);
5128 fib_table_entry_delete(fib_index,
5129 &pfx_10_10_10_1_s_32,
5130 FIB_SOURCE_ADJ);
5131 fib_table_entry_delete(fib_index,
5132 &pfx_10_10_10_2_s_32,
5133 FIB_SOURCE_ADJ);
5134 local_pfx.fp_len = 32;
5135 fib_table_entry_delete(fib_index,
5136 &local_pfx,
5137 FIB_SOURCE_INTERFACE);
5138 local_pfx.fp_len = 24;
5139 fib_table_entry_delete(fib_index,
5140 &local_pfx,
5141 FIB_SOURCE_API);
5142 fib_table_entry_delete(fib_index,
5143 &local_pfx,
5144 FIB_SOURCE_INTERFACE);
5145 local_pfx.fp_len = 24;
5146 fib_table_entry_delete(import_fib_index1,
5147 &local_pfx,
5148 FIB_SOURCE_API);
5149
5150 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
5151 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
5152
5153 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5154 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005155
5156 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005157}
5158
Neale Rannsad422ed2016-11-02 14:20:04 +00005159
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005160/*
5161 * Test the recursive route route handling for GRE tunnels
5162 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005163static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005164fib_test_label (void)
5165{
5166 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;
5167 const u32 fib_index = 0;
5168 test_main_t *tm;
5169 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00005170 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005171
5172 lb_count = pool_elts(load_balance_pool);
5173 tm = &test_main;
5174 im = &ip4_main;
5175
5176 /*
5177 * add interface routes. We'll assume this works. It's more rigorously
5178 * tested elsewhere.
5179 */
5180 fib_prefix_t local0_pfx = {
5181 .fp_len = 24,
5182 .fp_proto = FIB_PROTOCOL_IP4,
5183 .fp_addr = {
5184 .ip4 = {
5185 /* 10.10.10.10 */
5186 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5187 },
5188 },
5189 };
5190
5191 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5192 adj_nbr_db_size());
5193
5194 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5195 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5196
5197 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5198 FIB_SOURCE_INTERFACE,
5199 (FIB_ENTRY_FLAG_CONNECTED |
5200 FIB_ENTRY_FLAG_ATTACHED),
5201 FIB_PROTOCOL_IP4,
5202 NULL,
5203 tm->hw[0]->sw_if_index,
5204 ~0,
5205 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005206 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005207 FIB_ROUTE_PATH_FLAG_NONE);
5208 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5209 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5210 "attached interface route present");
5211
5212 local0_pfx.fp_len = 32;
5213 fib_table_entry_update_one_path(fib_index, &local0_pfx,
5214 FIB_SOURCE_INTERFACE,
5215 (FIB_ENTRY_FLAG_CONNECTED |
5216 FIB_ENTRY_FLAG_LOCAL),
5217 FIB_PROTOCOL_IP4,
5218 NULL,
5219 tm->hw[0]->sw_if_index,
5220 ~0, // invalid fib index
5221 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005222 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005223 FIB_ROUTE_PATH_FLAG_NONE);
5224 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
5225
5226 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5227 "local interface route present");
5228
5229 fib_prefix_t local1_pfx = {
5230 .fp_len = 24,
5231 .fp_proto = FIB_PROTOCOL_IP4,
5232 .fp_addr = {
5233 .ip4 = {
5234 /* 10.10.11.10 */
5235 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
5236 },
5237 },
5238 };
5239
5240 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
5241 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
5242
5243 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5244 FIB_SOURCE_INTERFACE,
5245 (FIB_ENTRY_FLAG_CONNECTED |
5246 FIB_ENTRY_FLAG_ATTACHED),
5247 FIB_PROTOCOL_IP4,
5248 NULL,
5249 tm->hw[1]->sw_if_index,
5250 ~0,
5251 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005252 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005253 FIB_ROUTE_PATH_FLAG_NONE);
5254 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5255 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5256 "attached interface route present");
5257
5258 local1_pfx.fp_len = 32;
5259 fib_table_entry_update_one_path(fib_index, &local1_pfx,
5260 FIB_SOURCE_INTERFACE,
5261 (FIB_ENTRY_FLAG_CONNECTED |
5262 FIB_ENTRY_FLAG_LOCAL),
5263 FIB_PROTOCOL_IP4,
5264 NULL,
5265 tm->hw[1]->sw_if_index,
5266 ~0, // invalid fib index
5267 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005268 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005269 FIB_ROUTE_PATH_FLAG_NONE);
5270 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
5271
5272 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5273 "local interface route present");
5274
5275 ip46_address_t nh_10_10_10_1 = {
5276 .ip4 = {
5277 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5278 },
5279 };
5280 ip46_address_t nh_10_10_11_1 = {
5281 .ip4 = {
5282 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5283 },
5284 };
5285 ip46_address_t nh_10_10_11_2 = {
5286 .ip4 = {
5287 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5288 },
5289 };
5290
5291 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005292 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005293 &nh_10_10_11_1,
5294 tm->hw[1]->sw_if_index);
5295 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005296 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005297 &nh_10_10_11_2,
5298 tm->hw[1]->sw_if_index);
5299 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005300 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005301 &nh_10_10_10_1,
5302 tm->hw[0]->sw_if_index);
5303 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005304 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005305 &nh_10_10_11_2,
5306 tm->hw[1]->sw_if_index);
5307 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01005308 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005309 &nh_10_10_11_1,
5310 tm->hw[1]->sw_if_index);
5311
5312 /*
5313 * Add an etry with one path with a real out-going label
5314 */
5315 fib_prefix_t pfx_1_1_1_1_s_32 = {
5316 .fp_len = 32,
5317 .fp_proto = FIB_PROTOCOL_IP4,
5318 .fp_addr = {
5319 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
5320 },
5321 };
5322 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
5323 .type = FT_LB_LABEL_O_ADJ,
5324 .label_o_adj = {
5325 .adj = ai_mpls_10_10_10_1,
5326 .label = 99,
5327 .eos = MPLS_EOS,
5328 },
5329 };
5330 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
5331 .type = FT_LB_LABEL_O_ADJ,
5332 .label_o_adj = {
5333 .adj = ai_mpls_10_10_10_1,
5334 .label = 99,
5335 .eos = MPLS_NON_EOS,
5336 },
5337 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005338 mpls_label_t *l99 = NULL;
5339 vec_add1(l99, 99);
5340
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005341 fib_table_entry_update_one_path(fib_index,
5342 &pfx_1_1_1_1_s_32,
5343 FIB_SOURCE_API,
5344 FIB_ENTRY_FLAG_NONE,
5345 FIB_PROTOCOL_IP4,
5346 &nh_10_10_10_1,
5347 tm->hw[0]->sw_if_index,
5348 ~0, // invalid fib index
5349 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005350 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005351 FIB_ROUTE_PATH_FLAG_NONE);
5352
5353 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5354 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
5355
5356 FIB_TEST(fib_test_validate_entry(fei,
5357 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5358 1,
5359 &l99_eos_o_10_10_10_1),
5360 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
5361
5362 /*
5363 * add a path with an implicit NULL label
5364 */
5365 fib_test_lb_bucket_t a_o_10_10_11_1 = {
5366 .type = FT_LB_ADJ,
5367 .adj = {
5368 .adj = ai_v4_10_10_11_1,
5369 },
5370 };
5371 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
5372 .type = FT_LB_ADJ,
5373 .adj = {
5374 .adj = ai_mpls_10_10_11_1,
5375 },
5376 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005377 mpls_label_t *l_imp_null = NULL;
5378 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005379
5380 fei = fib_table_entry_path_add(fib_index,
5381 &pfx_1_1_1_1_s_32,
5382 FIB_SOURCE_API,
5383 FIB_ENTRY_FLAG_NONE,
5384 FIB_PROTOCOL_IP4,
5385 &nh_10_10_11_1,
5386 tm->hw[1]->sw_if_index,
5387 ~0, // invalid fib index
5388 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005389 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005390 FIB_ROUTE_PATH_FLAG_NONE);
5391
5392 FIB_TEST(fib_test_validate_entry(fei,
5393 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5394 2,
5395 &l99_eos_o_10_10_10_1,
5396 &a_o_10_10_11_1),
5397 "1.1.1.1/32 LB 2 buckets via: "
5398 "label 99 over 10.10.10.1, "
5399 "adj over 10.10.11.1");
5400
5401 /*
5402 * assign the route a local label
5403 */
5404 fib_table_entry_local_label_add(fib_index,
5405 &pfx_1_1_1_1_s_32,
5406 24001);
5407
5408 fib_prefix_t pfx_24001_eos = {
5409 .fp_proto = FIB_PROTOCOL_MPLS,
5410 .fp_label = 24001,
5411 .fp_eos = MPLS_EOS,
5412 };
5413 fib_prefix_t pfx_24001_neos = {
5414 .fp_proto = FIB_PROTOCOL_MPLS,
5415 .fp_label = 24001,
5416 .fp_eos = MPLS_NON_EOS,
5417 };
5418
5419 /*
5420 * The EOS entry should link to both the paths,
5421 * and use an ip adj for the imp-null
5422 * The NON-EOS entry should link to both the paths,
5423 * and use an mpls adj for the imp-null
5424 */
5425 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5426 &pfx_24001_eos);
5427 FIB_TEST(fib_test_validate_entry(fei,
5428 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5429 2,
5430 &l99_eos_o_10_10_10_1,
5431 &a_o_10_10_11_1),
5432 "24001/eos LB 2 buckets via: "
5433 "label 99 over 10.10.10.1, "
5434 "adj over 10.10.11.1");
5435
5436
5437 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5438 &pfx_24001_neos);
5439 FIB_TEST(fib_test_validate_entry(fei,
5440 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5441 2,
5442 &l99_neos_o_10_10_10_1,
5443 &a_mpls_o_10_10_11_1),
5444 "24001/neos LB 1 bucket via: "
5445 "label 99 over 10.10.10.1 ",
5446 "mpls-adj via 10.10.11.1");
5447
5448 /*
5449 * add an unlabelled path, this is excluded from the neos chains,
5450 */
5451 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
5452 .type = FT_LB_ADJ,
5453 .adj = {
5454 .adj = ai_v4_10_10_11_2,
5455 },
5456 };
5457
5458 fei = fib_table_entry_path_add(fib_index,
5459 &pfx_1_1_1_1_s_32,
5460 FIB_SOURCE_API,
5461 FIB_ENTRY_FLAG_NONE,
5462 FIB_PROTOCOL_IP4,
5463 &nh_10_10_11_2,
5464 tm->hw[1]->sw_if_index,
5465 ~0, // invalid fib index
5466 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005467 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005468 FIB_ROUTE_PATH_FLAG_NONE);
5469
5470 FIB_TEST(fib_test_validate_entry(fei,
5471 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5472 16, // 3 choices spread over 16 buckets
5473 &l99_eos_o_10_10_10_1,
5474 &l99_eos_o_10_10_10_1,
5475 &l99_eos_o_10_10_10_1,
5476 &l99_eos_o_10_10_10_1,
5477 &l99_eos_o_10_10_10_1,
5478 &l99_eos_o_10_10_10_1,
5479 &a_o_10_10_11_1,
5480 &a_o_10_10_11_1,
5481 &a_o_10_10_11_1,
5482 &a_o_10_10_11_1,
5483 &a_o_10_10_11_1,
5484 &adj_o_10_10_11_2,
5485 &adj_o_10_10_11_2,
5486 &adj_o_10_10_11_2,
5487 &adj_o_10_10_11_2,
5488 &adj_o_10_10_11_2),
5489 "1.1.1.1/32 LB 16 buckets via: "
5490 "label 99 over 10.10.10.1, "
5491 "adj over 10.10.11.1",
5492 "adj over 10.10.11.2");
5493
5494 /*
5495 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
5496 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005497 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005498 fib_entry_contribute_forwarding(fei,
5499 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5500 &non_eos_1_1_1_1);
5501
5502 /*
5503 * n-eos has only the 2 labelled paths
5504 */
5505 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5506 &pfx_24001_neos);
5507
5508 FIB_TEST(fib_test_validate_entry(fei,
5509 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5510 2,
5511 &l99_neos_o_10_10_10_1,
5512 &a_mpls_o_10_10_11_1),
5513 "24001/neos LB 2 buckets via: "
5514 "label 99 over 10.10.10.1, "
5515 "adj-mpls over 10.10.11.2");
5516
5517 /*
5518 * A labelled recursive
5519 */
5520 fib_prefix_t pfx_2_2_2_2_s_32 = {
5521 .fp_len = 32,
5522 .fp_proto = FIB_PROTOCOL_IP4,
5523 .fp_addr = {
5524 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
5525 },
5526 };
5527 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
5528 .type = FT_LB_LABEL_O_LB,
5529 .label_o_lb = {
5530 .lb = non_eos_1_1_1_1.dpoi_index,
5531 .label = 1600,
5532 .eos = MPLS_EOS,
5533 },
5534 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005535 mpls_label_t *l1600 = NULL;
5536 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005537
5538 fib_table_entry_update_one_path(fib_index,
5539 &pfx_2_2_2_2_s_32,
5540 FIB_SOURCE_API,
5541 FIB_ENTRY_FLAG_NONE,
5542 FIB_PROTOCOL_IP4,
5543 &pfx_1_1_1_1_s_32.fp_addr,
5544 ~0,
5545 fib_index,
5546 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005547 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005548 FIB_ROUTE_PATH_FLAG_NONE);
5549
5550 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
5551 FIB_TEST(fib_test_validate_entry(fei,
5552 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5553 1,
5554 &l1600_eos_o_1_1_1_1),
5555 "2.2.2.2.2/32 LB 1 buckets via: "
5556 "label 1600 over 1.1.1.1");
5557
Neale Ranns948e00f2016-10-20 13:39:34 +01005558 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01005559 index_t urpfi;
5560
5561 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
5562 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
5563
5564 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
5565 "uRPF check for 2.2.2.2/32 on %d OK",
5566 tm->hw[0]->sw_if_index);
5567 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
5568 "uRPF check for 2.2.2.2/32 on %d OK",
5569 tm->hw[1]->sw_if_index);
5570 FIB_TEST(!fib_urpf_check(urpfi, 99),
5571 "uRPF check for 2.2.2.2/32 on 99 not-OK",
5572 99);
5573
5574 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
5575 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
5576 "Shared uRPF on IP and non-EOS chain");
5577
5578 dpo_reset(&dpo_44);
5579
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005580 /*
5581 * we are holding a lock on the non-eos LB of the via-entry.
5582 * do a PIC-core failover by shutting the link of the via-entry.
5583 *
5584 * shut down the link with the valid label
5585 */
5586 vnet_sw_interface_set_flags(vnet_get_main(),
5587 tm->hw[0]->sw_if_index,
5588 0);
5589
5590 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5591 FIB_TEST(fib_test_validate_entry(fei,
5592 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5593 2,
5594 &a_o_10_10_11_1,
5595 &adj_o_10_10_11_2),
5596 "1.1.1.1/32 LB 2 buckets via: "
5597 "adj over 10.10.11.1, ",
5598 "adj-v4 over 10.10.11.2");
5599
5600 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5601 &pfx_24001_eos);
5602 FIB_TEST(fib_test_validate_entry(fei,
5603 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5604 2,
5605 &a_o_10_10_11_1,
5606 &adj_o_10_10_11_2),
5607 "24001/eos LB 2 buckets via: "
5608 "adj over 10.10.11.1, ",
5609 "adj-v4 over 10.10.11.2");
5610
5611 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5612 &pfx_24001_neos);
5613 FIB_TEST(fib_test_validate_entry(fei,
5614 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5615 1,
5616 &a_mpls_o_10_10_11_1),
5617 "24001/neos LB 1 buckets via: "
5618 "adj-mpls over 10.10.11.2");
5619
5620 /*
5621 * test that the pre-failover load-balance has been in-place
5622 * modified
5623 */
Neale Ranns948e00f2016-10-20 13:39:34 +01005624 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005625 fib_entry_contribute_forwarding(fei,
5626 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5627 &current);
5628
5629 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
5630 &current),
5631 "PIC-core LB inplace modified %U %U",
5632 format_dpo_id, &non_eos_1_1_1_1, 0,
5633 format_dpo_id, &current, 0);
5634
5635 dpo_reset(&non_eos_1_1_1_1);
5636 dpo_reset(&current);
5637
5638 /*
5639 * no-shut the link with the valid label
5640 */
5641 vnet_sw_interface_set_flags(vnet_get_main(),
5642 tm->hw[0]->sw_if_index,
5643 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5644
5645 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5646 FIB_TEST(fib_test_validate_entry(fei,
5647 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5648 16, // 3 choices spread over 16 buckets
5649 &l99_eos_o_10_10_10_1,
5650 &l99_eos_o_10_10_10_1,
5651 &l99_eos_o_10_10_10_1,
5652 &l99_eos_o_10_10_10_1,
5653 &l99_eos_o_10_10_10_1,
5654 &l99_eos_o_10_10_10_1,
5655 &a_o_10_10_11_1,
5656 &a_o_10_10_11_1,
5657 &a_o_10_10_11_1,
5658 &a_o_10_10_11_1,
5659 &a_o_10_10_11_1,
5660 &adj_o_10_10_11_2,
5661 &adj_o_10_10_11_2,
5662 &adj_o_10_10_11_2,
5663 &adj_o_10_10_11_2,
5664 &adj_o_10_10_11_2),
5665 "1.1.1.1/32 LB 16 buckets via: "
5666 "label 99 over 10.10.10.1, "
5667 "adj over 10.10.11.1",
5668 "adj-v4 over 10.10.11.2");
5669
5670
5671 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5672 &pfx_24001_eos);
5673 FIB_TEST(fib_test_validate_entry(fei,
5674 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5675 16, // 3 choices spread over 16 buckets
5676 &l99_eos_o_10_10_10_1,
5677 &l99_eos_o_10_10_10_1,
5678 &l99_eos_o_10_10_10_1,
5679 &l99_eos_o_10_10_10_1,
5680 &l99_eos_o_10_10_10_1,
5681 &l99_eos_o_10_10_10_1,
5682 &a_o_10_10_11_1,
5683 &a_o_10_10_11_1,
5684 &a_o_10_10_11_1,
5685 &a_o_10_10_11_1,
5686 &a_o_10_10_11_1,
5687 &adj_o_10_10_11_2,
5688 &adj_o_10_10_11_2,
5689 &adj_o_10_10_11_2,
5690 &adj_o_10_10_11_2,
5691 &adj_o_10_10_11_2),
5692 "24001/eos LB 16 buckets via: "
5693 "label 99 over 10.10.10.1, "
5694 "adj over 10.10.11.1",
5695 "adj-v4 over 10.10.11.2");
5696
5697 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5698 &pfx_24001_neos);
5699 FIB_TEST(fib_test_validate_entry(fei,
5700 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5701 2,
5702 &l99_neos_o_10_10_10_1,
5703 &a_mpls_o_10_10_11_1),
5704 "24001/neos LB 2 buckets via: "
5705 "label 99 over 10.10.10.1, "
5706 "adj-mpls over 10.10.11.2");
5707
5708 /*
5709 * remove the first path with the valid label
5710 */
5711 fib_table_entry_path_remove(fib_index,
5712 &pfx_1_1_1_1_s_32,
5713 FIB_SOURCE_API,
5714 FIB_PROTOCOL_IP4,
5715 &nh_10_10_10_1,
5716 tm->hw[0]->sw_if_index,
5717 ~0, // invalid fib index
5718 1,
5719 FIB_ROUTE_PATH_FLAG_NONE);
5720
5721 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5722 FIB_TEST(fib_test_validate_entry(fei,
5723 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5724 2,
5725 &a_o_10_10_11_1,
5726 &adj_o_10_10_11_2),
5727 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07005728 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005729 "adj-v4 over 10.10.11.2");
5730
5731 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5732 &pfx_24001_eos);
5733 FIB_TEST(fib_test_validate_entry(fei,
5734 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5735 2,
5736 &a_o_10_10_11_1,
5737 &adj_o_10_10_11_2),
5738 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07005739 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005740 "adj-v4 over 10.10.11.2");
5741
5742 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5743 &pfx_24001_neos);
5744
5745 FIB_TEST(fib_test_validate_entry(fei,
5746 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5747 1,
5748 &a_mpls_o_10_10_11_1),
5749 "24001/neos LB 1 buckets via: "
5750 "adj-mpls over 10.10.11.2");
5751
5752 /*
5753 * remove the other path with a valid label
5754 */
5755 fib_test_lb_bucket_t bucket_drop = {
5756 .type = FT_LB_SPECIAL,
5757 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00005758 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005759 },
5760 };
5761
5762 fib_table_entry_path_remove(fib_index,
5763 &pfx_1_1_1_1_s_32,
5764 FIB_SOURCE_API,
5765 FIB_PROTOCOL_IP4,
5766 &nh_10_10_11_1,
5767 tm->hw[1]->sw_if_index,
5768 ~0, // invalid fib index
5769 1,
5770 FIB_ROUTE_PATH_FLAG_NONE);
5771
5772 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5773 FIB_TEST(fib_test_validate_entry(fei,
5774 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5775 1,
5776 &adj_o_10_10_11_2),
5777 "1.1.1.1/32 LB 1 buckets via: "
5778 "adj over 10.10.11.2");
5779
5780 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5781 &pfx_24001_eos);
5782 FIB_TEST(fib_test_validate_entry(fei,
5783 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5784 1,
5785 &adj_o_10_10_11_2),
5786 "24001/eos LB 1 buckets via: "
5787 "adj over 10.10.11.2");
5788
5789 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5790 &pfx_24001_neos);
5791 FIB_TEST(fib_test_validate_entry(fei,
5792 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5793 1,
5794 &bucket_drop),
5795 "24001/eos LB 1 buckets via: DROP");
5796
5797 /*
5798 * add back the path with the valid label
5799 */
Neale Rannsad422ed2016-11-02 14:20:04 +00005800 l99 = NULL;
5801 vec_add1(l99, 99);
5802
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005803 fib_table_entry_path_add(fib_index,
5804 &pfx_1_1_1_1_s_32,
5805 FIB_SOURCE_API,
5806 FIB_ENTRY_FLAG_NONE,
5807 FIB_PROTOCOL_IP4,
5808 &nh_10_10_10_1,
5809 tm->hw[0]->sw_if_index,
5810 ~0, // invalid fib index
5811 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005812 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005813 FIB_ROUTE_PATH_FLAG_NONE);
5814
5815 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5816 FIB_TEST(fib_test_validate_entry(fei,
5817 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5818 2,
5819 &l99_eos_o_10_10_10_1,
5820 &adj_o_10_10_11_2),
5821 "1.1.1.1/32 LB 2 buckets via: "
5822 "label 99 over 10.10.10.1, "
5823 "adj over 10.10.11.2");
5824
5825 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5826 &pfx_24001_eos);
5827 FIB_TEST(fib_test_validate_entry(fei,
5828 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5829 2,
5830 &l99_eos_o_10_10_10_1,
5831 &adj_o_10_10_11_2),
5832 "24001/eos LB 2 buckets via: "
5833 "label 99 over 10.10.10.1, "
5834 "adj over 10.10.11.2");
5835
5836 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5837 &pfx_24001_neos);
5838 FIB_TEST(fib_test_validate_entry(fei,
5839 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5840 1,
5841 &l99_neos_o_10_10_10_1),
5842 "24001/neos LB 1 buckets via: "
5843 "label 99 over 10.10.10.1");
5844
5845 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07005846 * change the local label
5847 */
5848 fib_table_entry_local_label_add(fib_index,
5849 &pfx_1_1_1_1_s_32,
5850 25005);
5851
5852 fib_prefix_t pfx_25005_eos = {
5853 .fp_proto = FIB_PROTOCOL_MPLS,
5854 .fp_label = 25005,
5855 .fp_eos = MPLS_EOS,
5856 };
5857 fib_prefix_t pfx_25005_neos = {
5858 .fp_proto = FIB_PROTOCOL_MPLS,
5859 .fp_label = 25005,
5860 .fp_eos = MPLS_NON_EOS,
5861 };
5862
5863 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5864 fib_table_lookup(fib_index, &pfx_24001_eos)),
5865 "24001/eos removed after label change");
5866 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5867 fib_table_lookup(fib_index, &pfx_24001_neos)),
5868 "24001/eos removed after label change");
5869
5870 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5871 &pfx_25005_eos);
5872 FIB_TEST(fib_test_validate_entry(fei,
5873 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
5874 2,
5875 &l99_eos_o_10_10_10_1,
5876 &adj_o_10_10_11_2),
5877 "25005/eos LB 2 buckets via: "
5878 "label 99 over 10.10.10.1, "
5879 "adj over 10.10.11.2");
5880
5881 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
5882 &pfx_25005_neos);
5883 FIB_TEST(fib_test_validate_entry(fei,
5884 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5885 1,
5886 &l99_neos_o_10_10_10_1),
5887 "25005/neos LB 1 buckets via: "
5888 "label 99 over 10.10.10.1");
5889
5890 /*
5891 * remove the local label.
5892 * the check that the MPLS entries are gone is done by the fact the
5893 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005894 */
5895 fib_table_entry_local_label_remove(fib_index,
5896 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07005897 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005898
5899 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
5900 FIB_TEST(fib_test_validate_entry(fei,
5901 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5902 2,
5903 &l99_eos_o_10_10_10_1,
5904 &adj_o_10_10_11_2),
5905 "24001/eos LB 2 buckets via: "
5906 "label 99 over 10.10.10.1, "
5907 "adj over 10.10.11.2");
5908
5909 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5910 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
5911 "No more MPLS FIB entries => table removed");
5912
5913 /*
5914 * add another via-entry for the recursive
5915 */
5916 fib_prefix_t pfx_1_1_1_2_s_32 = {
5917 .fp_len = 32,
5918 .fp_proto = FIB_PROTOCOL_IP4,
5919 .fp_addr = {
5920 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
5921 },
5922 };
5923 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
5924 .type = FT_LB_LABEL_O_ADJ,
5925 .label_o_adj = {
5926 .adj = ai_mpls_10_10_10_1,
5927 .label = 101,
5928 .eos = MPLS_EOS,
5929 },
5930 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005931 mpls_label_t *l101 = NULL;
5932 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005933
5934 fei = fib_table_entry_update_one_path(fib_index,
5935 &pfx_1_1_1_2_s_32,
5936 FIB_SOURCE_API,
5937 FIB_ENTRY_FLAG_NONE,
5938 FIB_PROTOCOL_IP4,
5939 &nh_10_10_10_1,
5940 tm->hw[0]->sw_if_index,
5941 ~0, // invalid fib index
5942 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005943 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005944 FIB_ROUTE_PATH_FLAG_NONE);
5945
5946 FIB_TEST(fib_test_validate_entry(fei,
5947 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5948 1,
5949 &l101_eos_o_10_10_10_1),
5950 "1.1.1.2/32 LB 1 buckets via: "
5951 "label 101 over 10.10.10.1");
5952
Neale Ranns948e00f2016-10-20 13:39:34 +01005953 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005954 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5955 &pfx_1_1_1_1_s_32),
5956 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5957 &non_eos_1_1_1_1);
5958 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
5959 &pfx_1_1_1_2_s_32),
5960 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
5961 &non_eos_1_1_1_2);
5962
5963 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
5964 .type = FT_LB_LABEL_O_LB,
5965 .label_o_lb = {
5966 .lb = non_eos_1_1_1_2.dpoi_index,
5967 .label = 1601,
5968 .eos = MPLS_EOS,
5969 },
5970 };
Neale Rannsad422ed2016-11-02 14:20:04 +00005971 mpls_label_t *l1601 = NULL;
5972 vec_add1(l1601, 1601);
5973
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005974 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
5975
5976 fei = fib_table_entry_path_add(fib_index,
5977 &pfx_2_2_2_2_s_32,
5978 FIB_SOURCE_API,
5979 FIB_ENTRY_FLAG_NONE,
5980 FIB_PROTOCOL_IP4,
5981 &pfx_1_1_1_2_s_32.fp_addr,
5982 ~0,
5983 fib_index,
5984 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005985 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005986 FIB_ROUTE_PATH_FLAG_NONE);
5987
5988 FIB_TEST(fib_test_validate_entry(fei,
5989 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5990 2,
5991 &l1600_eos_o_1_1_1_1,
5992 &l1601_eos_o_1_1_1_2),
5993 "2.2.2.2/32 LB 2 buckets via: "
5994 "label 1600 via 1.1,1.1, "
5995 "label 16001 via 1.1.1.2");
5996
5997 /*
5998 * update the via-entry so it no longer has an imp-null path.
5999 * the LB for the recursive can use an imp-null
6000 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006001 l_imp_null = NULL;
6002 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6003
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006004 fei = fib_table_entry_update_one_path(fib_index,
6005 &pfx_1_1_1_2_s_32,
6006 FIB_SOURCE_API,
6007 FIB_ENTRY_FLAG_NONE,
6008 FIB_PROTOCOL_IP4,
6009 &nh_10_10_11_1,
6010 tm->hw[1]->sw_if_index,
6011 ~0, // invalid fib index
6012 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006013 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006014 FIB_ROUTE_PATH_FLAG_NONE);
6015
6016 FIB_TEST(fib_test_validate_entry(fei,
6017 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6018 1,
6019 &a_o_10_10_11_1),
6020 "1.1.1.2/32 LB 1 buckets via: "
6021 "adj 10.10.11.1");
6022
6023 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6024 FIB_TEST(fib_test_validate_entry(fei,
6025 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6026 2,
6027 &l1600_eos_o_1_1_1_1,
6028 &l1601_eos_o_1_1_1_2),
6029 "2.2.2.2/32 LB 2 buckets via: "
6030 "label 1600 via 1.1,1.1, "
6031 "label 16001 via 1.1.1.2");
6032
6033 /*
6034 * update the via-entry so it no longer has labelled paths.
6035 * the LB for the recursive should exclue this via form its LB
6036 */
6037 fei = fib_table_entry_update_one_path(fib_index,
6038 &pfx_1_1_1_2_s_32,
6039 FIB_SOURCE_API,
6040 FIB_ENTRY_FLAG_NONE,
6041 FIB_PROTOCOL_IP4,
6042 &nh_10_10_11_1,
6043 tm->hw[1]->sw_if_index,
6044 ~0, // invalid fib index
6045 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006046 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006047 FIB_ROUTE_PATH_FLAG_NONE);
6048
6049 FIB_TEST(fib_test_validate_entry(fei,
6050 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6051 1,
6052 &a_o_10_10_11_1),
6053 "1.1.1.2/32 LB 1 buckets via: "
6054 "adj 10.10.11.1");
6055
6056 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6057 FIB_TEST(fib_test_validate_entry(fei,
6058 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6059 1,
6060 &l1600_eos_o_1_1_1_1),
6061 "2.2.2.2/32 LB 1 buckets via: "
6062 "label 1600 via 1.1,1.1");
6063
6064 dpo_reset(&non_eos_1_1_1_1);
6065 dpo_reset(&non_eos_1_1_1_2);
6066
6067 /*
6068 * Add a recursive with no out-labels. We expect to use the IP of the via
6069 */
6070 fib_prefix_t pfx_2_2_2_3_s_32 = {
6071 .fp_len = 32,
6072 .fp_proto = FIB_PROTOCOL_IP4,
6073 .fp_addr = {
6074 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6075 },
6076 };
Neale Ranns948e00f2016-10-20 13:39:34 +01006077 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006078
6079 fib_table_entry_update_one_path(fib_index,
6080 &pfx_2_2_2_3_s_32,
6081 FIB_SOURCE_API,
6082 FIB_ENTRY_FLAG_NONE,
6083 FIB_PROTOCOL_IP4,
6084 &pfx_1_1_1_1_s_32.fp_addr,
6085 ~0,
6086 fib_index,
6087 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006088 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006089 FIB_ROUTE_PATH_FLAG_NONE);
6090
6091 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6092 &pfx_1_1_1_1_s_32),
6093 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6094 &ip_1_1_1_1);
6095
6096 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
6097 .type = FT_LB_O_LB,
6098 .lb = {
6099 .lb = ip_1_1_1_1.dpoi_index,
6100 },
6101 };
6102
6103 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
6104 FIB_TEST(fib_test_validate_entry(fei,
6105 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6106 1,
6107 &ip_o_1_1_1_1),
6108 "2.2.2.2.3/32 LB 1 buckets via: "
6109 "ip 1.1.1.1");
6110
6111 /*
6112 * Add a recursive with an imp-null out-label.
6113 * We expect to use the IP of the via
6114 */
6115 fib_prefix_t pfx_2_2_2_4_s_32 = {
6116 .fp_len = 32,
6117 .fp_proto = FIB_PROTOCOL_IP4,
6118 .fp_addr = {
6119 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
6120 },
6121 };
6122
6123 fib_table_entry_update_one_path(fib_index,
6124 &pfx_2_2_2_4_s_32,
6125 FIB_SOURCE_API,
6126 FIB_ENTRY_FLAG_NONE,
6127 FIB_PROTOCOL_IP4,
6128 &pfx_1_1_1_1_s_32.fp_addr,
6129 ~0,
6130 fib_index,
6131 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006132 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006133 FIB_ROUTE_PATH_FLAG_NONE);
6134
6135 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
6136 FIB_TEST(fib_test_validate_entry(fei,
6137 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6138 1,
6139 &ip_o_1_1_1_1),
6140 "2.2.2.2.4/32 LB 1 buckets via: "
6141 "ip 1.1.1.1");
6142
6143 dpo_reset(&ip_1_1_1_1);
6144
6145 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00006146 * Create an entry with a deep label stack
6147 */
6148 fib_prefix_t pfx_2_2_5_5_s_32 = {
6149 .fp_len = 32,
6150 .fp_proto = FIB_PROTOCOL_IP4,
6151 .fp_addr = {
6152 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
6153 },
6154 };
6155 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
6156 .type = FT_LB_LABEL_STACK_O_ADJ,
6157 .label_stack_o_adj = {
6158 .adj = ai_mpls_10_10_11_1,
6159 .label_stack_size = 8,
6160 .label_stack = {
6161 200, 201, 202, 203, 204, 205, 206, 207
6162 },
6163 .eos = MPLS_EOS,
6164 },
6165 };
6166 mpls_label_t *label_stack = NULL;
6167 vec_validate(label_stack, 7);
6168 for (ii = 0; ii < 8; ii++)
6169 {
6170 label_stack[ii] = ii + 200;
6171 }
6172
6173 fei = fib_table_entry_update_one_path(fib_index,
6174 &pfx_2_2_5_5_s_32,
6175 FIB_SOURCE_API,
6176 FIB_ENTRY_FLAG_NONE,
6177 FIB_PROTOCOL_IP4,
6178 &nh_10_10_11_1,
6179 tm->hw[1]->sw_if_index,
6180 ~0, // invalid fib index
6181 1,
6182 label_stack,
6183 FIB_ROUTE_PATH_FLAG_NONE);
6184
6185 FIB_TEST(fib_test_validate_entry(fei,
6186 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6187 1,
6188 &ls_eos_o_10_10_10_1),
6189 "2.2.5.5/32 LB 1 buckets via: "
6190 "adj 10.10.11.1");
6191 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
6192
6193 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006194 * cleanup
6195 */
6196 fib_table_entry_delete(fib_index,
6197 &pfx_1_1_1_2_s_32,
6198 FIB_SOURCE_API);
6199
6200 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6201 FIB_TEST(fib_test_validate_entry(fei,
6202 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6203 1,
6204 &l1600_eos_o_1_1_1_1),
6205 "2.2.2.2/32 LB 1 buckets via: "
6206 "label 1600 via 1.1,1.1");
6207
6208 fib_table_entry_delete(fib_index,
6209 &pfx_1_1_1_1_s_32,
6210 FIB_SOURCE_API);
6211
6212 FIB_TEST(fib_test_validate_entry(fei,
6213 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6214 1,
6215 &bucket_drop),
6216 "2.2.2.2/32 LB 1 buckets via: DROP");
6217
6218 fib_table_entry_delete(fib_index,
6219 &pfx_2_2_2_2_s_32,
6220 FIB_SOURCE_API);
6221 fib_table_entry_delete(fib_index,
6222 &pfx_2_2_2_3_s_32,
6223 FIB_SOURCE_API);
6224 fib_table_entry_delete(fib_index,
6225 &pfx_2_2_2_4_s_32,
6226 FIB_SOURCE_API);
6227
6228 adj_unlock(ai_mpls_10_10_10_1);
6229 adj_unlock(ai_mpls_10_10_11_2);
6230 adj_unlock(ai_v4_10_10_11_1);
6231 adj_unlock(ai_v4_10_10_11_2);
6232 adj_unlock(ai_mpls_10_10_11_1);
6233
6234 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6235 adj_nbr_db_size());
6236
6237 local0_pfx.fp_len = 32;
6238 fib_table_entry_delete(fib_index,
6239 &local0_pfx,
6240 FIB_SOURCE_INTERFACE);
6241 local0_pfx.fp_len = 24;
6242 fib_table_entry_delete(fib_index,
6243 &local0_pfx,
6244 FIB_SOURCE_INTERFACE);
6245 local1_pfx.fp_len = 32;
6246 fib_table_entry_delete(fib_index,
6247 &local1_pfx,
6248 FIB_SOURCE_INTERFACE);
6249 local1_pfx.fp_len = 24;
6250 fib_table_entry_delete(fib_index,
6251 &local1_pfx,
6252 FIB_SOURCE_INTERFACE);
6253
6254 /*
6255 * +1 for the drop LB in the MPLS tables.
6256 */
6257 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
6258 "Load-balance resources freed %d of %d",
6259 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006260
6261 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006262}
6263
6264#define N_TEST_CHILDREN 4
6265#define PARENT_INDEX 0
6266
6267typedef struct fib_node_test_t_
6268{
6269 fib_node_t node;
6270 u32 sibling;
6271 u32 index;
6272 fib_node_back_walk_ctx_t *ctxs;
6273 u32 destroyed;
6274} fib_node_test_t;
6275
6276static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
6277
6278#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
6279
6280#define FOR_EACH_TEST_CHILD(_tc) \
6281 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
6282 ii < N_TEST_CHILDREN+1; \
6283 ii++, (_tc) = &fib_test_nodes[ii])
6284
6285static fib_node_t *
6286fib_test_child_get_node (fib_node_index_t index)
6287{
6288 return (&fib_test_nodes[index].node);
6289}
6290
6291static int fib_test_walk_spawns_walks;
6292
6293static fib_node_back_walk_rc_t
6294fib_test_child_back_walk_notify (fib_node_t *node,
6295 fib_node_back_walk_ctx_t *ctx)
6296{
6297 fib_node_test_t *tc = (fib_node_test_t*) node;
6298
6299 vec_add1(tc->ctxs, *ctx);
6300
6301 if (1 == fib_test_walk_spawns_walks)
6302 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
6303 if (2 == fib_test_walk_spawns_walks)
6304 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
6305 FIB_WALK_PRIORITY_HIGH, ctx);
6306
6307 return (FIB_NODE_BACK_WALK_CONTINUE);
6308}
6309
6310static void
6311fib_test_child_last_lock_gone (fib_node_t *node)
6312{
6313 fib_node_test_t *tc = (fib_node_test_t *)node;
6314
6315 tc->destroyed = 1;
6316}
6317
6318/**
6319 * The FIB walk's graph node virtual function table
6320 */
6321static const fib_node_vft_t fib_test_child_vft = {
6322 .fnv_get = fib_test_child_get_node,
6323 .fnv_last_lock = fib_test_child_last_lock_gone,
6324 .fnv_back_walk = fib_test_child_back_walk_notify,
6325};
6326
6327/*
6328 * the function (that should have been static but isn't so I can do this)
6329 * that processes the walk from the async queue,
6330 */
6331f64 fib_walk_process_queues(vlib_main_t * vm,
6332 const f64 quota);
6333u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
6334
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006335static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006336fib_test_walk (void)
6337{
6338 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
6339 fib_node_test_t *tc;
6340 vlib_main_t *vm;
6341 u32 ii;
6342
6343 vm = vlib_get_main();
6344 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
6345
6346 /*
6347 * init a fake node on which we will add children
6348 */
6349 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
6350 FIB_NODE_TYPE_TEST);
6351
6352 FOR_EACH_TEST_CHILD(tc)
6353 {
6354 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
6355 fib_node_lock(&tc->node);
6356 tc->ctxs = NULL;
6357 tc->index = ii;
6358 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
6359 PARENT_INDEX,
6360 FIB_NODE_TYPE_TEST, ii);
6361 }
6362
6363 /*
6364 * enqueue a walk across the parents children.
6365 */
Neale Ranns450cd302016-11-09 17:49:42 +00006366 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006367
6368 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6369 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6370 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6371 "Parent has %d children pre-walk",
6372 fib_node_list_get_size(PARENT()->fn_children));
6373
6374 /*
6375 * give the walk a large amount of time so it gets to the end
6376 */
6377 fib_walk_process_queues(vm, 1);
6378
6379 FOR_EACH_TEST_CHILD(tc)
6380 {
6381 FIB_TEST(1 == vec_len(tc->ctxs),
6382 "%d child visitsed %d times",
6383 ii, vec_len(tc->ctxs));
6384 vec_free(tc->ctxs);
6385 }
6386 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6387 "Queue is empty post walk");
6388 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6389 "Parent has %d children post walk",
6390 fib_node_list_get_size(PARENT()->fn_children));
6391
6392 /*
6393 * walk again. should be no increase in the number of visits, since
6394 * the walk will have terminated.
6395 */
6396 fib_walk_process_queues(vm, 1);
6397
6398 FOR_EACH_TEST_CHILD(tc)
6399 {
6400 FIB_TEST(0 == vec_len(tc->ctxs),
6401 "%d child visitsed %d times",
6402 ii, vec_len(tc->ctxs));
6403 }
6404
6405 /*
6406 * schedule a low and hig priority walk. expect the high to be performed
6407 * before the low.
6408 * schedule the high prio walk first so that it is further from the head
6409 * of the dependency list. that way it won't merge with the low one.
6410 */
6411 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6412 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6413
6414 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6415 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6416 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6417 FIB_WALK_PRIORITY_LOW, &low_ctx);
6418
6419 fib_walk_process_queues(vm, 1);
6420
6421 FOR_EACH_TEST_CHILD(tc)
6422 {
6423 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6424 "%d child visitsed by high prio walk", ii);
6425 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6426 "%d child visitsed by low prio walk", ii);
6427 vec_free(tc->ctxs);
6428 }
6429 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6430 "Queue is empty post prio walk");
6431 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6432 "Parent has %d children post prio walk",
6433 fib_node_list_get_size(PARENT()->fn_children));
6434
6435 /*
6436 * schedule 2 walks of the same priority that can be megred.
6437 * expect that each child is thus visited only once.
6438 */
6439 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6440 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6441
6442 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6443 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6444 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6445 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6446
6447 fib_walk_process_queues(vm, 1);
6448
6449 FOR_EACH_TEST_CHILD(tc)
6450 {
6451 FIB_TEST(1 == vec_len(tc->ctxs),
6452 "%d child visitsed %d times during merge walk",
6453 ii, vec_len(tc->ctxs));
6454 vec_free(tc->ctxs);
6455 }
6456 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6457 "Queue is empty post merge walk");
6458 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6459 "Parent has %d children post merge walk",
6460 fib_node_list_get_size(PARENT()->fn_children));
6461
6462 /*
6463 * schedule 2 walks of the same priority that cannot be megred.
6464 * expect that each child is thus visited twice and in the order
6465 * in which the walks were scheduled.
6466 */
6467 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
6468 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
6469
6470 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6471 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6472 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6473 FIB_WALK_PRIORITY_HIGH, &low_ctx);
6474
6475 fib_walk_process_queues(vm, 1);
6476
6477 FOR_EACH_TEST_CHILD(tc)
6478 {
6479 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
6480 "%d child visitsed by high prio walk", ii);
6481 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
6482 "%d child visitsed by low prio walk", ii);
6483 vec_free(tc->ctxs);
6484 }
6485 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6486 "Queue is empty post no-merge walk");
6487 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6488 "Parent has %d children post no-merge walk",
6489 fib_node_list_get_size(PARENT()->fn_children));
6490
6491 /*
6492 * schedule a walk that makes one one child progress.
6493 * we do this by giving the queue draining process zero
6494 * time quanta. it's a do..while loop, so it does something.
6495 */
Neale Ranns450cd302016-11-09 17:49:42 +00006496 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006497
6498 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6499 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6500 fib_walk_process_queues(vm, 0);
6501
6502 FOR_EACH_TEST_CHILD(tc)
6503 {
6504 if (ii == N_TEST_CHILDREN)
6505 {
6506 FIB_TEST(1 == vec_len(tc->ctxs),
6507 "%d child visitsed %d times in zero quanta walk",
6508 ii, vec_len(tc->ctxs));
6509 }
6510 else
6511 {
6512 FIB_TEST(0 == vec_len(tc->ctxs),
6513 "%d child visitsed %d times in 0 quanta walk",
6514 ii, vec_len(tc->ctxs));
6515 }
6516 }
6517 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6518 "Queue is not empty post zero quanta walk");
6519 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6520 "Parent has %d children post zero qunta walk",
6521 fib_node_list_get_size(PARENT()->fn_children));
6522
6523 /*
6524 * another one step
6525 */
6526 fib_walk_process_queues(vm, 0);
6527
6528 FOR_EACH_TEST_CHILD(tc)
6529 {
6530 if (ii >= N_TEST_CHILDREN-1)
6531 {
6532 FIB_TEST(1 == vec_len(tc->ctxs),
6533 "%d child visitsed %d times in 2nd zero quanta walk",
6534 ii, vec_len(tc->ctxs));
6535 }
6536 else
6537 {
6538 FIB_TEST(0 == vec_len(tc->ctxs),
6539 "%d child visitsed %d times in 2nd 0 quanta walk",
6540 ii, vec_len(tc->ctxs));
6541 }
6542 }
6543 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6544 "Queue is not empty post zero quanta walk");
6545 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
6546 "Parent has %d children post zero qunta walk",
6547 fib_node_list_get_size(PARENT()->fn_children));
6548
6549 /*
6550 * schedule another walk that will catch-up and merge.
6551 */
6552 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6553 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6554 fib_walk_process_queues(vm, 1);
6555
6556 FOR_EACH_TEST_CHILD(tc)
6557 {
6558 if (ii >= N_TEST_CHILDREN-1)
6559 {
6560 FIB_TEST(2 == vec_len(tc->ctxs),
6561 "%d child visitsed %d times in 2nd zero quanta merge walk",
6562 ii, vec_len(tc->ctxs));
6563 vec_free(tc->ctxs);
6564 }
6565 else
6566 {
6567 FIB_TEST(1 == vec_len(tc->ctxs),
6568 "%d child visitsed %d times in 2nd 0 quanta merge walk",
6569 ii, vec_len(tc->ctxs));
6570 vec_free(tc->ctxs);
6571 }
6572 }
6573 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6574 "Queue is not empty post 2nd zero quanta merge walk");
6575 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6576 "Parent has %d children post 2nd zero qunta merge walk",
6577 fib_node_list_get_size(PARENT()->fn_children));
6578
6579 /*
6580 * park a async walk in the middle of the list, then have an sync walk catch
6581 * it. same expectations as async catches async.
6582 */
Neale Ranns450cd302016-11-09 17:49:42 +00006583 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006584
6585 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6586 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6587
6588 fib_walk_process_queues(vm, 0);
6589 fib_walk_process_queues(vm, 0);
6590
6591 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6592
6593 FOR_EACH_TEST_CHILD(tc)
6594 {
6595 if (ii >= N_TEST_CHILDREN-1)
6596 {
6597 FIB_TEST(2 == vec_len(tc->ctxs),
6598 "%d child visitsed %d times in sync catches async walk",
6599 ii, vec_len(tc->ctxs));
6600 vec_free(tc->ctxs);
6601 }
6602 else
6603 {
6604 FIB_TEST(1 == vec_len(tc->ctxs),
6605 "%d child visitsed %d times in sync catches async walk",
6606 ii, vec_len(tc->ctxs));
6607 vec_free(tc->ctxs);
6608 }
6609 }
6610 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
6611 "Queue is not empty post 2nd zero quanta merge walk");
6612 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6613 "Parent has %d children post 2nd zero qunta merge walk",
6614 fib_node_list_get_size(PARENT()->fn_children));
6615
6616 /*
6617 * make the parent a child of one of its children, thus inducing a routing loop.
6618 */
6619 fib_test_nodes[PARENT_INDEX].sibling =
6620 fib_node_child_add(FIB_NODE_TYPE_TEST,
6621 1, // the first child
6622 FIB_NODE_TYPE_TEST,
6623 PARENT_INDEX);
6624
6625 /*
6626 * execute a sync walk from the parent. each child visited spawns more sync
6627 * walks. we expect the walk to terminate.
6628 */
6629 fib_test_walk_spawns_walks = 1;
6630
6631 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
6632
6633 FOR_EACH_TEST_CHILD(tc)
6634 {
6635 /*
6636 * child 1 - which is last in the list - has the loop.
6637 * the other children a re thus visitsed first. the we meet
6638 * child 1. we go round the loop again, visting the other children.
6639 * then we meet the walk in the dep list and bail. child 1 is not visitsed
6640 * again.
6641 */
6642 if (1 == ii)
6643 {
6644 FIB_TEST(1 == vec_len(tc->ctxs),
6645 "child %d visitsed %d times during looped sync walk",
6646 ii, vec_len(tc->ctxs));
6647 }
6648 else
6649 {
6650 FIB_TEST(2 == vec_len(tc->ctxs),
6651 "child %d visitsed %d times during looped sync walk",
6652 ii, vec_len(tc->ctxs));
6653 }
6654 vec_free(tc->ctxs);
6655 }
6656 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
6657 "Parent has %d children post sync loop walk",
6658 fib_node_list_get_size(PARENT()->fn_children));
6659
6660 /*
6661 * the walk doesn't reach the max depth because the infra knows that sync
6662 * meets sync implies a loop and bails early.
6663 */
6664 FIB_TEST(high_ctx.fnbw_depth == 9,
6665 "Walk context depth %d post sync loop walk",
6666 high_ctx.fnbw_depth);
6667
6668 /*
6669 * execute an async walk of the graph loop, with each child spawns sync walks
6670 */
6671 high_ctx.fnbw_depth = 0;
6672 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6673 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6674
6675 fib_walk_process_queues(vm, 1);
6676
6677 FOR_EACH_TEST_CHILD(tc)
6678 {
6679 /*
6680 * we don't really care how many times the children are visisted, as long as
6681 * it is more than once.
6682 */
6683 FIB_TEST(1 <= vec_len(tc->ctxs),
6684 "child %d visitsed %d times during looped aync spawns sync walk",
6685 ii, vec_len(tc->ctxs));
6686 vec_free(tc->ctxs);
6687 }
6688
6689 /*
6690 * execute an async walk of the graph loop, with each child spawns async walks
6691 */
6692 fib_test_walk_spawns_walks = 2;
6693 high_ctx.fnbw_depth = 0;
6694 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6695 FIB_WALK_PRIORITY_HIGH, &high_ctx);
6696
6697 fib_walk_process_queues(vm, 1);
6698
6699 FOR_EACH_TEST_CHILD(tc)
6700 {
6701 /*
6702 * we don't really care how many times the children are visisted, as long as
6703 * it is more than once.
6704 */
6705 FIB_TEST(1 <= vec_len(tc->ctxs),
6706 "child %d visitsed %d times during looped async spawns async walk",
6707 ii, vec_len(tc->ctxs));
6708 vec_free(tc->ctxs);
6709 }
6710
6711
6712 fib_node_child_remove(FIB_NODE_TYPE_TEST,
6713 1, // the first child
6714 fib_test_nodes[PARENT_INDEX].sibling);
6715
6716 /*
6717 * cleanup
6718 */
6719 FOR_EACH_TEST_CHILD(tc)
6720 {
6721 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
6722 tc->sibling);
6723 fib_node_deinit(&tc->node);
6724 fib_node_unlock(&tc->node);
6725 }
6726 fib_node_deinit(PARENT());
6727
6728 /*
6729 * The parent will be destroyed when the last lock on it goes.
6730 * this test ensures all the walk objects are unlocking it.
6731 */
6732 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
6733 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006734
6735 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006736}
6737
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006738static int
6739lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006740{
6741 const mpls_label_t deag_label = 50;
6742 const u32 lfib_index = 0;
6743 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01006744 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006745 const dpo_id_t *dpo1;
6746 fib_node_index_t lfe;
6747 lookup_dpo_t *lkd;
6748 test_main_t *tm;
6749 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00006750 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006751
6752 tm = &test_main;
6753 lb_count = pool_elts(load_balance_pool);
6754
6755 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6756 adj_nbr_db_size());
6757
6758 /*
6759 * MPLS enable an interface so we get the MPLS table created
6760 */
6761 mpls_sw_interface_enable_disable(&mpls_main,
6762 tm->hw[0]->sw_if_index,
6763 1);
6764
Neale Rannsad422ed2016-11-02 14:20:04 +00006765 ip46_address_t nh_10_10_10_1 = {
6766 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6767 };
6768 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
6769 VNET_LINK_MPLS,
6770 &nh_10_10_10_1,
6771 tm->hw[0]->sw_if_index);
6772
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006773 /*
6774 * Test the specials stack properly.
6775 */
6776 fib_prefix_t exp_null_v6_pfx = {
6777 .fp_proto = FIB_PROTOCOL_MPLS,
6778 .fp_eos = MPLS_EOS,
6779 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6780 .fp_payload_proto = DPO_PROTO_IP6,
6781 };
6782 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
6783 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
6784 "%U/%U present",
6785 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
6786 format_mpls_eos_bit, MPLS_EOS);
6787 fib_entry_contribute_forwarding(lfe,
6788 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6789 &dpo);
6790 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6791 lkd = lookup_dpo_get(dpo1->dpoi_index);
6792
6793 FIB_TEST((fib_index == lkd->lkd_fib_index),
6794 "%U/%U is deag in %d %U",
6795 format_mpls_unicast_label, deag_label,
6796 format_mpls_eos_bit, MPLS_EOS,
6797 lkd->lkd_fib_index,
6798 format_dpo_id, &dpo, 0);
6799 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6800 "%U/%U is dst deag",
6801 format_mpls_unicast_label, deag_label,
6802 format_mpls_eos_bit, MPLS_EOS);
6803 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
6804 "%U/%U is lookup in interface's table",
6805 format_mpls_unicast_label, deag_label,
6806 format_mpls_eos_bit, MPLS_EOS);
6807 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
6808 "%U/%U is %U dst deag",
6809 format_mpls_unicast_label, deag_label,
6810 format_mpls_eos_bit, MPLS_EOS,
6811 format_dpo_proto, lkd->lkd_proto);
6812
6813
6814 /*
6815 * A route deag route for EOS
6816 */
6817 fib_prefix_t pfx = {
6818 .fp_proto = FIB_PROTOCOL_MPLS,
6819 .fp_eos = MPLS_EOS,
6820 .fp_label = deag_label,
6821 .fp_payload_proto = DPO_PROTO_IP4,
6822 };
6823 lfe = fib_table_entry_path_add(lfib_index,
6824 &pfx,
6825 FIB_SOURCE_CLI,
6826 FIB_ENTRY_FLAG_NONE,
6827 FIB_PROTOCOL_IP4,
6828 &zero_addr,
6829 ~0,
6830 fib_index,
6831 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006832 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006833 FIB_ROUTE_PATH_FLAG_NONE);
6834
6835 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6836 "%U/%U present",
6837 format_mpls_unicast_label, deag_label,
6838 format_mpls_eos_bit, MPLS_EOS);
6839
6840 fib_entry_contribute_forwarding(lfe,
6841 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6842 &dpo);
6843 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6844 lkd = lookup_dpo_get(dpo1->dpoi_index);
6845
6846 FIB_TEST((fib_index == lkd->lkd_fib_index),
6847 "%U/%U is deag in %d %U",
6848 format_mpls_unicast_label, deag_label,
6849 format_mpls_eos_bit, MPLS_EOS,
6850 lkd->lkd_fib_index,
6851 format_dpo_id, &dpo, 0);
6852 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6853 "%U/%U is dst deag",
6854 format_mpls_unicast_label, deag_label,
6855 format_mpls_eos_bit, MPLS_EOS);
6856 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
6857 "%U/%U is %U dst deag",
6858 format_mpls_unicast_label, deag_label,
6859 format_mpls_eos_bit, MPLS_EOS,
6860 format_dpo_proto, lkd->lkd_proto);
6861
6862 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6863
6864 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6865 &pfx)),
6866 "%U/%U not present",
6867 format_mpls_unicast_label, deag_label,
6868 format_mpls_eos_bit, MPLS_EOS);
6869
6870 /*
6871 * A route deag route for non-EOS
6872 */
6873 pfx.fp_eos = MPLS_NON_EOS;
6874 lfe = fib_table_entry_path_add(lfib_index,
6875 &pfx,
6876 FIB_SOURCE_CLI,
6877 FIB_ENTRY_FLAG_NONE,
6878 FIB_PROTOCOL_IP4,
6879 &zero_addr,
6880 ~0,
6881 lfib_index,
6882 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006883 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006884 FIB_ROUTE_PATH_FLAG_NONE);
6885
6886 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
6887 "%U/%U present",
6888 format_mpls_unicast_label, deag_label,
6889 format_mpls_eos_bit, MPLS_NON_EOS);
6890
6891 fib_entry_contribute_forwarding(lfe,
6892 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6893 &dpo);
6894 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
6895 lkd = lookup_dpo_get(dpo1->dpoi_index);
6896
6897 FIB_TEST((fib_index == lkd->lkd_fib_index),
6898 "%U/%U is deag in %d %U",
6899 format_mpls_unicast_label, deag_label,
6900 format_mpls_eos_bit, MPLS_NON_EOS,
6901 lkd->lkd_fib_index,
6902 format_dpo_id, &dpo, 0);
6903 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
6904 "%U/%U is dst deag",
6905 format_mpls_unicast_label, deag_label,
6906 format_mpls_eos_bit, MPLS_NON_EOS);
6907
6908 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
6909 "%U/%U is %U dst deag",
6910 format_mpls_unicast_label, deag_label,
6911 format_mpls_eos_bit, MPLS_NON_EOS,
6912 format_dpo_proto, lkd->lkd_proto);
6913
6914 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
6915
6916 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
6917 &pfx)),
6918 "%U/%U not present",
6919 format_mpls_unicast_label, deag_label,
6920 format_mpls_eos_bit, MPLS_EOS);
6921
Neale Rannsad422ed2016-11-02 14:20:04 +00006922 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006923
Neale Rannsad422ed2016-11-02 14:20:04 +00006924 /*
6925 * An MPLS x-connect
6926 */
6927 fib_prefix_t pfx_1200 = {
6928 .fp_len = 21,
6929 .fp_proto = FIB_PROTOCOL_MPLS,
6930 .fp_label = 1200,
6931 .fp_eos = MPLS_NON_EOS,
6932 };
6933 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
6934 .type = FT_LB_LABEL_STACK_O_ADJ,
6935 .label_stack_o_adj = {
6936 .adj = ai_mpls_10_10_10_1,
6937 .label_stack_size = 4,
6938 .label_stack = {
6939 200, 300, 400, 500,
6940 },
6941 .eos = MPLS_NON_EOS,
6942 },
6943 };
6944 dpo_id_t neos_1200 = DPO_INVALID;
6945 dpo_id_t ip_1200 = DPO_INVALID;
6946 mpls_label_t *l200 = NULL;
6947 vec_add1(l200, 200);
6948 vec_add1(l200, 300);
6949 vec_add1(l200, 400);
6950 vec_add1(l200, 500);
6951
6952 lfe = fib_table_entry_update_one_path(fib_index,
6953 &pfx_1200,
6954 FIB_SOURCE_API,
6955 FIB_ENTRY_FLAG_NONE,
6956 FIB_PROTOCOL_IP4,
6957 &nh_10_10_10_1,
6958 tm->hw[0]->sw_if_index,
6959 ~0, // invalid fib index
6960 1,
6961 l200,
6962 FIB_ROUTE_PATH_FLAG_NONE);
6963
6964 FIB_TEST(fib_test_validate_entry(lfe,
6965 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6966 1,
6967 &neos_o_10_10_10_1),
6968 "1200/0 LB 1 buckets via: "
6969 "adj 10.10.11.1");
6970
6971 /*
6972 * A recursive route via the MPLS x-connect
6973 */
6974 fib_prefix_t pfx_2_2_2_3_s_32 = {
6975 .fp_len = 32,
6976 .fp_proto = FIB_PROTOCOL_IP4,
6977 .fp_addr = {
6978 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
6979 },
6980 };
6981 fib_route_path_t *rpaths = NULL, rpath = {
6982 .frp_proto = FIB_PROTOCOL_MPLS,
6983 .frp_local_label = 1200,
6984 .frp_sw_if_index = ~0, // recurive
6985 .frp_fib_index = 0, // Default MPLS fib
6986 .frp_weight = 1,
6987 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
6988 .frp_label_stack = NULL,
6989 };
6990 vec_add1(rpaths, rpath);
6991
6992 fib_table_entry_path_add2(fib_index,
6993 &pfx_2_2_2_3_s_32,
6994 FIB_SOURCE_API,
6995 FIB_ENTRY_FLAG_NONE,
6996 rpaths);
6997
6998 /*
6999 * A labelled recursive route via the MPLS x-connect
7000 */
7001 fib_prefix_t pfx_2_2_2_4_s_32 = {
7002 .fp_len = 32,
7003 .fp_proto = FIB_PROTOCOL_IP4,
7004 .fp_addr = {
7005 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7006 },
7007 };
7008 mpls_label_t *l999 = NULL;
7009 vec_add1(l999, 999);
7010 rpaths[0].frp_label_stack = l999,
7011
7012 fib_table_entry_path_add2(fib_index,
7013 &pfx_2_2_2_4_s_32,
7014 FIB_SOURCE_API,
7015 FIB_ENTRY_FLAG_NONE,
7016 rpaths);
7017
7018 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7019 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7020 &ip_1200);
7021 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7022 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
7023 &neos_1200);
7024
7025 fib_test_lb_bucket_t ip_o_1200 = {
7026 .type = FT_LB_O_LB,
7027 .lb = {
7028 .lb = ip_1200.dpoi_index,
7029 },
7030 };
7031 fib_test_lb_bucket_t mpls_o_1200 = {
7032 .type = FT_LB_LABEL_O_LB,
7033 .label_o_lb = {
7034 .lb = neos_1200.dpoi_index,
7035 .label = 999,
7036 .eos = MPLS_EOS,
7037 },
7038 };
7039
7040 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7041 FIB_TEST(fib_test_validate_entry(lfe,
7042 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7043 1,
7044 &ip_o_1200),
7045 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
7046 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7047 FIB_TEST(fib_test_validate_entry(lfe,
7048 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7049 1,
7050 &mpls_o_1200),
7051 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
7052
7053 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
7054 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
7055 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7056
7057 dpo_reset(&neos_1200);
7058 dpo_reset(&ip_1200);
7059
7060 /*
7061 * A recursive via a label that does not exist
7062 */
7063 fib_test_lb_bucket_t bucket_drop = {
7064 .type = FT_LB_SPECIAL,
7065 .special = {
7066 .adj = DPO_PROTO_MPLS,
7067 },
7068 };
7069
7070 rpaths[0].frp_label_stack = NULL;
7071 lfe = fib_table_entry_path_add2(fib_index,
7072 &pfx_2_2_2_4_s_32,
7073 FIB_SOURCE_API,
7074 FIB_ENTRY_FLAG_NONE,
7075 rpaths);
7076
7077 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
7078 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7079 &ip_1200);
7080 ip_o_1200.lb.lb = ip_1200.dpoi_index;
7081
7082 FIB_TEST(fib_test_validate_entry(lfe,
7083 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7084 1,
7085 &ip_o_1200),
7086 "2.2.2.2.4/32 LB 1 buckets via: label 1200 EOS");
7087 lfe = fib_table_lookup(fib_index, &pfx_1200);
7088 FIB_TEST(fib_test_validate_entry(lfe,
7089 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7090 1,
7091 &bucket_drop),
7092 "2.2.2.4/32 LB 1 buckets via: ip4-DROP");
7093
7094 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
7095
7096 dpo_reset(&ip_1200);
7097
7098 /*
7099 * cleanup
7100 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007101 mpls_sw_interface_enable_disable(&mpls_main,
7102 tm->hw[0]->sw_if_index,
7103 0);
7104
Neale Rannsad422ed2016-11-02 14:20:04 +00007105 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007106 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00007107 lb_count, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007108
7109 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007110}
7111
7112static clib_error_t *
7113fib_test (vlib_main_t * vm,
7114 unformat_input_t * input,
7115 vlib_cli_command_t * cmd_arg)
7116{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007117 int res;
7118
7119 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007120 fib_test_mk_intf(4);
7121
7122 if (unformat (input, "ip"))
7123 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007124 res += fib_test_v4();
7125 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007126 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007127 else if (unformat (input, "label"))
7128 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007129 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007130 }
7131 else if (unformat (input, "ae"))
7132 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007133 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007134 }
Neale Rannsad422ed2016-11-02 14:20:04 +00007135 else if (unformat (input, "lfib"))
7136 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007137 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00007138 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007139 else if (unformat (input, "walk"))
7140 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007141 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007142 }
7143 else
7144 {
7145 /*
7146 * These walk UT aren't run as part of the full suite, since the
7147 * fib-walk process must be disabled in order for the tests to work
7148 *
7149 * fib_test_walk();
7150 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007151 res += fib_test_v4();
7152 res += fib_test_v6();
7153 res += fib_test_ae();
7154 res += fib_test_label();
7155 res += lfib_test();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007156 }
7157
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007158 if (res)
7159 {
7160 return clib_error_return(0, "FIB Unit Test Failed");
7161 }
7162 else
7163 {
7164 return (NULL);
7165 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007166}
7167
7168VLIB_CLI_COMMAND (test_fib_command, static) = {
7169 .path = "test fib",
7170 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
7171 .function = fib_test,
7172};
7173
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007174clib_error_t *
7175fib_test_init (vlib_main_t *vm)
7176{
7177 return 0;
7178}
7179
7180VLIB_INIT_FUNCTION (fib_test_init);