blob: 2658eb2781153ce3ee5ccec03e2760c41108432d [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
Neale Rannsd792d9c2017-10-21 10:53:20 -070016#include <vnet/fib/fib_test.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010017#include <vnet/fib/ip6_fib.h>
18#include <vnet/fib/ip4_fib.h>
19#include <vnet/fib/mpls_fib.h>
20#include <vnet/adj/adj.h>
21#include <vnet/dpo/load_balance.h>
22#include <vnet/dpo/load_balance_map.h>
23#include <vnet/dpo/mpls_label_dpo.h>
24#include <vnet/dpo/lookup_dpo.h>
25#include <vnet/dpo/drop_dpo.h>
26#include <vnet/dpo/receive_dpo.h>
Neale Ranns948e00f2016-10-20 13:39:34 +010027#include <vnet/dpo/ip_null_dpo.h>
Neale Ranns88fc83e2017-04-05 08:11:14 -070028#include <vnet/bfd/bfd_main.h>
Neale Ranns43161a82017-08-12 02:12:00 -070029#include <vnet/dpo/interface_rx_dpo.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080030#include <vnet/dpo/replicate_dpo.h>
Neale Ranns6f631152017-10-03 08:20:21 -070031#include <vnet/dpo/l2_bridge_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010032
33#include <vnet/mpls/mpls.h>
34
Neale Ranns6f631152017-10-03 08:20:21 -070035#include <vnet/fib/fib_test.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010036#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000037#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010038#include <vnet/fib/fib_walk.h>
39#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010040#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010041
Neale Ranns88fc83e2017-04-05 08:11:14 -070042/*
43 * Add debugs for passing tests
44 */
45static int fib_test_do_debug;
46
Neale Ranns0bfe5d82016-08-25 15:29:12 +010047#define FIB_TEST_I(_cond, _comment, _args...) \
48({ \
49 int _evald = (_cond); \
50 if (!(_evald)) { \
51 fformat(stderr, "FAIL:%d: " _comment "\n", \
52 __LINE__, ##_args); \
53 } else { \
Neale Ranns88fc83e2017-04-05 08:11:14 -070054 if (fib_test_do_debug) \
55 fformat(stderr, "PASS:%d: " _comment "\n", \
56 __LINE__, ##_args); \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010057 } \
58 _evald; \
59})
60#define FIB_TEST(_cond, _comment, _args...) \
61{ \
62 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000063 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010064 ASSERT(!("FAIL: " _comment)); \
65 } \
66}
67
68/**
69 * A 'i'm not fussed is this is not efficient' store of test data
70 */
71typedef struct test_main_t_ {
72 /**
73 * HW if indicies
74 */
75 u32 hw_if_indicies[4];
76 /**
77 * HW interfaces
78 */
79 vnet_hw_interface_t * hw[4];
80
81} test_main_t;
82static test_main_t test_main;
83
84/* fake ethernet device class, distinct from "fake-ethX" */
85static u8 * format_test_interface_name (u8 * s, va_list * args)
86{
87 u32 dev_instance = va_arg (*args, u32);
88 return format (s, "test-eth%d", dev_instance);
89}
90
91static uword dummy_interface_tx (vlib_main_t * vm,
92 vlib_node_runtime_t * node,
93 vlib_frame_t * frame)
94{
95 clib_warning ("you shouldn't be here, leaking buffers...");
96 return frame->n_vectors;
97}
98
Neale Ranns8b37b872016-11-21 12:25:22 +000099static clib_error_t *
100test_interface_admin_up_down (vnet_main_t * vnm,
101 u32 hw_if_index,
102 u32 flags)
103{
104 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
105 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
106 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
107 return 0;
108}
109
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100110VNET_DEVICE_CLASS (test_interface_device_class,static) = {
111 .name = "Test interface",
112 .format_device_name = format_test_interface_name,
113 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000114 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100115};
116
117static u8 *hw_address;
118
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000119static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100120fib_test_mk_intf (u32 ninterfaces)
121{
122 clib_error_t * error = NULL;
123 test_main_t *tm = &test_main;
124 u8 byte;
125 u32 i;
126
127 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
128
129 for (i=0; i<6; i++)
130 {
131 byte = 0xd0+i;
132 vec_add1(hw_address, byte);
133 }
134
135 for (i = 0; i < ninterfaces; i++)
136 {
137 hw_address[5] = i;
138
139 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000140 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100141 i /* instance */,
142 hw_address,
143 &tm->hw_if_indicies[i],
144 /* flag change */ 0);
145
146 FIB_TEST((NULL == error), "ADD interface %d", i);
147
Neale Ranns8b37b872016-11-21 12:25:22 +0000148 error = vnet_hw_interface_set_flags(vnet_get_main(),
149 tm->hw_if_indicies[i],
150 VNET_HW_INTERFACE_FLAG_LINK_UP);
151 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100152 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000153 vec_validate (ip4_main.fib_index_by_sw_if_index,
154 tm->hw[i]->sw_if_index);
155 vec_validate (ip6_main.fib_index_by_sw_if_index,
156 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100157 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
158 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000159
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100160 error = vnet_sw_interface_set_flags(vnet_get_main(),
161 tm->hw[i]->sw_if_index,
162 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
163 FIB_TEST((NULL == error), "UP interface %d", i);
164 }
165 /*
166 * re-eval after the inevitable realloc
167 */
168 for (i = 0; i < ninterfaces; i++)
169 {
170 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
171 tm->hw_if_indicies[i]);
172 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000173
174 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100175}
176
Neale Ranns3ee44042016-10-03 13:05:48 +0100177#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100178{ \
179 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
180 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
181 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
182 fib_table_lookup(fib_index, (_via_prefix))); \
183 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100184 load_balance_get_bucket(_rec_dpo->dpoi_index, \
185 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100186 "%U is recursive via %U", \
187 format_fib_prefix, (_rec_prefix), \
188 format_fib_prefix, _via_prefix); \
189}
190
191#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
192{ \
193 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
194 fib_table_lookup_exact_match(fib_index, (_prefix))); \
195 const dpo_id_t *_dpo1 = \
196 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
197 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
198 format_dpo_type, _dpo1->dpoi_type); \
199 FIB_TEST((_ai == _dpo1->dpoi_index), \
200 "%U bucket %d resolves via %U", \
201 format_fib_prefix, (_prefix), \
202 _bucket, \
203 format_dpo_id, _dpo1, 0); \
204}
205
Neale Ranns3ee44042016-10-03 13:05:48 +0100206#define FIB_TEST_RPF(_cond, _comment, _args...) \
207{ \
208 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
209 return (0); \
210 } \
211}
212
213static int
214fib_test_urpf_is_equal (fib_node_index_t fei,
215 fib_forward_chain_type_t fct,
216 u32 num, ...)
217{
Neale Ranns948e00f2016-10-20 13:39:34 +0100218 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100219 fib_urpf_list_t *urpf;
220 index_t ui;
221 va_list ap;
222 int ii;
223
224 va_start(ap, num);
225
226 fib_entry_contribute_forwarding(fei, fct, &dpo);
227 ui = load_balance_get_urpf(dpo.dpoi_index);
228
229 urpf = fib_urpf_list_get(ui);
230
231 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
232 "RPF:%U len %d == %d",
233 format_fib_urpf_list, ui,
234 num, vec_len(urpf->furpf_itfs));
235 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
236 "RPF:%U check-size %d == %d",
237 format_fib_urpf_list, ui,
238 num, vec_len(urpf->furpf_itfs));
239
240 for (ii = 0; ii < num; ii++)
241 {
242 adj_index_t ai = va_arg(ap, adj_index_t);
243
244 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
245 "RPF:%d item:%d - %d == %d",
246 ui, ii, ai, urpf->furpf_itfs[ii]);
247 FIB_TEST_RPF(fib_urpf_check(ui, ai),
248 "RPF:%d %d found",
249 ui, ai);
250 }
251
252 dpo_reset(&dpo);
253
Neale Ranns5899fde2016-10-12 13:51:05 +0100254 va_end(ap);
255
Neale Ranns3ee44042016-10-03 13:05:48 +0100256 return (1);
257}
258
Neale Rannsb80c5362016-10-08 13:03:40 +0100259static u8*
260fib_test_build_rewrite (u8 *eth_addr)
261{
262 u8* rewrite = NULL;
263
264 vec_validate(rewrite, 13);
265
266 memcpy(rewrite, eth_addr, 6);
267 memcpy(rewrite+6, eth_addr, 6);
268
269 return (rewrite);
270}
271
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000272#define FIB_TEST_LB(_cond, _comment, _args...) \
273{ \
274 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
275 return (0); \
276 } \
277}
278
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800279int
280fib_test_validate_rep_v (const replicate_t *rep,
281 u16 n_buckets,
Christophe Fontained3c008d2017-10-02 18:10:54 +0200282 va_list *ap)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800283{
284 const fib_test_rep_bucket_t *exp;
285 const dpo_id_t *dpo;
286 int bucket;
287
288 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
289 "n_buckets = %d", rep->rep_n_buckets);
290
291 for (bucket = 0; bucket < n_buckets; bucket++)
292 {
Christophe Fontained3c008d2017-10-02 18:10:54 +0200293 exp = va_arg(*ap, fib_test_rep_bucket_t*);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800294
295 dpo = replicate_get_bucket_i(rep, bucket);
296
297 switch (exp->type)
298 {
299 case FT_REP_LABEL_O_ADJ:
300 {
301 const mpls_label_dpo_t *mld;
302 mpls_label_t hdr;
303 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
304 "bucket %d stacks on %U",
305 bucket,
306 format_dpo_type, dpo->dpoi_type);
307
308 mld = mpls_label_dpo_get(dpo->dpoi_index);
309 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
310
311 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
312 exp->label_o_adj.label),
313 "bucket %d stacks on label %d",
314 bucket,
315 exp->label_o_adj.label);
316
317 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
318 exp->label_o_adj.eos),
319 "bucket %d stacks on label %d %U",
320 bucket,
321 exp->label_o_adj.label,
322 format_mpls_eos_bit, exp->label_o_adj.eos);
323
324 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
325 "bucket %d label stacks on %U",
326 bucket,
327 format_dpo_type, mld->mld_dpo.dpoi_type);
328
329 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
330 "bucket %d label stacks on adj %d",
331 bucket,
332 exp->label_o_adj.adj);
333 }
334 break;
335 case FT_REP_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700336 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800337 "bucket %d stacks on %U",
338 bucket,
339 format_dpo_type, dpo->dpoi_type);
340
341 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
342 "bucket %d stacks on adj %d",
343 bucket,
344 exp->adj.adj);
345 break;
346 case FT_REP_DISP_MFIB_LOOKUP:
347// ASSERT(0);
348 break;
349 }
350 }
351
352 return (!0);
353}
354
355int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000356fib_test_validate_lb_v (const load_balance_t *lb,
357 u16 n_buckets,
Christophe Fontained3c008d2017-10-02 18:10:54 +0200358 va_list *ap)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000359{
360 const dpo_id_t *dpo;
361 int bucket;
362
363 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
364
365 for (bucket = 0; bucket < n_buckets; bucket++)
366 {
367 const fib_test_lb_bucket_t *exp;
368
Christophe Fontained3c008d2017-10-02 18:10:54 +0200369 exp = va_arg(*ap, fib_test_lb_bucket_t*);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000370 dpo = load_balance_get_bucket_i(lb, bucket);
371
372 switch (exp->type)
373 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000374 case FT_LB_LABEL_STACK_O_ADJ:
375 {
376 const mpls_label_dpo_t *mld;
377 mpls_label_t hdr;
378 u32 ii;
379
380 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
381 "bucket %d stacks on %U",
382 bucket,
383 format_dpo_type, dpo->dpoi_type);
384
385 mld = mpls_label_dpo_get(dpo->dpoi_index);
386
387 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
388 "label stack size",
389 mld->mld_n_labels);
390
391 for (ii = 0; ii < mld->mld_n_labels; ii++)
392 {
393 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
394 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
395 exp->label_stack_o_adj.label_stack[ii]),
396 "bucket %d stacks on label %d",
397 bucket,
398 exp->label_stack_o_adj.label_stack[ii]);
399
400 if (ii == mld->mld_n_labels-1)
401 {
402 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
403 exp->label_o_adj.eos),
404 "bucket %d stacks on label %d %U!=%U",
405 bucket,
406 exp->label_stack_o_adj.label_stack[ii],
407 format_mpls_eos_bit, exp->label_o_adj.eos,
408 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
409 }
410 else
411 {
412 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
413 "bucket %d stacks on label %d %U",
414 bucket,
415 exp->label_stack_o_adj.label_stack[ii],
416 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
417 }
418 }
419
420 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
421 "bucket %d label stacks on %U",
422 bucket,
423 format_dpo_type, mld->mld_dpo.dpoi_type);
424
425 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
426 "bucket %d label stacks on adj %d",
427 bucket,
428 exp->label_stack_o_adj.adj);
429 }
430 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000431 case FT_LB_LABEL_O_ADJ:
432 {
433 const mpls_label_dpo_t *mld;
434 mpls_label_t hdr;
435 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
436 "bucket %d stacks on %U",
437 bucket,
438 format_dpo_type, dpo->dpoi_type);
439
440 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000441 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000442
443 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
444 exp->label_o_adj.label),
445 "bucket %d stacks on label %d",
446 bucket,
447 exp->label_o_adj.label);
448
449 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
450 exp->label_o_adj.eos),
451 "bucket %d stacks on label %d %U",
452 bucket,
453 exp->label_o_adj.label,
454 format_mpls_eos_bit, exp->label_o_adj.eos);
455
456 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == 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_adj.adj == mld->mld_dpo.dpoi_index),
462 "bucket %d label stacks on adj %d",
463 bucket,
464 exp->label_o_adj.adj);
465 }
466 break;
467 case FT_LB_LABEL_O_LB:
468 {
469 const mpls_label_dpo_t *mld;
470 mpls_label_t hdr;
471
472 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
473 "bucket %d stacks on %U",
474 bucket,
475 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000476
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000477 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000478 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000479
Neale Rannsad422ed2016-11-02 14:20:04 +0000480 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
481 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000482 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
483 exp->label_o_lb.label),
484 "bucket %d stacks on label %d",
485 bucket,
486 exp->label_o_lb.label);
487
488 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
489 exp->label_o_lb.eos),
490 "bucket %d stacks on label %d %U",
491 bucket,
492 exp->label_o_lb.label,
493 format_mpls_eos_bit, exp->label_o_lb.eos);
494
495 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
496 "bucket %d label stacks on %U",
497 bucket,
498 format_dpo_type, mld->mld_dpo.dpoi_type);
499
500 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
501 "bucket %d label stacks on LB %d",
502 bucket,
503 exp->label_o_lb.lb);
504 }
505 break;
506 case FT_LB_ADJ:
507 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
508 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
509 "bucket %d stacks on %U",
510 bucket,
511 format_dpo_type, dpo->dpoi_type);
512 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
513 "bucket %d stacks on adj %d",
514 bucket,
515 exp->adj.adj);
516 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800517 case FT_LB_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700518 FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800519 "bucket %d stacks on %U",
520 bucket,
521 format_dpo_type, dpo->dpoi_type);
522 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
523 "bucket %d stacks on adj %d",
524 bucket,
525 exp->adj.adj);
526 break;
Neale Ranns6f631152017-10-03 08:20:21 -0700527 case FT_LB_L2:
528 FIB_TEST_I((DPO_L2_BRIDGE == dpo->dpoi_type),
529 "bucket %d stacks on %U",
530 bucket,
531 format_dpo_type, dpo->dpoi_type);
532 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
533 "bucket %d stacks on adj %d",
534 bucket,
535 exp->adj.adj);
536 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000537 case FT_LB_O_LB:
538 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
539 "bucket %d stacks on %U",
540 bucket,
541 format_dpo_type, dpo->dpoi_type);
542 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
Neale Ranns57b58602017-07-15 07:37:25 -0700543 "bucket %d stacks on lb %d not %d",
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000544 bucket,
Neale Ranns57b58602017-07-15 07:37:25 -0700545 dpo->dpoi_index,
546 exp->lb.lb);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000547 break;
Neale Rannsd792d9c2017-10-21 10:53:20 -0700548 case FT_LB_BIER_TABLE:
549 FIB_TEST_LB((DPO_BIER_TABLE == dpo->dpoi_type),
550 "bucket %d stacks on %U",
551 bucket,
552 format_dpo_type, dpo->dpoi_type);
553 FIB_TEST_LB((exp->bier.table == dpo->dpoi_index),
554 "bucket %d stacks on lb %d",
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000555 bucket,
Neale Rannsd792d9c2017-10-21 10:53:20 -0700556 exp->bier.table);
557 break;
558 case FT_LB_BIER_FMASK:
559 FIB_TEST_LB((DPO_BIER_FMASK == dpo->dpoi_type),
560 "bucket %d stacks on %U",
561 bucket,
562 format_dpo_type, dpo->dpoi_type);
563 FIB_TEST_LB((exp->bier.fmask == dpo->dpoi_index),
564 "bucket %d stacks on lb %d",
565 bucket,
566 exp->bier.fmask);
567 break;
568 case FT_LB_DROP:
569 FIB_TEST_LB((DPO_DROP == dpo->dpoi_type),
570 "bucket %d stacks on %U",
571 bucket,
572 format_dpo_type, dpo->dpoi_type);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000573 break;
574 }
575 }
576 return (!0);
577}
578
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800579int
Neale Rannsd792d9c2017-10-21 10:53:20 -0700580fib_test_validate_lb (const dpo_id_t *dpo,
581 u16 n_buckets,
582 ...)
583{
584 const load_balance_t *lb;
585 va_list ap;
586 int res;
587
588 va_start(ap, n_buckets);
589
590 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo->dpoi_type),
591 "Entry links to %U",
592 format_dpo_type, dpo->dpoi_type);
593 lb = load_balance_get(dpo->dpoi_index);
594
595 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
596
597 va_end(ap);
598
599 return (res);
600}
601
602int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000603fib_test_validate_entry (fib_node_index_t fei,
604 fib_forward_chain_type_t fct,
Gabriel Ganned71e0fc2017-10-26 10:35:28 +0200605 int n_buckets,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000606 ...)
607{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000608 dpo_id_t dpo = DPO_INVALID;
609 fib_prefix_t pfx;
610 index_t fw_lbi;
611 u32 fib_index;
612 va_list ap;
613 int res;
614
615 va_start(ap, n_buckets);
616
617 fib_entry_get_prefix(fei, &pfx);
618 fib_index = fib_entry_get_fib_index(fei);
619 fib_entry_contribute_forwarding(fei, fct, &dpo);
620
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800621 if (DPO_REPLICATE == dpo.dpoi_type)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000622 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800623 const replicate_t *rep;
624
625 rep = replicate_get(dpo.dpoi_index);
Christophe Fontained3c008d2017-10-02 18:10:54 +0200626 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800627 }
628 else
629 {
630 const load_balance_t *lb;
631
632 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
633 "Entry links to %U",
634 format_dpo_type, dpo.dpoi_type);
635
636 lb = load_balance_get(dpo.dpoi_index);
Christophe Fontained3c008d2017-10-02 18:10:54 +0200637 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800638
639 /*
640 * ensure that the LB contributed by the entry is the
641 * same as the LB in the forwarding tables
642 */
643 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Rannsad422ed2016-11-02 14:20:04 +0000644 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800645 switch (pfx.fp_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000646 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800647 case FIB_PROTOCOL_IP4:
648 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
Neale Rannsad422ed2016-11-02 14:20:04 +0000649 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800650 case FIB_PROTOCOL_IP6:
651 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
652 break;
653 case FIB_PROTOCOL_MPLS:
654 {
655 mpls_unicast_header_t hdr = {
656 .label_exp_s_ttl = 0,
657 };
658
659 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
660 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
661 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
662
663 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
664 break;
665 }
666 default:
667 fw_lbi = 0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000668 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800669 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
670 "Contributed LB = FW LB: %U\n %U",
671 format_load_balance, fw_lbi, 0,
672 format_load_balance, dpo.dpoi_index, 0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000673 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000674 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000675
676 dpo_reset(&dpo);
677
678 va_end(ap);
679
680 return (res);
681}
682
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000683static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100684fib_test_v4 (void)
685{
686 /*
687 * In the default table check for the presence and correct forwarding
688 * of the special entries
689 */
690 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
691 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
692 const ip_adjacency_t *adj;
693 const load_balance_t *lb;
694 test_main_t *tm;
695 u32 fib_index;
Neale Ranns994dab42017-04-18 12:56:45 -0700696 int lb_count;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100697 int ii;
698
699 /* via 10.10.10.1 */
700 ip46_address_t nh_10_10_10_1 = {
701 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
702 };
703 /* via 10.10.10.2 */
704 ip46_address_t nh_10_10_10_2 = {
705 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
706 };
707
Neale Rannsf12a83f2017-04-18 09:09:40 -0700708 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
709 pool_elts(load_balance_map_pool));
710
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100711 tm = &test_main;
712
Neale Ranns994dab42017-04-18 12:56:45 -0700713 /* record the nubmer of load-balances in use before we start */
714 lb_count = pool_elts(load_balance_pool);
715
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100716 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -0700717 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
718 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100719
720 for (ii = 0; ii < 4; ii++)
721 {
722 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
723 }
724
725 fib_prefix_t pfx_0_0_0_0_s_0 = {
726 .fp_len = 0,
727 .fp_proto = FIB_PROTOCOL_IP4,
728 .fp_addr = {
729 .ip4 = {
730 {0}
731 },
732 },
733 };
734
735 fib_prefix_t pfx = {
736 .fp_len = 0,
737 .fp_proto = FIB_PROTOCOL_IP4,
738 .fp_addr = {
739 .ip4 = {
740 {0}
741 },
742 },
743 };
744
745 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
746
747 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
748 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
749 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
750 "Default route is DROP");
751
752 pfx.fp_len = 32;
753 fei = fib_table_lookup(fib_index, &pfx);
754 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
755 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
756 "all 0s route is DROP");
757
758 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
759 pfx.fp_len = 32;
760 fei = fib_table_lookup(fib_index, &pfx);
761 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
762 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
763 "all 1s route is DROP");
764
765 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
766 pfx.fp_len = 8;
767 fei = fib_table_lookup(fib_index, &pfx);
768 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
769 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
770 "all-mcast route is DROP");
771
772 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
773 pfx.fp_len = 8;
774 fei = fib_table_lookup(fib_index, &pfx);
775 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
776 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
777 "class-e route is DROP");
778
779 /*
780 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
781 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000782 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
783 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100784 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000785#define ENBR (5+5+2)
786#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100787 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000788 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100789 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000790 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100791 fib_entry_pool_size());
792
793 /*
794 * add interface routes.
795 * validate presence of /24 attached and /32 recieve.
796 * test for the presence of the receive address in the glean and local adj
797 */
798 fib_prefix_t local_pfx = {
799 .fp_len = 24,
800 .fp_proto = FIB_PROTOCOL_IP4,
801 .fp_addr = {
802 .ip4 = {
803 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
804 },
805 },
806 };
807
808 fib_table_entry_update_one_path(fib_index, &local_pfx,
809 FIB_SOURCE_INTERFACE,
810 (FIB_ENTRY_FLAG_CONNECTED |
811 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -0700812 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100813 NULL,
814 tm->hw[0]->sw_if_index,
815 ~0, // invalid fib index
816 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000817 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100818 FIB_ROUTE_PATH_FLAG_NONE);
819 fei = fib_table_lookup(fib_index, &local_pfx);
820 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
821 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
822 fib_entry_get_flags(fei)),
823 "Flags set on attached interface");
824
825 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -0700826 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
827 "attached interface route adj present %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100828 adj = adj_get(ai);
829 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
830 "attached interface adj is glean");
831 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
832 &adj->sub_type.glean.receive_addr)),
833 "attached interface adj is receive ok");
834
835 local_pfx.fp_len = 32;
836 fib_table_entry_update_one_path(fib_index, &local_pfx,
837 FIB_SOURCE_INTERFACE,
838 (FIB_ENTRY_FLAG_CONNECTED |
839 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -0700840 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100841 NULL,
842 tm->hw[0]->sw_if_index,
843 ~0, // invalid fib index
844 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000845 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100846 FIB_ROUTE_PATH_FLAG_NONE);
847 fei = fib_table_lookup(fib_index, &local_pfx);
848 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
849 fib_entry_get_flags(fei)),
850 "Flags set on local interface");
851
852 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
853
854 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100855 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
856 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100857 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
858 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
859 "local interface adj is local");
860 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
861
862 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
863 &rd->rd_addr)),
864 "local interface adj is receive ok");
865
866 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
867 FIB_PROTOCOL_IP4,
868 FIB_SOURCE_INTERFACE)),
869 "2 Interface Source'd prefixes");
870
871 /*
872 * +2 interface routes +2 non-shared path-lists
873 */
874 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000875 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100876 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000877 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100878 fib_entry_pool_size());
879
880 /*
881 * Modify the default route to be via an adj not yet known.
882 * this sources the defalut route with the API source, which is
883 * a higher preference to the DEFAULT_ROUTE source
884 */
885 pfx.fp_addr.ip4.as_u32 = 0;
886 pfx.fp_len = 0;
887 fib_table_entry_path_add(fib_index, &pfx,
888 FIB_SOURCE_API,
889 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -0700890 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100891 &nh_10_10_10_1,
892 tm->hw[0]->sw_if_index,
893 ~0, // invalid fib index
894 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000895 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100896 FIB_ROUTE_PATH_FLAG_NONE);
897 fei = fib_table_lookup(fib_index, &pfx);
898 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
899 "Flags set on API route");
900
901 FIB_TEST((fei == dfrt), "default route same index");
902 ai = fib_entry_get_adj(fei);
903 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
904 adj = adj_get(ai);
905 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
906 "adj is incomplete");
907 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
908 "adj nbr next-hop ok");
909 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
910 FIB_PROTOCOL_IP4,
911 FIB_SOURCE_API)),
912 "1 API Source'd prefixes");
913
914 /*
915 * find the adj in the shared db
916 */
917 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100918 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100919 &nh_10_10_10_1,
920 tm->hw[0]->sw_if_index);
921 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
922 adj_unlock(locked_ai);
923
924 /*
925 * +1 shared path-list
926 */
927 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
928 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000929 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100930 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000931 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100932 fib_entry_pool_size());
933
934 /*
935 * remove the API source from the default route. We expected
936 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
937 */
938 pfx.fp_addr.ip4.as_u32 = 0;
939 pfx.fp_len = 0;
940 fib_table_entry_path_remove(fib_index, &pfx,
941 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -0700942 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100943 &nh_10_10_10_1,
944 tm->hw[0]->sw_if_index,
945 ~0, // non-recursive path, so no FIB index
946 1,
947 FIB_ROUTE_PATH_FLAG_NONE);
948
949 fei = fib_table_lookup(fib_index, &pfx);
950
951 FIB_TEST((fei == dfrt), "default route same index");
952 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
953 "Default route is DROP");
954
955 /*
956 * -1 shared-path-list
957 */
958 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000959 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100960 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000961 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100962 fib_entry_pool_size());
963
964 /*
965 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
966 */
967 fib_prefix_t pfx_10_10_10_1_s_32 = {
968 .fp_len = 32,
969 .fp_proto = FIB_PROTOCOL_IP4,
970 .fp_addr = {
971 /* 10.10.10.1 */
972 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
973 },
974 };
975 fib_prefix_t pfx_10_10_10_2_s_32 = {
976 .fp_len = 32,
977 .fp_proto = FIB_PROTOCOL_IP4,
978 .fp_addr = {
979 /* 10.10.10.2 */
980 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
981 },
982 };
983 fib_prefix_t pfx_11_11_11_11_s_32 = {
984 .fp_len = 32,
985 .fp_proto = FIB_PROTOCOL_IP4,
986 .fp_addr = {
987 /* 11.11.11.11 */
988 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
989 },
990 };
991 u8 eth_addr[] = {
992 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
993 };
Neale Rannsb80c5362016-10-08 13:03:40 +0100994
Neale Ranns3ee44042016-10-03 13:05:48 +0100995 ip46_address_t nh_12_12_12_12 = {
996 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
997 };
998 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100999
1000 /*
1001 * Add a route via an incomplete ADJ. then complete the ADJ
1002 * Expect the route LB is updated to use complete adj type.
1003 */
1004 fei = fib_table_entry_update_one_path(fib_index,
1005 &pfx_11_11_11_11_s_32,
1006 FIB_SOURCE_API,
1007 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001008 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001009 &pfx_10_10_10_1_s_32.fp_addr,
1010 tm->hw[0]->sw_if_index,
1011 ~0, // invalid fib index
1012 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001013 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001014 FIB_ROUTE_PATH_FLAG_NONE);
1015
1016 dpo = fib_entry_contribute_ip_forwarding(fei);
1017 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1018 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
1019 "11.11.11.11/32 via incomplete adj");
1020
1021 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001022 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001023 &pfx_10_10_10_1_s_32.fp_addr,
1024 tm->hw[0]->sw_if_index);
1025 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
1026 adj = adj_get(ai_01);
1027 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1028 "adj is incomplete");
1029 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1030 &adj->sub_type.nbr.next_hop)),
1031 "adj nbr next-hop ok");
1032
Neale Rannsb80c5362016-10-08 13:03:40 +01001033 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1034 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001035 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1036 "adj is complete");
1037 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
1038 &adj->sub_type.nbr.next_hop)),
1039 "adj nbr next-hop ok");
1040 ai = fib_entry_get_adj(fei);
1041 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1042
1043 dpo = fib_entry_contribute_ip_forwarding(fei);
1044 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1045 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1046 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001047 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1048 tm->hw[0]->sw_if_index),
1049 "RPF list for adj-fib contains adj");
1050
1051 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001052 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001053 &nh_12_12_12_12,
1054 tm->hw[1]->sw_if_index);
1055 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1056 adj = adj_get(ai_12_12_12_12);
1057 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1058 "adj is incomplete");
1059 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1060 &adj->sub_type.nbr.next_hop)),
1061 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001062 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1063 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001064 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1065 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001066
1067 /*
1068 * add the adj fib
1069 */
Neale Ranns81424992017-05-18 03:03:22 -07001070 fei = fib_table_entry_path_add(fib_index,
1071 &pfx_10_10_10_1_s_32,
1072 FIB_SOURCE_ADJ,
1073 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001074 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001075 &pfx_10_10_10_1_s_32.fp_addr,
1076 tm->hw[0]->sw_if_index,
1077 ~0, // invalid fib index
1078 1,
1079 NULL,
1080 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001081 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1082 "Flags set on adj-fib");
1083 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -07001084 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001085
1086 fib_table_entry_path_remove(fib_index,
1087 &pfx_11_11_11_11_s_32,
1088 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001089 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001090 &pfx_10_10_10_1_s_32.fp_addr,
1091 tm->hw[0]->sw_if_index,
1092 ~0, // invalid fib index
1093 1,
1094 FIB_ROUTE_PATH_FLAG_NONE);
1095
1096 eth_addr[5] = 0xb2;
1097
1098 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001099 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001100 &pfx_10_10_10_2_s_32.fp_addr,
1101 tm->hw[0]->sw_if_index);
1102 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1103 adj = adj_get(ai_02);
1104 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1105 "adj is incomplete");
1106 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1107 &adj->sub_type.nbr.next_hop)),
1108 "adj nbr next-hop ok");
1109
Neale Rannsb80c5362016-10-08 13:03:40 +01001110 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1111 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001112 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1113 "adj is complete");
1114 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1115 &adj->sub_type.nbr.next_hop)),
1116 "adj nbr next-hop ok");
1117 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1118
Neale Ranns81424992017-05-18 03:03:22 -07001119 fib_table_entry_path_add(fib_index,
1120 &pfx_10_10_10_2_s_32,
1121 FIB_SOURCE_ADJ,
1122 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001123 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001124 &pfx_10_10_10_2_s_32.fp_addr,
1125 tm->hw[0]->sw_if_index,
1126 ~0, // invalid fib index
1127 1,
1128 NULL,
1129 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001130
1131 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1132 ai = fib_entry_get_adj(fei);
1133 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1134
1135 /*
1136 * +2 adj-fibs, and their non-shared path-lists
1137 */
1138 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001139 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001140 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001141 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001142 fib_entry_pool_size());
1143
1144 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001145 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001146 */
1147 fib_prefix_t pfx_1_1_1_1_s_32 = {
1148 .fp_len = 32,
1149 .fp_proto = FIB_PROTOCOL_IP4,
1150 .fp_addr = {
1151 /* 1.1.1.1/32 */
1152 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1153 },
1154 };
1155
1156 fib_table_entry_path_add(fib_index,
1157 &pfx_1_1_1_1_s_32,
1158 FIB_SOURCE_API,
1159 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001160 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001161 &nh_10_10_10_1,
1162 tm->hw[0]->sw_if_index,
1163 ~0, // invalid fib index
1164 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001165 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001166 FIB_ROUTE_PATH_FLAG_NONE);
1167 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1168 ai = fib_entry_get_adj(fei);
1169 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1170
1171 /*
1172 * +1 entry and a shared path-list
1173 */
1174 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001175 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001176 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001177 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001178 fib_entry_pool_size());
1179
1180 /* 1.1.2.0/24 */
1181 fib_prefix_t pfx_1_1_2_0_s_24 = {
1182 .fp_len = 24,
1183 .fp_proto = FIB_PROTOCOL_IP4,
1184 .fp_addr = {
1185 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1186 }
1187 };
1188
1189 fib_table_entry_path_add(fib_index,
1190 &pfx_1_1_2_0_s_24,
1191 FIB_SOURCE_API,
1192 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001193 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001194 &nh_10_10_10_1,
1195 tm->hw[0]->sw_if_index,
1196 ~0, // invalid fib index
1197 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001198 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001199 FIB_ROUTE_PATH_FLAG_NONE);
1200 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1201 ai = fib_entry_get_adj(fei);
1202 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1203
1204 /*
1205 * +1 entry only
1206 */
1207 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001208 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001209 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001210 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001211 fib_entry_pool_size());
1212
1213 /*
1214 * modify 1.1.2.0/24 to use multipath.
1215 */
1216 fib_table_entry_path_add(fib_index,
1217 &pfx_1_1_2_0_s_24,
1218 FIB_SOURCE_API,
1219 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001220 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001221 &nh_10_10_10_2,
1222 tm->hw[0]->sw_if_index,
1223 ~0, // invalid fib index
1224 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001225 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001226 FIB_ROUTE_PATH_FLAG_NONE);
1227 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1228 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001229 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1230 1, tm->hw[0]->sw_if_index),
1231 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001232
1233 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1234 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1235 FIB_TEST((ai_01 == dpo1->dpoi_index),
1236 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1237 ai_01, dpo1->dpoi_index);
1238
1239 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1240 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1241 FIB_TEST((ai_02 == dpo1->dpoi_index),
1242 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1243
1244 /*
1245 * +1 shared-pathlist
1246 */
1247 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001248 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001249 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001250 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001251 fib_entry_pool_size());
1252
1253 /*
1254 * revert the modify
1255 */
1256 fib_table_entry_path_remove(fib_index,
1257 &pfx_1_1_2_0_s_24,
1258 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001259 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001260 &nh_10_10_10_2,
1261 tm->hw[0]->sw_if_index,
1262 ~0,
1263 1,
1264 FIB_ROUTE_PATH_FLAG_NONE);
1265 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001266 dpo = fib_entry_contribute_ip_forwarding(fei);
1267 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1268 1, tm->hw[0]->sw_if_index),
1269 "RPF list for 1.1.2.0/24 contains one adj");
1270
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001271 ai = fib_entry_get_adj(fei);
1272 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1273
1274 /*
1275 * +1 shared-pathlist
1276 */
1277 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1278 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001279 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001280 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001281 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001282 fib_entry_pool_size());
1283
1284 /*
1285 * Add 2 recursive routes:
1286 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1287 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1288 */
1289 fib_prefix_t bgp_100_pfx = {
1290 .fp_len = 32,
1291 .fp_proto = FIB_PROTOCOL_IP4,
1292 .fp_addr = {
1293 /* 100.100.100.100/32 */
1294 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1295 },
1296 };
1297 /* via 1.1.1.1 */
1298 ip46_address_t nh_1_1_1_1 = {
1299 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1300 };
1301
Neale Ranns3ee44042016-10-03 13:05:48 +01001302 fei = fib_table_entry_path_add(fib_index,
1303 &bgp_100_pfx,
1304 FIB_SOURCE_API,
1305 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001306 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001307 &nh_1_1_1_1,
1308 ~0, // no index provided.
1309 fib_index, // nexthop in same fib as route
1310 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001311 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001312 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001313
Neale Ranns3ee44042016-10-03 13:05:48 +01001314 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1315 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1316 tm->hw[0]->sw_if_index),
1317 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001318
1319 /*
1320 * +1 entry and +1 shared-path-list
1321 */
1322 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1323 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001324 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001325 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001326 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001327 fib_entry_pool_size());
1328
1329 fib_prefix_t bgp_101_pfx = {
1330 .fp_len = 32,
1331 .fp_proto = FIB_PROTOCOL_IP4,
1332 .fp_addr = {
1333 /* 100.100.100.101/32 */
1334 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1335 },
1336 };
1337
1338 fib_table_entry_path_add(fib_index,
1339 &bgp_101_pfx,
1340 FIB_SOURCE_API,
1341 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001342 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001343 &nh_1_1_1_1,
1344 ~0, // no index provided.
1345 fib_index, // nexthop in same fib as route
1346 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001347 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001348 FIB_ROUTE_PATH_FLAG_NONE);
1349
Neale Ranns3ee44042016-10-03 13:05:48 +01001350 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1351 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1352 tm->hw[0]->sw_if_index),
1353 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001354
1355 /*
1356 * +1 entry, but the recursive path-list is shared.
1357 */
1358 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1359 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001360 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001361 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001362 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001363 fib_entry_pool_size());
1364
1365 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001366 * An special route; one where the user (me) provides the
1367 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001368 */
1369 fib_prefix_t ex_pfx = {
1370 .fp_len = 32,
1371 .fp_proto = FIB_PROTOCOL_IP4,
1372 .fp_addr = {
1373 /* 4.4.4.4/32 */
1374 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1375 },
1376 };
1377
1378 fib_table_entry_special_add(fib_index,
1379 &ex_pfx,
1380 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001381 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001382 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001383 dpo = fib_entry_contribute_ip_forwarding(fei);
1384 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1385 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1386 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001387
1388 fib_table_entry_special_remove(fib_index,
1389 &ex_pfx,
1390 FIB_SOURCE_SPECIAL);
1391 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1392 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1393 "Exclusive reoute removed");
1394
1395 /*
1396 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1397 * adjacency through which the route will resovle
1398 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001399 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001400
1401 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1402 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001403 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001404 LOOKUP_INPUT_DST_ADDR,
1405 LOOKUP_TABLE_FROM_CONFIG,
1406 &ex_dpo);
1407
1408 fib_table_entry_special_dpo_add(fib_index,
1409 &ex_pfx,
1410 FIB_SOURCE_SPECIAL,
1411 FIB_ENTRY_FLAG_EXCLUSIVE,
1412 &ex_dpo);
1413 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1414 dpo = fib_entry_contribute_ip_forwarding(fei);
1415 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1416 "exclusive remote uses lookup DPO");
1417
Neale Ranns948e00f2016-10-20 13:39:34 +01001418 /*
1419 * update the exclusive to use a different DPO
1420 */
Neale Ranns450cd302016-11-09 17:49:42 +00001421 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001422 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1423 &ex_dpo);
1424 fib_table_entry_special_dpo_update(fib_index,
1425 &ex_pfx,
1426 FIB_SOURCE_SPECIAL,
1427 FIB_ENTRY_FLAG_EXCLUSIVE,
1428 &ex_dpo);
1429 dpo = fib_entry_contribute_ip_forwarding(fei);
1430 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1431 "exclusive remote uses now uses NULL DPO");
1432
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001433 fib_table_entry_special_remove(fib_index,
1434 &ex_pfx,
1435 FIB_SOURCE_SPECIAL);
1436 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1437 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1438 "Exclusive reoute removed");
1439 dpo_reset(&ex_dpo);
1440
1441 /*
1442 * Add a recursive route:
1443 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1444 */
1445 fib_prefix_t bgp_200_pfx = {
1446 .fp_len = 32,
1447 .fp_proto = FIB_PROTOCOL_IP4,
1448 .fp_addr = {
1449 /* 200.200.200.200/32 */
1450 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1451 },
1452 };
1453 /* via 1.1.1.2 */
1454 fib_prefix_t pfx_1_1_1_2_s_32 = {
1455 .fp_len = 32,
1456 .fp_proto = FIB_PROTOCOL_IP4,
1457 .fp_addr = {
1458 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1459 },
1460 };
1461
Neale Ranns57b58602017-07-15 07:37:25 -07001462 fei = fib_table_entry_path_add(fib_index,
1463 &bgp_200_pfx,
1464 FIB_SOURCE_API,
1465 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001466 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07001467 &pfx_1_1_1_2_s_32.fp_addr,
1468 ~0, // no index provided.
1469 fib_index, // nexthop in same fib as route
1470 1,
1471 NULL,
1472 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001473
Neale Ranns57b58602017-07-15 07:37:25 -07001474 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1475 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001476
1477 /*
1478 * the adj should be recursive via drop, since the route resolves via
1479 * the default route, which is itself a DROP
1480 */
1481 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1482 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1483 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001484 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1485 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001486
1487 /*
1488 * +2 entry and +1 shared-path-list
1489 */
1490 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1491 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001492 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001493 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001494 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001495 fib_entry_pool_size());
1496
1497 /*
1498 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001499 * The paths are sort by NH first. in this case the the path with greater
1500 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001501 */
1502 fib_prefix_t pfx_1_2_3_4_s_32 = {
1503 .fp_len = 32,
1504 .fp_proto = FIB_PROTOCOL_IP4,
1505 .fp_addr = {
1506 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1507 },
1508 };
1509 fib_table_entry_path_add(fib_index,
1510 &pfx_1_2_3_4_s_32,
1511 FIB_SOURCE_API,
1512 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001513 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001514 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001515 tm->hw[0]->sw_if_index,
1516 ~0,
1517 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001518 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001519 FIB_ROUTE_PATH_FLAG_NONE);
1520 fei = fib_table_entry_path_add(fib_index,
1521 &pfx_1_2_3_4_s_32,
1522 FIB_SOURCE_API,
1523 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001524 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001525 &nh_12_12_12_12,
1526 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001527 ~0,
1528 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001529 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001530 FIB_ROUTE_PATH_FLAG_NONE);
1531
1532 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1533 dpo = fib_entry_contribute_ip_forwarding(fei);
1534 lb = load_balance_get(dpo->dpoi_index);
1535 FIB_TEST((lb->lb_n_buckets == 4),
1536 "1.2.3.4/32 LB has %d bucket",
1537 lb->lb_n_buckets);
1538
Neale Ranns3ee44042016-10-03 13:05:48 +01001539 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1540 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1541 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1542 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001543
Neale Ranns3ee44042016-10-03 13:05:48 +01001544 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1545 tm->hw[0]->sw_if_index,
1546 tm->hw[1]->sw_if_index),
1547 "RPF list for 1.2.3.4/32 contains both adjs");
1548
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001549
1550 /*
1551 * Unequal Cost load-balance. 4:1 ratio.
1552 * fits in a 16 bucket LB with ratio 13:3
1553 */
1554 fib_prefix_t pfx_1_2_3_5_s_32 = {
1555 .fp_len = 32,
1556 .fp_proto = FIB_PROTOCOL_IP4,
1557 .fp_addr = {
1558 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1559 },
1560 };
1561 fib_table_entry_path_add(fib_index,
1562 &pfx_1_2_3_5_s_32,
1563 FIB_SOURCE_API,
1564 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001565 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001566 &nh_12_12_12_12,
1567 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001568 ~0,
1569 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001570 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001571 FIB_ROUTE_PATH_FLAG_NONE);
1572 fei = fib_table_entry_path_add(fib_index,
1573 &pfx_1_2_3_5_s_32,
1574 FIB_SOURCE_API,
1575 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001576 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001577 &nh_10_10_10_1,
1578 tm->hw[0]->sw_if_index,
1579 ~0,
1580 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001581 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001582 FIB_ROUTE_PATH_FLAG_NONE);
1583
1584 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1585 dpo = fib_entry_contribute_ip_forwarding(fei);
1586 lb = load_balance_get(dpo->dpoi_index);
1587 FIB_TEST((lb->lb_n_buckets == 16),
1588 "1.2.3.5/32 LB has %d bucket",
1589 lb->lb_n_buckets);
1590
1591 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1592 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1593 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1594 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1595 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1596 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1597 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1598 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1599 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1600 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1601 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1602 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1603 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001604 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1605 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1606 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1607
1608 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1609 tm->hw[0]->sw_if_index,
1610 tm->hw[1]->sw_if_index),
1611 "RPF list for 1.2.3.4/32 contains both adjs");
1612
1613 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001614 * Test UCMP with a large weight skew - this produces load-balance objects with large
1615 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1616 * laso testing the LB in placce modify code when number of buckets is large.
1617 */
1618 fib_prefix_t pfx_6_6_6_6_s_32 = {
1619 .fp_len = 32,
1620 .fp_proto = FIB_PROTOCOL_IP4,
1621 .fp_addr = {
1622 /* 1.1.1.1/32 */
1623 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1624 },
1625 };
Neale Ranns81424992017-05-18 03:03:22 -07001626 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001627 .type = FT_LB_ADJ,
1628 .adj = {
1629 .adj = ai_01,
1630 },
1631 };
Neale Ranns81424992017-05-18 03:03:22 -07001632 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001633 .type = FT_LB_ADJ,
1634 .adj = {
1635 .adj = ai_02,
1636 },
1637 };
1638 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1639 .type = FT_LB_ADJ,
1640 .adj = {
1641 .adj = ai_12_12_12_12,
1642 },
1643 };
1644 fib_table_entry_update_one_path(fib_index,
1645 &pfx_6_6_6_6_s_32,
1646 FIB_SOURCE_API,
1647 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001648 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001649 &nh_10_10_10_1,
1650 tm->hw[0]->sw_if_index,
1651 ~0, // invalid fib index
1652 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001653 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001654 FIB_ROUTE_PATH_FLAG_NONE);
1655
1656 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1657 FIB_TEST(fib_test_validate_entry(fei,
1658 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1659 1,
Neale Ranns81424992017-05-18 03:03:22 -07001660 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001661 "6.6.6.6/32 via 10.10.10.1");
1662
1663 fib_table_entry_path_add(fib_index,
1664 &pfx_6_6_6_6_s_32,
1665 FIB_SOURCE_API,
1666 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001667 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001668 &nh_10_10_10_2,
1669 tm->hw[0]->sw_if_index,
1670 ~0, // invalid fib index
1671 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001672 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001673 FIB_ROUTE_PATH_FLAG_NONE);
1674
1675 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1676 FIB_TEST(fib_test_validate_entry(fei,
1677 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1678 64,
Neale Ranns81424992017-05-18 03:03:22 -07001679 &ip_o_10_10_10_2,
1680 &ip_o_10_10_10_2,
1681 &ip_o_10_10_10_2,
1682 &ip_o_10_10_10_2,
1683 &ip_o_10_10_10_2,
1684 &ip_o_10_10_10_2,
1685 &ip_o_10_10_10_2,
1686 &ip_o_10_10_10_2,
1687 &ip_o_10_10_10_2,
1688 &ip_o_10_10_10_2,
1689 &ip_o_10_10_10_2,
1690 &ip_o_10_10_10_2,
1691 &ip_o_10_10_10_2,
1692 &ip_o_10_10_10_2,
1693 &ip_o_10_10_10_2,
1694 &ip_o_10_10_10_2,
1695 &ip_o_10_10_10_2,
1696 &ip_o_10_10_10_2,
1697 &ip_o_10_10_10_2,
1698 &ip_o_10_10_10_2,
1699 &ip_o_10_10_10_2,
1700 &ip_o_10_10_10_2,
1701 &ip_o_10_10_10_2,
1702 &ip_o_10_10_10_2,
1703 &ip_o_10_10_10_2,
1704 &ip_o_10_10_10_2,
1705 &ip_o_10_10_10_2,
1706 &ip_o_10_10_10_2,
1707 &ip_o_10_10_10_2,
1708 &ip_o_10_10_10_2,
1709 &ip_o_10_10_10_2,
1710 &ip_o_10_10_10_2,
1711 &ip_o_10_10_10_2,
1712 &ip_o_10_10_10_2,
1713 &ip_o_10_10_10_2,
1714 &ip_o_10_10_10_2,
1715 &ip_o_10_10_10_2,
1716 &ip_o_10_10_10_2,
1717 &ip_o_10_10_10_2,
1718 &ip_o_10_10_10_2,
1719 &ip_o_10_10_10_2,
1720 &ip_o_10_10_10_2,
1721 &ip_o_10_10_10_2,
1722 &ip_o_10_10_10_2,
1723 &ip_o_10_10_10_2,
1724 &ip_o_10_10_10_2,
1725 &ip_o_10_10_10_2,
1726 &ip_o_10_10_10_2,
1727 &ip_o_10_10_10_2,
1728 &ip_o_10_10_10_2,
1729 &ip_o_10_10_10_2,
1730 &ip_o_10_10_10_2,
1731 &ip_o_10_10_10_2,
1732 &ip_o_10_10_10_2,
1733 &ip_o_10_10_10_2,
1734 &ip_o_10_10_10_2,
1735 &ip_o_10_10_10_2,
1736 &ip_o_10_10_10_2,
1737 &ip_o_10_10_10_2,
1738 &ip_o_10_10_10_2,
1739 &ip_o_10_10_10_2,
1740 &ip_o_10_10_10_2,
1741 &ip_o_10_10_10_2,
1742 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001743 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1744
1745 fib_table_entry_path_add(fib_index,
1746 &pfx_6_6_6_6_s_32,
1747 FIB_SOURCE_API,
1748 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001749 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001750 &nh_12_12_12_12,
1751 tm->hw[1]->sw_if_index,
1752 ~0, // invalid fib index
1753 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001754 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001755 FIB_ROUTE_PATH_FLAG_NONE);
1756
1757 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1758 FIB_TEST(fib_test_validate_entry(fei,
1759 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1760 128,
Neale Ranns81424992017-05-18 03:03:22 -07001761 &ip_o_10_10_10_1,
1762 &ip_o_10_10_10_2,
1763 &ip_o_10_10_10_2,
1764 &ip_o_10_10_10_2,
1765 &ip_o_10_10_10_2,
1766 &ip_o_10_10_10_2,
1767 &ip_o_10_10_10_2,
1768 &ip_o_10_10_10_2,
1769 &ip_o_10_10_10_2,
1770 &ip_o_10_10_10_2,
1771 &ip_o_10_10_10_2,
1772 &ip_o_10_10_10_2,
1773 &ip_o_10_10_10_2,
1774 &ip_o_10_10_10_2,
1775 &ip_o_10_10_10_2,
1776 &ip_o_10_10_10_2,
1777 &ip_o_10_10_10_2,
1778 &ip_o_10_10_10_2,
1779 &ip_o_10_10_10_2,
1780 &ip_o_10_10_10_2,
1781 &ip_o_10_10_10_2,
1782 &ip_o_10_10_10_2,
1783 &ip_o_10_10_10_2,
1784 &ip_o_10_10_10_2,
1785 &ip_o_10_10_10_2,
1786 &ip_o_10_10_10_2,
1787 &ip_o_10_10_10_2,
1788 &ip_o_10_10_10_2,
1789 &ip_o_10_10_10_2,
1790 &ip_o_10_10_10_2,
1791 &ip_o_10_10_10_2,
1792 &ip_o_10_10_10_2,
1793 &ip_o_10_10_10_2,
1794 &ip_o_10_10_10_2,
1795 &ip_o_10_10_10_2,
1796 &ip_o_10_10_10_2,
1797 &ip_o_10_10_10_2,
1798 &ip_o_10_10_10_2,
1799 &ip_o_10_10_10_2,
1800 &ip_o_10_10_10_2,
1801 &ip_o_10_10_10_2,
1802 &ip_o_10_10_10_2,
1803 &ip_o_10_10_10_2,
1804 &ip_o_10_10_10_2,
1805 &ip_o_10_10_10_2,
1806 &ip_o_10_10_10_2,
1807 &ip_o_10_10_10_2,
1808 &ip_o_10_10_10_2,
1809 &ip_o_10_10_10_2,
1810 &ip_o_10_10_10_2,
1811 &ip_o_10_10_10_2,
1812 &ip_o_10_10_10_2,
1813 &ip_o_10_10_10_2,
1814 &ip_o_10_10_10_2,
1815 &ip_o_10_10_10_2,
1816 &ip_o_10_10_10_2,
1817 &ip_o_10_10_10_2,
1818 &ip_o_10_10_10_2,
1819 &ip_o_10_10_10_2,
1820 &ip_o_10_10_10_2,
1821 &ip_o_10_10_10_2,
1822 &ip_o_10_10_10_2,
1823 &ip_o_10_10_10_2,
1824 &ip_o_10_10_10_2,
1825 &ip_o_10_10_10_2,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001826 &ip_6_6_6_6_o_12_12_12_12,
1827 &ip_6_6_6_6_o_12_12_12_12,
1828 &ip_6_6_6_6_o_12_12_12_12,
1829 &ip_6_6_6_6_o_12_12_12_12,
1830 &ip_6_6_6_6_o_12_12_12_12,
1831 &ip_6_6_6_6_o_12_12_12_12,
1832 &ip_6_6_6_6_o_12_12_12_12,
1833 &ip_6_6_6_6_o_12_12_12_12,
1834 &ip_6_6_6_6_o_12_12_12_12,
1835 &ip_6_6_6_6_o_12_12_12_12,
1836 &ip_6_6_6_6_o_12_12_12_12,
1837 &ip_6_6_6_6_o_12_12_12_12,
1838 &ip_6_6_6_6_o_12_12_12_12,
1839 &ip_6_6_6_6_o_12_12_12_12,
1840 &ip_6_6_6_6_o_12_12_12_12,
1841 &ip_6_6_6_6_o_12_12_12_12,
1842 &ip_6_6_6_6_o_12_12_12_12,
1843 &ip_6_6_6_6_o_12_12_12_12,
1844 &ip_6_6_6_6_o_12_12_12_12,
1845 &ip_6_6_6_6_o_12_12_12_12,
1846 &ip_6_6_6_6_o_12_12_12_12,
1847 &ip_6_6_6_6_o_12_12_12_12,
1848 &ip_6_6_6_6_o_12_12_12_12,
1849 &ip_6_6_6_6_o_12_12_12_12,
1850 &ip_6_6_6_6_o_12_12_12_12,
1851 &ip_6_6_6_6_o_12_12_12_12,
1852 &ip_6_6_6_6_o_12_12_12_12,
1853 &ip_6_6_6_6_o_12_12_12_12,
1854 &ip_6_6_6_6_o_12_12_12_12,
1855 &ip_6_6_6_6_o_12_12_12_12,
1856 &ip_6_6_6_6_o_12_12_12_12,
1857 &ip_6_6_6_6_o_12_12_12_12,
1858 &ip_6_6_6_6_o_12_12_12_12,
1859 &ip_6_6_6_6_o_12_12_12_12,
1860 &ip_6_6_6_6_o_12_12_12_12,
1861 &ip_6_6_6_6_o_12_12_12_12,
1862 &ip_6_6_6_6_o_12_12_12_12,
1863 &ip_6_6_6_6_o_12_12_12_12,
1864 &ip_6_6_6_6_o_12_12_12_12,
1865 &ip_6_6_6_6_o_12_12_12_12,
1866 &ip_6_6_6_6_o_12_12_12_12,
1867 &ip_6_6_6_6_o_12_12_12_12,
1868 &ip_6_6_6_6_o_12_12_12_12,
1869 &ip_6_6_6_6_o_12_12_12_12,
1870 &ip_6_6_6_6_o_12_12_12_12,
1871 &ip_6_6_6_6_o_12_12_12_12,
1872 &ip_6_6_6_6_o_12_12_12_12,
1873 &ip_6_6_6_6_o_12_12_12_12,
1874 &ip_6_6_6_6_o_12_12_12_12,
1875 &ip_6_6_6_6_o_12_12_12_12,
1876 &ip_6_6_6_6_o_12_12_12_12,
1877 &ip_6_6_6_6_o_12_12_12_12,
1878 &ip_6_6_6_6_o_12_12_12_12,
1879 &ip_6_6_6_6_o_12_12_12_12,
1880 &ip_6_6_6_6_o_12_12_12_12,
1881 &ip_6_6_6_6_o_12_12_12_12,
1882 &ip_6_6_6_6_o_12_12_12_12,
1883 &ip_6_6_6_6_o_12_12_12_12,
1884 &ip_6_6_6_6_o_12_12_12_12,
1885 &ip_6_6_6_6_o_12_12_12_12,
1886 &ip_6_6_6_6_o_12_12_12_12,
1887 &ip_6_6_6_6_o_12_12_12_12,
1888 &ip_6_6_6_6_o_12_12_12_12),
1889 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1890
1891 fib_table_entry_path_remove(fib_index,
1892 &pfx_6_6_6_6_s_32,
1893 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001894 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001895 &nh_12_12_12_12,
1896 tm->hw[1]->sw_if_index,
1897 ~0, // invalid fib index
1898 100,
1899 FIB_ROUTE_PATH_FLAG_NONE);
1900
1901 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1902 FIB_TEST(fib_test_validate_entry(fei,
1903 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1904 64,
Neale Ranns81424992017-05-18 03:03:22 -07001905 &ip_o_10_10_10_2,
1906 &ip_o_10_10_10_2,
1907 &ip_o_10_10_10_2,
1908 &ip_o_10_10_10_2,
1909 &ip_o_10_10_10_2,
1910 &ip_o_10_10_10_2,
1911 &ip_o_10_10_10_2,
1912 &ip_o_10_10_10_2,
1913 &ip_o_10_10_10_2,
1914 &ip_o_10_10_10_2,
1915 &ip_o_10_10_10_2,
1916 &ip_o_10_10_10_2,
1917 &ip_o_10_10_10_2,
1918 &ip_o_10_10_10_2,
1919 &ip_o_10_10_10_2,
1920 &ip_o_10_10_10_2,
1921 &ip_o_10_10_10_2,
1922 &ip_o_10_10_10_2,
1923 &ip_o_10_10_10_2,
1924 &ip_o_10_10_10_2,
1925 &ip_o_10_10_10_2,
1926 &ip_o_10_10_10_2,
1927 &ip_o_10_10_10_2,
1928 &ip_o_10_10_10_2,
1929 &ip_o_10_10_10_2,
1930 &ip_o_10_10_10_2,
1931 &ip_o_10_10_10_2,
1932 &ip_o_10_10_10_2,
1933 &ip_o_10_10_10_2,
1934 &ip_o_10_10_10_2,
1935 &ip_o_10_10_10_2,
1936 &ip_o_10_10_10_2,
1937 &ip_o_10_10_10_2,
1938 &ip_o_10_10_10_2,
1939 &ip_o_10_10_10_2,
1940 &ip_o_10_10_10_2,
1941 &ip_o_10_10_10_2,
1942 &ip_o_10_10_10_2,
1943 &ip_o_10_10_10_2,
1944 &ip_o_10_10_10_2,
1945 &ip_o_10_10_10_2,
1946 &ip_o_10_10_10_2,
1947 &ip_o_10_10_10_2,
1948 &ip_o_10_10_10_2,
1949 &ip_o_10_10_10_2,
1950 &ip_o_10_10_10_2,
1951 &ip_o_10_10_10_2,
1952 &ip_o_10_10_10_2,
1953 &ip_o_10_10_10_2,
1954 &ip_o_10_10_10_2,
1955 &ip_o_10_10_10_2,
1956 &ip_o_10_10_10_2,
1957 &ip_o_10_10_10_2,
1958 &ip_o_10_10_10_2,
1959 &ip_o_10_10_10_2,
1960 &ip_o_10_10_10_2,
1961 &ip_o_10_10_10_2,
1962 &ip_o_10_10_10_2,
1963 &ip_o_10_10_10_2,
1964 &ip_o_10_10_10_2,
1965 &ip_o_10_10_10_2,
1966 &ip_o_10_10_10_2,
1967 &ip_o_10_10_10_2,
1968 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001969 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1970
1971 fib_table_entry_path_remove(fib_index,
1972 &pfx_6_6_6_6_s_32,
1973 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001974 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001975 &nh_10_10_10_2,
1976 tm->hw[0]->sw_if_index,
1977 ~0, // invalid fib index
1978 100,
1979 FIB_ROUTE_PATH_FLAG_NONE);
1980
1981 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1982 FIB_TEST(fib_test_validate_entry(fei,
1983 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1984 1,
Neale Ranns81424992017-05-18 03:03:22 -07001985 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001986 "6.6.6.6/32 via 10.10.10.1");
1987
1988 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1989
1990 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001991 * A recursive via the two unequal cost entries
1992 */
1993 fib_prefix_t bgp_44_s_32 = {
1994 .fp_len = 32,
1995 .fp_proto = FIB_PROTOCOL_IP4,
1996 .fp_addr = {
1997 /* 200.200.200.201/32 */
1998 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1999 },
2000 };
2001 fei = fib_table_entry_path_add(fib_index,
2002 &bgp_44_s_32,
2003 FIB_SOURCE_API,
2004 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002005 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01002006 &pfx_1_2_3_4_s_32.fp_addr,
2007 ~0,
2008 fib_index,
2009 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002010 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002011 FIB_ROUTE_PATH_FLAG_NONE);
2012 fei = fib_table_entry_path_add(fib_index,
2013 &bgp_44_s_32,
2014 FIB_SOURCE_API,
2015 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002016 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01002017 &pfx_1_2_3_5_s_32.fp_addr,
2018 ~0,
2019 fib_index,
2020 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002021 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01002022 FIB_ROUTE_PATH_FLAG_NONE);
2023
2024 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
2025 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
2026 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
2027 tm->hw[0]->sw_if_index,
2028 tm->hw[1]->sw_if_index),
2029 "RPF list for 1.2.3.4/32 contains both adjs");
2030
2031 /*
2032 * test the uRPF check functions
2033 */
Neale Ranns948e00f2016-10-20 13:39:34 +01002034 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01002035 index_t urpfi;
2036
2037 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
2038 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
2039
2040 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2041 "uRPF check for 68.68.68.68/32 on %d OK",
2042 tm->hw[0]->sw_if_index);
2043 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2044 "uRPF check for 68.68.68.68/32 on %d OK",
2045 tm->hw[1]->sw_if_index);
2046 FIB_TEST(!fib_urpf_check(urpfi, 99),
2047 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2048 99);
2049 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002050
2051 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002052 &bgp_44_s_32,
2053 FIB_SOURCE_API);
2054 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002055 &pfx_1_2_3_5_s_32,
2056 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002057 fib_table_entry_delete(fib_index,
2058 &pfx_1_2_3_4_s_32,
2059 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002060
2061 /*
2062 * Add a recursive route:
2063 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2064 */
2065 fib_prefix_t bgp_201_pfx = {
2066 .fp_len = 32,
2067 .fp_proto = FIB_PROTOCOL_IP4,
2068 .fp_addr = {
2069 /* 200.200.200.201/32 */
2070 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2071 },
2072 };
2073 /* via 1.1.1.200 */
2074 fib_prefix_t pfx_1_1_1_200_s_32 = {
2075 .fp_len = 32,
2076 .fp_proto = FIB_PROTOCOL_IP4,
2077 .fp_addr = {
2078 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2079 },
2080 };
2081
Neale Ranns57b58602017-07-15 07:37:25 -07002082 fei = fib_table_entry_path_add(fib_index,
2083 &bgp_201_pfx,
2084 FIB_SOURCE_API,
2085 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002086 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002087 &pfx_1_1_1_200_s_32.fp_addr,
2088 ~0, // no index provided.
2089 fib_index, // nexthop in same fib as route
2090 1,
2091 NULL,
2092 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002093
Neale Ranns57b58602017-07-15 07:37:25 -07002094 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2095 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002096
2097 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2098 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2099 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002100 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2101 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002102
2103 /*
2104 * +2 entry (BGP & RR) and +1 shared-path-list
2105 */
2106 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2107 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002108 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002109 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002110 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002111 fib_entry_pool_size());
2112
2113 /*
2114 * insert a route that covers the missing 1.1.1.2/32. we epxect
2115 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2116 */
2117 fib_prefix_t pfx_1_1_1_0_s_24 = {
2118 .fp_len = 24,
2119 .fp_proto = FIB_PROTOCOL_IP4,
2120 .fp_addr = {
2121 /* 1.1.1.0/24 */
2122 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2123 },
2124 };
2125
2126 fib_table_entry_path_add(fib_index,
2127 &pfx_1_1_1_0_s_24,
2128 FIB_SOURCE_API,
2129 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002130 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002131 &nh_10_10_10_1,
2132 tm->hw[0]->sw_if_index,
2133 ~0, // invalid fib index
2134 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002135 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002136 FIB_ROUTE_PATH_FLAG_NONE);
2137 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2138 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2139 ai = fib_entry_get_adj(fei);
2140 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2141 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2142 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2143 ai = fib_entry_get_adj(fei);
2144 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2145 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2146 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2147 ai = fib_entry_get_adj(fei);
2148 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2149
2150 /*
2151 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2152 */
2153 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2154 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002155 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002156 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002157 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002158 fib_entry_pool_size());
2159
2160 /*
2161 * the recursive adj for 200.200.200.200 should be updated.
2162 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002163 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2164 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2165 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2166 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2167 tm->hw[0]->sw_if_index),
2168 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002169
2170 /*
2171 * insert a more specific route than 1.1.1.0/24 that also covers the
2172 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2173 * 200.200.200.200 to resolve through it.
2174 */
2175 fib_prefix_t pfx_1_1_1_0_s_28 = {
2176 .fp_len = 28,
2177 .fp_proto = FIB_PROTOCOL_IP4,
2178 .fp_addr = {
2179 /* 1.1.1.0/24 */
2180 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2181 },
2182 };
2183
2184 fib_table_entry_path_add(fib_index,
2185 &pfx_1_1_1_0_s_28,
2186 FIB_SOURCE_API,
2187 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002188 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002189 &nh_10_10_10_2,
2190 tm->hw[0]->sw_if_index,
2191 ~0, // invalid fib index
2192 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002193 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002194 FIB_ROUTE_PATH_FLAG_NONE);
2195 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2196 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2197 ai = fib_entry_get_adj(fei);
2198 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2199
2200 /*
2201 * +1 entry. +1 shared path-list
2202 */
2203 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2204 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002205 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002206 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002207 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002208 fib_entry_pool_size());
2209
2210 /*
2211 * the recursive adj for 200.200.200.200 should be updated.
2212 * 200.200.200.201 remains unchanged.
2213 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002214 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2215 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002216
2217 /*
2218 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2219 */
2220 fib_table_entry_path_remove(fib_index,
2221 &pfx_1_1_1_0_s_28,
2222 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002223 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002224 &nh_10_10_10_2,
2225 tm->hw[0]->sw_if_index,
2226 ~0,
2227 1,
2228 FIB_ROUTE_PATH_FLAG_NONE);
2229 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2230 FIB_NODE_INDEX_INVALID),
2231 "1.1.1.0/28 removed");
2232 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2233 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2234 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002235 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2236 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002237
2238 /*
2239 * -1 entry. -1 shared path-list
2240 */
2241 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2242 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002243 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002244 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002245 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002246 fib_entry_pool_size());
2247
2248 /*
2249 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2250 */
2251 fib_table_entry_path_remove(fib_index,
2252 &pfx_1_1_1_0_s_24,
2253 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002254 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002255 &nh_10_10_10_1,
2256 tm->hw[0]->sw_if_index,
2257 ~0,
2258 1,
2259 FIB_ROUTE_PATH_FLAG_NONE);
2260 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2261 FIB_NODE_INDEX_INVALID),
2262 "1.1.1.0/24 removed");
2263
2264 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2265 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2266 "1.1.1.2/32 route is DROP");
Neale Ranns57b58602017-07-15 07:37:25 -07002267 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002268 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2269 "1.1.1.200/32 route is DROP");
2270
Neale Ranns57b58602017-07-15 07:37:25 -07002271 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2272 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2273 "201 is drop");
2274 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2275 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2276 "200 is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002277
2278 /*
2279 * -1 entry
2280 */
2281 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2282 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002283 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002284 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002285 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002286 fib_entry_pool_size());
2287
2288 /*
2289 * insert the missing 1.1.1.2/32
2290 */
2291 fei = fib_table_entry_path_add(fib_index,
2292 &pfx_1_1_1_2_s_32,
2293 FIB_SOURCE_API,
2294 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002295 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002296 &nh_10_10_10_1,
2297 tm->hw[0]->sw_if_index,
2298 ~0, // invalid fib index
2299 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002300 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002301 FIB_ROUTE_PATH_FLAG_NONE);
2302 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2303 ai = fib_entry_get_adj(fei);
2304 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2305
Neale Ranns57b58602017-07-15 07:37:25 -07002306 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2307 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2308 "201 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01002309 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002310
2311 /*
2312 * no change. 1.1.1.2/32 was already there RR sourced.
2313 */
2314 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2315 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002316 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002317 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002318 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002319 fib_entry_pool_size());
2320
2321 /*
Neale Ranns57b58602017-07-15 07:37:25 -07002322 * give 201 a resolved path.
2323 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2324 * only the latter contributes forwarding.
2325 */
2326 fei = fib_table_entry_path_add(fib_index,
2327 &bgp_201_pfx,
2328 FIB_SOURCE_API,
2329 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002330 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002331 &pfx_1_1_1_2_s_32.fp_addr,
2332 ~0,
2333 fib_index,
2334 1,
2335 NULL,
2336 FIB_ROUTE_PATH_FLAG_NONE);
2337 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2338 fib_table_entry_path_remove(fib_index,
2339 &bgp_201_pfx,
2340 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002341 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002342 &pfx_1_1_1_2_s_32.fp_addr,
2343 ~0,
2344 fib_index,
2345 1,
2346 FIB_ROUTE_PATH_FLAG_NONE);
2347
2348 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002349 * remove 200.200.200.201/32 which does not have a valid via FIB
2350 */
2351 fib_table_entry_path_remove(fib_index,
2352 &bgp_201_pfx,
2353 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002354 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002355 &pfx_1_1_1_200_s_32.fp_addr,
2356 ~0, // no index provided.
2357 fib_index,
2358 1,
2359 FIB_ROUTE_PATH_FLAG_NONE);
2360
2361 /*
2362 * -2 entries (BGP and RR). -1 shared path-list;
2363 */
2364 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2365 FIB_NODE_INDEX_INVALID),
2366 "200.200.200.201/32 removed");
2367 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2368 FIB_NODE_INDEX_INVALID),
2369 "1.1.1.200/32 removed");
2370
2371 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2372 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002373 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002374 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002375 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002376 fib_entry_pool_size());
2377
2378 /*
2379 * remove 200.200.200.200/32 which does have a valid via FIB
2380 */
2381 fib_table_entry_path_remove(fib_index,
2382 &bgp_200_pfx,
2383 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002384 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002385 &pfx_1_1_1_2_s_32.fp_addr,
2386 ~0, // no index provided.
2387 fib_index,
2388 1,
2389 FIB_ROUTE_PATH_FLAG_NONE);
2390
2391 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2392 FIB_NODE_INDEX_INVALID),
2393 "200.200.200.200/32 removed");
2394 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2395 FIB_NODE_INDEX_INVALID),
2396 "1.1.1.2/32 still present");
2397
2398 /*
2399 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2400 */
2401 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2402 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002403 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002404 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002405 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002406 fib_entry_pool_size());
2407
2408 /*
2409 * A recursive prefix that has a 2 path load-balance.
2410 * It also shares a next-hop with other BGP prefixes and hence
2411 * test the ref counting of RR sourced prefixes and 2 level LB.
2412 */
2413 const fib_prefix_t bgp_102 = {
2414 .fp_len = 32,
2415 .fp_proto = FIB_PROTOCOL_IP4,
2416 .fp_addr = {
2417 /* 100.100.100.101/32 */
2418 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2419 },
2420 };
2421 fib_table_entry_path_add(fib_index,
2422 &bgp_102,
2423 FIB_SOURCE_API,
2424 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002425 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002426 &pfx_1_1_1_1_s_32.fp_addr,
2427 ~0, // no index provided.
2428 fib_index, // same as route
2429 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002430 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002431 FIB_ROUTE_PATH_FLAG_NONE);
2432 fib_table_entry_path_add(fib_index,
2433 &bgp_102,
2434 FIB_SOURCE_API,
2435 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002436 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002437 &pfx_1_1_1_2_s_32.fp_addr,
2438 ~0, // no index provided.
2439 fib_index, // same as route's FIB
2440 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002441 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002442 FIB_ROUTE_PATH_FLAG_NONE);
2443 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2444 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2445 dpo = fib_entry_contribute_ip_forwarding(fei);
2446
2447 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2448 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2449 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2450 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2451
2452 lb = load_balance_get(dpo->dpoi_index);
2453 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2454 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2455 "First via 10.10.10.1");
2456 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2457 "Second via 10.10.10.1");
2458
2459 fib_table_entry_path_remove(fib_index,
2460 &bgp_102,
2461 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002462 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002463 &pfx_1_1_1_1_s_32.fp_addr,
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_102,
2470 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002471 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002472 &pfx_1_1_1_2_s_32.fp_addr,
2473 ~0, // no index provided.
2474 fib_index, // same as route's FIB
2475 1,
2476 FIB_ROUTE_PATH_FLAG_NONE);
2477 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2478 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2479
2480 /*
2481 * remove the remaining recursives
2482 */
2483 fib_table_entry_path_remove(fib_index,
2484 &bgp_100_pfx,
2485 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002486 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002487 &pfx_1_1_1_1_s_32.fp_addr,
2488 ~0, // no index provided.
2489 fib_index, // same as route's FIB
2490 1,
2491 FIB_ROUTE_PATH_FLAG_NONE);
2492 fib_table_entry_path_remove(fib_index,
2493 &bgp_101_pfx,
2494 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002495 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002496 &pfx_1_1_1_1_s_32.fp_addr,
2497 ~0, // no index provided.
2498 fib_index, // same as route's FIB
2499 1,
2500 FIB_ROUTE_PATH_FLAG_NONE);
2501 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2502 FIB_NODE_INDEX_INVALID),
2503 "100.100.100.100/32 removed");
2504 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2505 FIB_NODE_INDEX_INVALID),
2506 "100.100.100.101/32 removed");
2507
2508 /*
2509 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2510 */
2511 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2512 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002513 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002514 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002515 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002516 fib_entry_pool_size());
2517
2518 /*
2519 * Add a recursive route via a connected cover, using an adj-fib that does exist
2520 */
2521 fib_table_entry_path_add(fib_index,
2522 &bgp_200_pfx,
2523 FIB_SOURCE_API,
2524 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002525 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002526 &nh_10_10_10_1,
2527 ~0, // no index provided.
2528 fib_index, // Same as route's FIB
2529 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002530 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002531 FIB_ROUTE_PATH_FLAG_NONE);
2532
2533 /*
2534 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2535 */
2536 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2537 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002538 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002539 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002540 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002541 fib_entry_pool_size());
2542
2543 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2544 dpo = fib_entry_contribute_ip_forwarding(fei);
2545
2546 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2547 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2548
2549 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2550 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2551
2552 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2553 "Flags set on RR via existing attached");
2554
2555 /*
2556 * Add a recursive route via a connected cover, using and adj-fib that does
2557 * not exist
2558 */
2559 ip46_address_t nh_10_10_10_3 = {
2560 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2561 };
2562 fib_prefix_t pfx_10_10_10_3 = {
2563 .fp_len = 32,
2564 .fp_proto = FIB_PROTOCOL_IP4,
2565 .fp_addr = nh_10_10_10_3,
2566 };
2567
2568 fib_table_entry_path_add(fib_index,
2569 &bgp_201_pfx,
2570 FIB_SOURCE_API,
2571 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002572 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002573 &nh_10_10_10_3,
2574 ~0, // no index provided.
2575 fib_index,
2576 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002577 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002578 FIB_ROUTE_PATH_FLAG_NONE);
2579
2580 /*
2581 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2582 * one unshared non-recursive via 10.10.10.3
2583 */
2584 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2585 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002586 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002587 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002588 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002589 fib_entry_pool_size());
2590
2591 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002592 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002593 &nh_10_10_10_3,
2594 tm->hw[0]->sw_if_index);
2595
2596 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2597 dpo = fib_entry_contribute_ip_forwarding(fei);
2598 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2599 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2600
2601 ai = fib_entry_get_adj(fei);
2602 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2603 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2604 fib_entry_get_flags(fei)),
2605 "Flags set on RR via non-existing attached");
2606
2607 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2608 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2609
2610 adj_unlock(ai_03);
2611
2612 /*
2613 * remove the recursives
2614 */
2615 fib_table_entry_path_remove(fib_index,
2616 &bgp_200_pfx,
2617 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002618 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002619 &nh_10_10_10_1,
2620 ~0, // no index provided.
2621 fib_index, // same as route's FIB
2622 1,
2623 FIB_ROUTE_PATH_FLAG_NONE);
2624 fib_table_entry_path_remove(fib_index,
2625 &bgp_201_pfx,
2626 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002627 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002628 &nh_10_10_10_3,
2629 ~0, // no index provided.
2630 fib_index, // same as route's FIB
2631 1,
2632 FIB_ROUTE_PATH_FLAG_NONE);
2633
2634 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2635 FIB_NODE_INDEX_INVALID),
2636 "200.200.200.201/32 removed");
2637 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2638 FIB_NODE_INDEX_INVALID),
2639 "200.200.200.200/32 removed");
2640 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2641 FIB_NODE_INDEX_INVALID),
2642 "10.10.10.3/32 removed");
2643
2644 /*
2645 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2646 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2647 */
2648 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2649 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002650 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002651 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002652 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002653 fib_entry_pool_size());
2654
2655
2656 /*
2657 * RECURSION LOOPS
2658 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2659 */
2660 fib_prefix_t pfx_5_5_5_5_s_32 = {
2661 .fp_len = 32,
2662 .fp_proto = FIB_PROTOCOL_IP4,
2663 .fp_addr = {
2664 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2665 },
2666 };
2667 fib_prefix_t pfx_5_5_5_6_s_32 = {
2668 .fp_len = 32,
2669 .fp_proto = FIB_PROTOCOL_IP4,
2670 .fp_addr = {
2671 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2672 },
2673 };
2674 fib_prefix_t pfx_5_5_5_7_s_32 = {
2675 .fp_len = 32,
2676 .fp_proto = FIB_PROTOCOL_IP4,
2677 .fp_addr = {
2678 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2679 },
2680 };
2681
2682 fib_table_entry_path_add(fib_index,
2683 &pfx_5_5_5_5_s_32,
2684 FIB_SOURCE_API,
2685 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002686 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002687 &pfx_5_5_5_6_s_32.fp_addr,
2688 ~0, // no index provided.
2689 fib_index,
2690 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002691 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002692 FIB_ROUTE_PATH_FLAG_NONE);
2693 fib_table_entry_path_add(fib_index,
2694 &pfx_5_5_5_6_s_32,
2695 FIB_SOURCE_API,
2696 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002697 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002698 &pfx_5_5_5_7_s_32.fp_addr,
2699 ~0, // no index provided.
2700 fib_index,
2701 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002702 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002703 FIB_ROUTE_PATH_FLAG_NONE);
2704 fib_table_entry_path_add(fib_index,
2705 &pfx_5_5_5_7_s_32,
2706 FIB_SOURCE_API,
2707 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002708 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002709 &pfx_5_5_5_5_s_32.fp_addr,
2710 ~0, // no index provided.
2711 fib_index,
2712 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002713 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002714 FIB_ROUTE_PATH_FLAG_NONE);
2715 /*
2716 * +3 entries, +3 shared path-list
2717 */
2718 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2719 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002720 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002721 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002722 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002723 fib_entry_pool_size());
2724
2725 /*
2726 * All the entries have only looped paths, so they are all drop
2727 */
2728 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2729 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2730 "LB for 5.5.5.7/32 is via adj for DROP");
2731 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2732 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2733 "LB for 5.5.5.5/32 is via adj for DROP");
2734 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2735 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2736 "LB for 5.5.5.6/32 is via adj for DROP");
2737
2738 /*
2739 * provide 5.5.5.6/32 with alternate path.
2740 * this will allow only 5.5.5.6/32 to forward with this path, the others
2741 * are still drop since the loop is still present.
2742 */
2743 fib_table_entry_path_add(fib_index,
2744 &pfx_5_5_5_6_s_32,
2745 FIB_SOURCE_API,
2746 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002747 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002748 &nh_10_10_10_1,
2749 tm->hw[0]->sw_if_index,
2750 ~0,
2751 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002752 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002753 FIB_ROUTE_PATH_FLAG_NONE);
2754
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002755 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2756 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2757
2758 lb = load_balance_get(dpo1->dpoi_index);
2759 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2760
2761 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2762 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2763 FIB_TEST((ai_01 == dpo2->dpoi_index),
2764 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2765
2766 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2767 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2768 "LB for 5.5.5.7/32 is via adj for DROP");
2769 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2770 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2771 "LB for 5.5.5.5/32 is via adj for DROP");
2772
2773 /*
2774 * remove the alternate path for 5.5.5.6/32
2775 * back to all drop
2776 */
2777 fib_table_entry_path_remove(fib_index,
2778 &pfx_5_5_5_6_s_32,
2779 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002780 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002781 &nh_10_10_10_1,
2782 tm->hw[0]->sw_if_index,
2783 ~0,
2784 1,
2785 FIB_ROUTE_PATH_FLAG_NONE);
2786
2787 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2788 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2789 "LB for 5.5.5.7/32 is via adj for DROP");
2790 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2791 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2792 "LB for 5.5.5.5/32 is via adj for DROP");
2793 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2794 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2795 "LB for 5.5.5.6/32 is via adj for DROP");
2796
2797 /*
2798 * break the loop by giving 5.5.5.5/32 a new set of paths
2799 * expect all to forward via this new path.
2800 */
2801 fib_table_entry_update_one_path(fib_index,
2802 &pfx_5_5_5_5_s_32,
2803 FIB_SOURCE_API,
2804 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002805 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002806 &nh_10_10_10_1,
2807 tm->hw[0]->sw_if_index,
2808 ~0, // invalid fib index
2809 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002810 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002811 FIB_ROUTE_PATH_FLAG_NONE);
2812
2813 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2814 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2815 lb = load_balance_get(dpo1->dpoi_index);
2816 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2817
2818 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2819 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2820 FIB_TEST((ai_01 == dpo2->dpoi_index),
2821 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2822
2823 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2824 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2825
2826 lb = load_balance_get(dpo2->dpoi_index);
2827 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2828 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2829 "5.5.5.5.7 via 5.5.5.5");
2830
2831 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2832 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2833
2834 lb = load_balance_get(dpo1->dpoi_index);
2835 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2836 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2837 "5.5.5.5.6 via 5.5.5.7");
2838
2839 /*
2840 * revert back to the loop. so we can remove the prefixes with
2841 * the loop intact
2842 */
2843 fib_table_entry_update_one_path(fib_index,
2844 &pfx_5_5_5_5_s_32,
2845 FIB_SOURCE_API,
2846 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002847 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002848 &pfx_5_5_5_6_s_32.fp_addr,
2849 ~0, // no index provided.
2850 fib_index,
2851 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002852 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002853 FIB_ROUTE_PATH_FLAG_NONE);
2854
2855 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2856 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2857 "LB for 5.5.5.7/32 is via adj for DROP");
2858 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2859 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2860 "LB for 5.5.5.5/32 is via adj for DROP");
2861 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2862 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2863 "LB for 5.5.5.6/32 is via adj for DROP");
2864
2865 /*
2866 * remove all the 5.5.5.x/32 prefixes
2867 */
2868 fib_table_entry_path_remove(fib_index,
2869 &pfx_5_5_5_5_s_32,
2870 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002871 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002872 &pfx_5_5_5_6_s_32.fp_addr,
2873 ~0, // no index provided.
2874 fib_index, // same as route's FIB
2875 1,
2876 FIB_ROUTE_PATH_FLAG_NONE);
2877 fib_table_entry_path_remove(fib_index,
2878 &pfx_5_5_5_6_s_32,
2879 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002880 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002881 &pfx_5_5_5_7_s_32.fp_addr,
2882 ~0, // no index provided.
2883 fib_index, // same as route's FIB
2884 1,
2885 FIB_ROUTE_PATH_FLAG_NONE);
2886 fib_table_entry_path_remove(fib_index,
2887 &pfx_5_5_5_7_s_32,
2888 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002889 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002890 &pfx_5_5_5_5_s_32.fp_addr,
2891 ~0, // no index provided.
2892 fib_index, // same as route's FIB
2893 1,
2894 FIB_ROUTE_PATH_FLAG_NONE);
2895 fib_table_entry_path_remove(fib_index,
2896 &pfx_5_5_5_6_s_32,
2897 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002898 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002899 &nh_10_10_10_2,
2900 ~0, // no index provided.
2901 fib_index, // same as route's FIB
2902 1,
2903 FIB_ROUTE_PATH_FLAG_NONE);
2904
2905 /*
2906 * -3 entries, -3 shared path-list
2907 */
2908 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2909 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002910 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002911 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002912 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002913 fib_entry_pool_size());
2914
2915 /*
2916 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2917 */
2918 fib_table_entry_path_add(fib_index,
2919 &pfx_5_5_5_6_s_32,
2920 FIB_SOURCE_API,
2921 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002922 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002923 &pfx_5_5_5_6_s_32.fp_addr,
2924 ~0, // no index provided.
2925 fib_index,
2926 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002927 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002928 FIB_ROUTE_PATH_FLAG_NONE);
2929 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2930 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2931 "1-level 5.5.5.6/32 loop is via adj for DROP");
2932
2933 fib_table_entry_path_remove(fib_index,
2934 &pfx_5_5_5_6_s_32,
2935 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002936 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002937 &pfx_5_5_5_6_s_32.fp_addr,
2938 ~0, // no index provided.
2939 fib_index, // same as route's FIB
2940 1,
2941 FIB_ROUTE_PATH_FLAG_NONE);
2942 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2943 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2944 "1-level 5.5.5.6/32 loop is removed");
2945
2946 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002947 * A recursive route whose next-hop is covered by the prefix.
2948 * This would mean the via-fib, which inherits forwarding from its
2949 * cover, thus picks up forwarding from the prfix, which is via the
2950 * via-fib, and we have a loop.
2951 */
2952 fib_prefix_t pfx_23_23_23_0_s_24 = {
2953 .fp_len = 24,
2954 .fp_proto = FIB_PROTOCOL_IP4,
2955 .fp_addr = {
2956 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2957 },
2958 };
2959 fib_prefix_t pfx_23_23_23_23_s_32 = {
2960 .fp_len = 32,
2961 .fp_proto = FIB_PROTOCOL_IP4,
2962 .fp_addr = {
2963 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2964 },
2965 };
2966 fei = fib_table_entry_path_add(fib_index,
2967 &pfx_23_23_23_0_s_24,
2968 FIB_SOURCE_API,
2969 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002970 DPO_PROTO_IP4,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002971 &pfx_23_23_23_23_s_32.fp_addr,
2972 ~0, // recursive
2973 fib_index,
2974 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002975 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002976 FIB_ROUTE_PATH_FLAG_NONE);
2977 dpo = fib_entry_contribute_ip_forwarding(fei);
2978 FIB_TEST(load_balance_is_drop(dpo),
2979 "23.23.23.0/24 via covered is DROP");
2980 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2981
2982 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002983 * add-remove test. no change.
2984 */
2985 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2986 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002987 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002988 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002989 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002990 fib_entry_pool_size());
2991
2992 /*
Neale Ranns08b16482017-05-13 05:52:58 -07002993 * Make the default route recursive via a unknown next-hop. Thus the
2994 * next hop's cover would be the default route
2995 */
2996 fei = fib_table_entry_path_add(fib_index,
2997 &pfx_0_0_0_0_s_0,
2998 FIB_SOURCE_API,
2999 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003000 DPO_PROTO_IP4,
Neale Ranns08b16482017-05-13 05:52:58 -07003001 &pfx_23_23_23_23_s_32.fp_addr,
3002 ~0, // recursive
3003 fib_index,
3004 1,
3005 NULL,
3006 FIB_ROUTE_PATH_FLAG_NONE);
3007 dpo = fib_entry_contribute_ip_forwarding(fei);
3008 FIB_TEST(load_balance_is_drop(dpo),
3009 "0.0.0.0.0/0 via is DROP");
3010 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3011 "no resolving interface for looped 0.0.0.0/0");
3012
3013 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
3014 dpo = fib_entry_contribute_ip_forwarding(fei);
3015 FIB_TEST(load_balance_is_drop(dpo),
3016 "23.23.23.23/32 via is DROP");
3017 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
3018 "no resolving interface for looped 23.23.23.23/32");
3019
3020 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
3021
3022 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003023 * A recursive route with recursion constraints.
3024 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
3025 */
3026 fib_table_entry_path_add(fib_index,
3027 &bgp_200_pfx,
3028 FIB_SOURCE_API,
3029 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003030 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003031 &nh_1_1_1_1,
3032 ~0,
3033 fib_index,
3034 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003035 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003036 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3037
3038 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3039 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3040
3041 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3042 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3043
3044 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3045 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3046
3047 /*
3048 * save the load-balance. we expect it to be inplace modified
3049 */
3050 lb = load_balance_get(dpo1->dpoi_index);
3051
3052 /*
3053 * add a covering prefix for the via fib that would otherwise serve
3054 * as the resolving route when the host is removed
3055 */
3056 fib_table_entry_path_add(fib_index,
3057 &pfx_1_1_1_0_s_28,
3058 FIB_SOURCE_API,
3059 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003060 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003061 &nh_10_10_10_1,
3062 tm->hw[0]->sw_if_index,
3063 ~0, // invalid fib index
3064 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003065 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003066 FIB_ROUTE_PATH_FLAG_NONE);
3067 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3068 ai = fib_entry_get_adj(fei);
3069 FIB_TEST((ai == ai_01),
3070 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3071
3072 /*
3073 * remove the host via FIB - expect the BGP prefix to be drop
3074 */
3075 fib_table_entry_path_remove(fib_index,
3076 &pfx_1_1_1_1_s_32,
3077 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003078 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003079 &nh_10_10_10_1,
3080 tm->hw[0]->sw_if_index,
3081 ~0, // invalid fib index
3082 1,
3083 FIB_ROUTE_PATH_FLAG_NONE);
3084
3085 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3086 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3087
3088 /*
3089 * add the via-entry host reoute back. expect to resolve again
3090 */
3091 fib_table_entry_path_add(fib_index,
3092 &pfx_1_1_1_1_s_32,
3093 FIB_SOURCE_API,
3094 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003095 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003096 &nh_10_10_10_1,
3097 tm->hw[0]->sw_if_index,
3098 ~0, // invalid fib index
3099 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003100 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003101 FIB_ROUTE_PATH_FLAG_NONE);
3102 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3103 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3104
3105 /*
3106 * add another path for the recursive. it will then have 2.
3107 */
3108 fib_prefix_t pfx_1_1_1_3_s_32 = {
3109 .fp_len = 32,
3110 .fp_proto = FIB_PROTOCOL_IP4,
3111 .fp_addr = {
3112 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3113 },
3114 };
3115 fib_table_entry_path_add(fib_index,
3116 &pfx_1_1_1_3_s_32,
3117 FIB_SOURCE_API,
3118 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003119 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003120 &nh_10_10_10_2,
3121 tm->hw[0]->sw_if_index,
3122 ~0, // invalid fib index
3123 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003124 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003125 FIB_ROUTE_PATH_FLAG_NONE);
3126
3127 fib_table_entry_path_add(fib_index,
3128 &bgp_200_pfx,
3129 FIB_SOURCE_API,
3130 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003131 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003132 &pfx_1_1_1_3_s_32.fp_addr,
3133 ~0,
3134 fib_index,
3135 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003136 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003137 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3138
Neale Rannsf12a83f2017-04-18 09:09:40 -07003139 /*
3140 * add a bunch load more entries using this path combo so that we get
3141 * an LB-map created.
3142 */
3143#define N_P 128
3144 fib_prefix_t bgp_78s[N_P];
3145 for (ii = 0; ii < N_P; ii++)
3146 {
3147 bgp_78s[ii].fp_len = 32;
3148 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3149 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3150
3151
3152 fib_table_entry_path_add(fib_index,
3153 &bgp_78s[ii],
3154 FIB_SOURCE_API,
3155 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003156 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003157 &pfx_1_1_1_3_s_32.fp_addr,
3158 ~0,
3159 fib_index,
3160 1,
3161 NULL,
3162 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3163 fib_table_entry_path_add(fib_index,
3164 &bgp_78s[ii],
3165 FIB_SOURCE_API,
3166 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003167 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003168 &nh_1_1_1_1,
3169 ~0,
3170 fib_index,
3171 1,
3172 NULL,
3173 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3174 }
3175
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003176 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3177 dpo = fib_entry_contribute_ip_forwarding(fei);
3178
3179 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3180 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3181 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3182 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3183 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3184 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3185 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3186 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3187
3188 /*
3189 * expect the lb-map used by the recursive's load-balance is using both buckets
3190 */
3191 load_balance_map_t *lbm;
3192 index_t lbmi;
3193
3194 lb = load_balance_get(dpo->dpoi_index);
3195 lbmi = lb->lb_map;
3196 load_balance_map_lock(lbmi);
3197 lbm = load_balance_map_get(lbmi);
3198
3199 FIB_TEST(lbm->lbm_buckets[0] == 0,
3200 "LB maps's bucket 0 is %d",
3201 lbm->lbm_buckets[0]);
3202 FIB_TEST(lbm->lbm_buckets[1] == 1,
3203 "LB maps's bucket 1 is %d",
3204 lbm->lbm_buckets[1]);
3205
3206 /*
3207 * withdraw one of the /32 via-entrys.
3208 * that ECMP path will be unresolved and forwarding should continue on the
3209 * other available path. this is an iBGP PIC edge failover.
3210 * Test the forwarding changes without re-fetching the adj from the
3211 * recursive entry. this ensures its the same one that is updated; i.e. an
3212 * inplace-modify.
3213 */
3214 fib_table_entry_path_remove(fib_index,
3215 &pfx_1_1_1_1_s_32,
3216 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003217 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003218 &nh_10_10_10_1,
3219 tm->hw[0]->sw_if_index,
3220 ~0, // invalid fib index
3221 1,
3222 FIB_ROUTE_PATH_FLAG_NONE);
3223
Neale Rannsf12a83f2017-04-18 09:09:40 -07003224 /* suspend so the update walk kicks int */
3225 vlib_process_suspend(vlib_get_main(), 1e-5);
3226
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003227 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3228 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3229 "post PIC 200.200.200.200/32 was inplace modified");
3230
3231 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3232 "post PIC adj for 200.200.200.200/32 is recursive"
3233 " via adj for 1.1.1.3");
3234
3235 /*
3236 * the LB maps that was locked above should have been modified to remove
3237 * the path that was down, and thus its bucket points to a path that is
3238 * still up.
3239 */
3240 FIB_TEST(lbm->lbm_buckets[0] == 1,
3241 "LB maps's bucket 0 is %d",
3242 lbm->lbm_buckets[0]);
3243 FIB_TEST(lbm->lbm_buckets[1] == 1,
3244 "LB maps's bucket 1 is %d",
3245 lbm->lbm_buckets[1]);
3246
Neale Ranns994dab42017-04-18 12:56:45 -07003247 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003248
3249 /*
3250 * add it back. again
3251 */
3252 fib_table_entry_path_add(fib_index,
3253 &pfx_1_1_1_1_s_32,
3254 FIB_SOURCE_API,
3255 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003256 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003257 &nh_10_10_10_1,
3258 tm->hw[0]->sw_if_index,
3259 ~0, // invalid fib index
3260 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003261 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003262 FIB_ROUTE_PATH_FLAG_NONE);
3263
Neale Rannsf12a83f2017-04-18 09:09:40 -07003264 /* suspend so the update walk kicks in */
3265 vlib_process_suspend(vlib_get_main(), 1e-5);
3266
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003267 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3268 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3269 "via adj for 1.1.1.1");
3270 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3271 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3272 "via adj for 1.1.1.3");
3273
3274 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3275 dpo = fib_entry_contribute_ip_forwarding(fei);
3276 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3277 "post PIC 200.200.200.200/32 was inplace modified");
3278
3279 /*
3280 * add a 3rd path. this makes the LB 16 buckets.
3281 */
3282 fib_table_entry_path_add(fib_index,
3283 &bgp_200_pfx,
3284 FIB_SOURCE_API,
3285 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003286 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003287 &pfx_1_1_1_2_s_32.fp_addr,
3288 ~0,
3289 fib_index,
3290 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003291 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003292 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003293 for (ii = 0; ii < N_P; ii++)
3294 {
3295 fib_table_entry_path_add(fib_index,
3296 &bgp_78s[ii],
3297 FIB_SOURCE_API,
3298 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003299 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003300 &pfx_1_1_1_2_s_32.fp_addr,
3301 ~0,
3302 fib_index,
3303 1,
3304 NULL,
3305 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3306 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003307
3308 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3309 dpo = fib_entry_contribute_ip_forwarding(fei);
3310 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3311 "200.200.200.200/32 was inplace modified for 3rd path");
3312 FIB_TEST(16 == lb->lb_n_buckets,
3313 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3314
3315 lbmi = lb->lb_map;
3316 load_balance_map_lock(lbmi);
3317 lbm = load_balance_map_get(lbmi);
3318
3319 for (ii = 0; ii < 16; ii++)
3320 {
3321 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3322 "LB Map for 200.200.200.200/32 at %d is %d",
3323 ii, lbm->lbm_buckets[ii]);
3324 }
3325
3326 /*
3327 * trigger PIC by removing the first via-entry
3328 * the first 6 buckets of the map should map to the next 6
3329 */
3330 fib_table_entry_path_remove(fib_index,
3331 &pfx_1_1_1_1_s_32,
3332 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003333 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003334 &nh_10_10_10_1,
3335 tm->hw[0]->sw_if_index,
3336 ~0,
3337 1,
3338 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003339 /* suspend so the update walk kicks int */
3340 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003341
3342 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3343 dpo = fib_entry_contribute_ip_forwarding(fei);
3344 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3345 "200.200.200.200/32 was inplace modified for 3rd path");
3346 FIB_TEST(2 == lb->lb_n_buckets,
3347 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3348
3349 for (ii = 0; ii < 6; ii++)
3350 {
3351 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3352 "LB Map for 200.200.200.200/32 at %d is %d",
3353 ii, lbm->lbm_buckets[ii]);
3354 }
3355 for (ii = 6; ii < 16; ii++)
3356 {
3357 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3358 "LB Map for 200.200.200.200/32 at %d is %d",
3359 ii, lbm->lbm_buckets[ii]);
3360 }
Neale Ranns994dab42017-04-18 12:56:45 -07003361 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003362
3363 /*
3364 * tidy up
3365 */
3366 fib_table_entry_path_add(fib_index,
3367 &pfx_1_1_1_1_s_32,
3368 FIB_SOURCE_API,
3369 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003370 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003371 &nh_10_10_10_1,
3372 tm->hw[0]->sw_if_index,
3373 ~0,
3374 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003375 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003376 FIB_ROUTE_PATH_FLAG_NONE);
3377
Neale Rannsf12a83f2017-04-18 09:09:40 -07003378 for (ii = 0; ii < N_P; ii++)
3379 {
3380 fib_table_entry_delete(fib_index,
3381 &bgp_78s[ii],
3382 FIB_SOURCE_API);
3383 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3384 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3385 "%U removed",
3386 format_fib_prefix, &bgp_78s[ii]);
3387 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003388 fib_table_entry_path_remove(fib_index,
3389 &bgp_200_pfx,
3390 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003391 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003392 &pfx_1_1_1_2_s_32.fp_addr,
3393 ~0,
3394 fib_index,
3395 1,
3396 MPLS_LABEL_INVALID);
3397 fib_table_entry_path_remove(fib_index,
3398 &bgp_200_pfx,
3399 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003400 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003401 &nh_1_1_1_1,
3402 ~0,
3403 fib_index,
3404 1,
3405 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3406 fib_table_entry_path_remove(fib_index,
3407 &bgp_200_pfx,
3408 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003409 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003410 &pfx_1_1_1_3_s_32.fp_addr,
3411 ~0,
3412 fib_index,
3413 1,
3414 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3415 fib_table_entry_delete(fib_index,
3416 &pfx_1_1_1_3_s_32,
3417 FIB_SOURCE_API);
3418 fib_table_entry_delete(fib_index,
3419 &pfx_1_1_1_0_s_28,
3420 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003421 /* suspend so the update walk kicks int */
3422 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003423 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3424 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3425 "1.1.1.1/28 removed");
3426 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3427 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3428 "1.1.1.3/32 removed");
3429 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3430 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3431 "200.200.200.200/32 removed");
3432
3433 /*
3434 * add-remove test. no change.
3435 */
3436 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3437 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003438 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003439 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003440 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003441 fib_entry_pool_size());
3442
3443 /*
3444 * A route whose paths are built up iteratively and then removed
3445 * all at once
3446 */
3447 fib_prefix_t pfx_4_4_4_4_s_32 = {
3448 .fp_len = 32,
3449 .fp_proto = FIB_PROTOCOL_IP4,
3450 .fp_addr = {
3451 /* 4.4.4.4/32 */
3452 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3453 },
3454 };
3455
3456 fib_table_entry_path_add(fib_index,
3457 &pfx_4_4_4_4_s_32,
3458 FIB_SOURCE_API,
3459 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003460 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003461 &nh_10_10_10_1,
3462 tm->hw[0]->sw_if_index,
3463 ~0,
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 fib_table_entry_path_add(fib_index,
3468 &pfx_4_4_4_4_s_32,
3469 FIB_SOURCE_API,
3470 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003471 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003472 &nh_10_10_10_2,
3473 tm->hw[0]->sw_if_index,
3474 ~0,
3475 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003476 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003477 FIB_ROUTE_PATH_FLAG_NONE);
3478 fib_table_entry_path_add(fib_index,
3479 &pfx_4_4_4_4_s_32,
3480 FIB_SOURCE_API,
3481 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003482 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003483 &nh_10_10_10_3,
3484 tm->hw[0]->sw_if_index,
3485 ~0,
3486 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003487 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003488 FIB_ROUTE_PATH_FLAG_NONE);
3489 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3490 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3491 "4.4.4.4/32 present");
3492
3493 fib_table_entry_delete(fib_index,
3494 &pfx_4_4_4_4_s_32,
3495 FIB_SOURCE_API);
3496 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3497 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3498 "4.4.4.4/32 removed");
3499
3500 /*
3501 * add-remove test. no change.
3502 */
3503 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3504 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003505 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003506 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003507 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003508 fib_entry_pool_size());
3509
3510 /*
3511 * A route with multiple paths at once
3512 */
3513 fib_route_path_t *r_paths = NULL;
3514
3515 for (ii = 0; ii < 4; ii++)
3516 {
3517 fib_route_path_t r_path = {
Neale Rannsda78f952017-05-24 09:15:43 -07003518 .frp_proto = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003519 .frp_addr = {
3520 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3521 },
3522 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3523 .frp_weight = 1,
3524 .frp_fib_index = ~0,
3525 };
3526 vec_add1(r_paths, r_path);
3527 }
3528
3529 fib_table_entry_update(fib_index,
3530 &pfx_4_4_4_4_s_32,
3531 FIB_SOURCE_API,
3532 FIB_ENTRY_FLAG_NONE,
3533 r_paths);
3534
3535 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3536 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3537 dpo = fib_entry_contribute_ip_forwarding(fei);
3538
3539 lb = load_balance_get(dpo->dpoi_index);
3540 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3541
3542 fib_table_entry_delete(fib_index,
3543 &pfx_4_4_4_4_s_32,
3544 FIB_SOURCE_API);
3545 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3546 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3547 "4.4.4.4/32 removed");
3548 vec_free(r_paths);
3549
3550 /*
3551 * add-remove test. no change.
3552 */
3553 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3554 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003555 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003556 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003557 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003558 fib_entry_pool_size());
3559
3560 /*
3561 * A route deag route
3562 */
3563 fib_table_entry_path_add(fib_index,
3564 &pfx_4_4_4_4_s_32,
3565 FIB_SOURCE_API,
3566 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003567 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003568 &zero_addr,
3569 ~0,
3570 fib_index,
3571 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003572 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003573 FIB_ROUTE_PATH_FLAG_NONE);
3574
3575 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3576 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3577
3578 dpo = fib_entry_contribute_ip_forwarding(fei);
3579 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3580 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3581
3582 FIB_TEST((fib_index == lkd->lkd_fib_index),
3583 "4.4.4.4/32 is deag in %d %U",
3584 lkd->lkd_fib_index,
3585 format_dpo_id, dpo, 0);
Neale Ranns054c03a2017-10-13 05:15:07 -07003586 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3587 "4.4.4.4/32 is source deag in %d %U",
3588 lkd->lkd_input,
3589 format_dpo_id, dpo, 0);
3590
3591 fib_table_entry_delete(fib_index,
3592 &pfx_4_4_4_4_s_32,
3593 FIB_SOURCE_API);
3594 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3595 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3596 "4.4.4.4/32 removed");
3597 vec_free(r_paths);
3598
3599 /*
3600 * A route deag route in a source lookup table
3601 */
3602 fib_table_entry_path_add(fib_index,
3603 &pfx_4_4_4_4_s_32,
3604 FIB_SOURCE_API,
3605 FIB_ENTRY_FLAG_NONE,
3606 DPO_PROTO_IP4,
3607 &zero_addr,
3608 ~0,
3609 fib_index,
3610 1,
3611 NULL,
3612 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3613
3614 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3615 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3616
3617 dpo = fib_entry_contribute_ip_forwarding(fei);
3618 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3619 lkd = lookup_dpo_get(dpo->dpoi_index);
3620
3621 FIB_TEST((fib_index == lkd->lkd_fib_index),
3622 "4.4.4.4/32 is deag in %d %U",
3623 lkd->lkd_fib_index,
3624 format_dpo_id, dpo, 0);
3625 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3626 "4.4.4.4/32 is source deag in %d %U",
3627 lkd->lkd_input,
3628 format_dpo_id, dpo, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003629
3630 fib_table_entry_delete(fib_index,
3631 &pfx_4_4_4_4_s_32,
3632 FIB_SOURCE_API);
3633 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3634 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3635 "4.4.4.4/32 removed");
3636 vec_free(r_paths);
3637
3638 /*
3639 * add-remove test. no change.
3640 */
3641 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3642 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003643 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003644 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003645 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003646 fib_entry_pool_size());
3647
3648 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003649 * Duplicate paths:
3650 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3651 */
3652 fib_prefix_t pfx_34_1_1_1_s_32 = {
3653 .fp_len = 32,
3654 .fp_proto = FIB_PROTOCOL_IP4,
3655 .fp_addr = {
3656 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3657 },
3658 };
3659 fib_prefix_t pfx_34_34_1_1_s_32 = {
3660 .fp_len = 32,
3661 .fp_proto = FIB_PROTOCOL_IP4,
3662 .fp_addr = {
3663 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3664 },
3665 };
3666 fei = fib_table_entry_path_add(fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -07003667 &pfx_34_34_1_1_s_32,
3668 FIB_SOURCE_API,
3669 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003670 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07003671 &nh_10_10_10_1,
3672 tm->hw[0]->sw_if_index,
3673 0,
3674 1,
3675 NULL,
3676 FIB_ROUTE_PATH_FLAG_NONE);
3677 fei = fib_table_entry_path_add(fib_index,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003678 &pfx_34_1_1_1_s_32,
3679 FIB_SOURCE_API,
3680 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003681 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003682 &pfx_34_34_1_1_s_32.fp_addr,
3683 ~0,
3684 fib_index,
3685 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003686 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003687 FIB_ROUTE_PATH_FLAG_NONE);
3688 fei = fib_table_entry_path_add(fib_index,
3689 &pfx_34_1_1_1_s_32,
3690 FIB_SOURCE_API,
3691 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003692 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003693 &pfx_34_34_1_1_s_32.fp_addr,
3694 ~0,
3695 fib_index,
3696 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003697 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003698 FIB_ROUTE_PATH_FLAG_NONE);
3699 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3700 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
Neale Ranns57b58602017-07-15 07:37:25 -07003701 fib_table_entry_delete(fib_index,
3702 &pfx_34_34_1_1_s_32,
3703 FIB_SOURCE_API);
Neale Rannsbcc889c2016-11-03 14:15:28 -07003704
3705 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003706 * CLEANUP
3707 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3708 * all of which are via 10.10.10.1, Itf1
3709 */
3710 fib_table_entry_path_remove(fib_index,
3711 &pfx_1_1_1_2_s_32,
3712 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003713 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003714 &nh_10_10_10_1,
3715 tm->hw[0]->sw_if_index,
3716 ~0,
3717 1,
3718 FIB_ROUTE_PATH_FLAG_NONE);
3719 fib_table_entry_path_remove(fib_index,
3720 &pfx_1_1_1_1_s_32,
3721 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003722 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003723 &nh_10_10_10_1,
3724 tm->hw[0]->sw_if_index,
3725 ~0,
3726 1,
3727 FIB_ROUTE_PATH_FLAG_NONE);
3728 fib_table_entry_path_remove(fib_index,
3729 &pfx_1_1_2_0_s_24,
3730 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003731 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003732 &nh_10_10_10_1,
3733 tm->hw[0]->sw_if_index,
3734 ~0,
3735 1,
3736 FIB_ROUTE_PATH_FLAG_NONE);
3737
3738 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3739 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3740 "1.1.1.1/32 removed");
3741 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3742 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3743 "1.1.1.2/32 removed");
3744 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3745 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3746 "1.1.2.0/24 removed");
3747
3748 /*
3749 * -3 entries and -1 shared path-list
3750 */
3751 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3752 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003753 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003754 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003755 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003756 fib_entry_pool_size());
3757
3758 /*
3759 * An attached-host route. Expect to link to the incomplete adj
3760 */
3761 fib_prefix_t pfx_4_1_1_1_s_32 = {
3762 .fp_len = 32,
3763 .fp_proto = FIB_PROTOCOL_IP4,
3764 .fp_addr = {
3765 /* 4.1.1.1/32 */
3766 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3767 },
3768 };
3769 fib_table_entry_path_add(fib_index,
3770 &pfx_4_1_1_1_s_32,
3771 FIB_SOURCE_API,
3772 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003773 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003774 &zero_addr,
3775 tm->hw[0]->sw_if_index,
3776 fib_index,
3777 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003778 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003779 FIB_ROUTE_PATH_FLAG_NONE);
3780
3781 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3782 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3783 ai = fib_entry_get_adj(fei);
3784
3785 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003786 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003787 &pfx_4_1_1_1_s_32.fp_addr,
3788 tm->hw[0]->sw_if_index);
3789 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3790 adj_unlock(ai2);
3791
3792 /*
3793 * +1 entry and +1 shared path-list
3794 */
3795 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3796 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003797 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003798 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003799 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003800 fib_entry_pool_size());
3801
3802 fib_table_entry_delete(fib_index,
3803 &pfx_4_1_1_1_s_32,
3804 FIB_SOURCE_API);
3805
3806 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3807 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003808 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003809 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003810 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003811 fib_entry_pool_size());
3812
3813 /*
3814 * add a v6 prefix via v4 next-hops
3815 */
3816 fib_prefix_t pfx_2001_s_64 = {
3817 .fp_len = 64,
3818 .fp_proto = FIB_PROTOCOL_IP6,
3819 .fp_addr = {
3820 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3821 },
3822 };
3823 fei = fib_table_entry_path_add(0, //default v6 table
3824 &pfx_2001_s_64,
3825 FIB_SOURCE_API,
3826 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003827 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003828 &nh_10_10_10_1,
3829 tm->hw[0]->sw_if_index,
3830 fib_index,
3831 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003832 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003833 FIB_ROUTE_PATH_FLAG_NONE);
3834
3835 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3836 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3837 ai = fib_entry_get_adj(fei);
3838 adj = adj_get(ai);
3839 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3840 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003841 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003842 "2001::/64 is link type v6");
3843 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3844 "2001::/64 ADJ-adj is NH proto v4");
3845 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3846
Neale Ranns3ee44042016-10-03 13:05:48 +01003847 /*
3848 * add a uRPF exempt prefix:
3849 * test:
3850 * - it's forwarding is drop
3851 * - it's uRPF list is not empty
3852 * - the uRPF list for the default route (it's cover) is empty
3853 */
3854 fei = fib_table_entry_special_add(fib_index,
3855 &pfx_4_1_1_1_s_32,
3856 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003857 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003858 dpo = fib_entry_contribute_ip_forwarding(fei);
3859 FIB_TEST(load_balance_is_drop(dpo),
3860 "uRPF exempt 4.1.1.1/32 DROP");
3861 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3862 "uRPF list for exempt prefix has itf index 0");
3863 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3864 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3865 "uRPF list for 0.0.0.0/0 empty");
3866
3867 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003868
3869 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003870 * An adj-fib that fails the refinement criteria - no connected cover
3871 */
3872 fib_prefix_t pfx_12_10_10_2_s_32 = {
3873 .fp_len = 32,
3874 .fp_proto = FIB_PROTOCOL_IP4,
3875 .fp_addr = {
3876 /* 12.10.10.2 */
3877 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3878 },
3879 };
3880
Neale Ranns81424992017-05-18 03:03:22 -07003881 fib_table_entry_path_add(fib_index,
3882 &pfx_12_10_10_2_s_32,
3883 FIB_SOURCE_ADJ,
3884 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003885 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003886 &pfx_12_10_10_2_s_32.fp_addr,
3887 tm->hw[0]->sw_if_index,
3888 ~0, // invalid fib index
3889 1,
3890 NULL,
3891 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003892
3893 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3894 dpo = fib_entry_contribute_ip_forwarding(fei);
3895 FIB_TEST(!dpo_id_is_valid(dpo),
3896 "no connected cover adj-fib fails refinement");
3897
3898 fib_table_entry_delete(fib_index,
3899 &pfx_12_10_10_2_s_32,
3900 FIB_SOURCE_ADJ);
3901
3902 /*
3903 * An adj-fib that fails the refinement criteria - cover is connected
3904 * but on a different interface
3905 */
3906 fib_prefix_t pfx_10_10_10_127_s_32 = {
3907 .fp_len = 32,
3908 .fp_proto = FIB_PROTOCOL_IP4,
3909 .fp_addr = {
3910 /* 10.10.10.127 */
3911 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3912 },
3913 };
3914
Neale Ranns81424992017-05-18 03:03:22 -07003915 fib_table_entry_path_add(fib_index,
3916 &pfx_10_10_10_127_s_32,
3917 FIB_SOURCE_ADJ,
3918 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003919 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003920 &pfx_10_10_10_127_s_32.fp_addr,
3921 tm->hw[1]->sw_if_index,
3922 ~0, // invalid fib index
3923 1,
3924 NULL,
3925 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003926
3927 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3928 dpo = fib_entry_contribute_ip_forwarding(fei);
3929 FIB_TEST(!dpo_id_is_valid(dpo),
3930 "wrong interface adj-fib fails refinement");
3931
3932 fib_table_entry_delete(fib_index,
3933 &pfx_10_10_10_127_s_32,
3934 FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07003935
3936 /*
3937 * add a second path to an adj-fib
3938 * this is a sumiluation of another ARP entry created
3939 * on an interface on which the connected prefi does not exist.
3940 * The second path fails refinement. Expect to forward through the
3941 * first.
3942 */
3943 fib_prefix_t pfx_10_10_10_3_s_32 = {
3944 .fp_len = 32,
3945 .fp_proto = FIB_PROTOCOL_IP4,
3946 .fp_addr = {
3947 /* 10.10.10.3 */
3948 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3949 },
3950 };
3951
3952 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3953 VNET_LINK_IP4,
3954 &nh_10_10_10_3,
3955 tm->hw[0]->sw_if_index);
3956
3957 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
3958 .type = FT_LB_ADJ,
3959 .adj = {
3960 .adj = ai_03,
3961 },
3962 };
3963 fei = fib_table_entry_path_add(fib_index,
3964 &pfx_10_10_10_3_s_32,
3965 FIB_SOURCE_ADJ,
3966 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003967 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003968 &nh_10_10_10_3,
3969 tm->hw[0]->sw_if_index,
3970 fib_index,
3971 1,
3972 NULL,
3973 FIB_ROUTE_PATH_FLAG_NONE);
3974 fei = fib_table_entry_path_add(fib_index,
3975 &pfx_10_10_10_3_s_32,
3976 FIB_SOURCE_ADJ,
3977 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003978 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003979 &nh_12_12_12_12,
3980 tm->hw[1]->sw_if_index,
3981 fib_index,
3982 1,
3983 NULL,
3984 FIB_ROUTE_PATH_FLAG_NONE);
3985 FIB_TEST(fib_test_validate_entry(fei,
3986 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3987 1,
3988 &ip_o_10_10_10_3),
3989 "10.10.10.3 via 10.10.10.3/Eth0 only");
3990
3991 /*
3992 * remove the path that refines the cover, should go unresolved
3993 */
3994 fib_table_entry_path_remove(fib_index,
3995 &pfx_10_10_10_3_s_32,
3996 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07003997 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003998 &nh_10_10_10_3,
3999 tm->hw[0]->sw_if_index,
4000 fib_index,
4001 1,
4002 FIB_ROUTE_PATH_FLAG_NONE);
4003 dpo = fib_entry_contribute_ip_forwarding(fei);
4004 FIB_TEST(!dpo_id_is_valid(dpo),
4005 "wrong interface adj-fib fails refinement");
4006
4007 /*
4008 * add back the path that refines the cover
4009 */
4010 fei = fib_table_entry_path_add(fib_index,
4011 &pfx_10_10_10_3_s_32,
4012 FIB_SOURCE_ADJ,
4013 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004014 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004015 &nh_10_10_10_3,
4016 tm->hw[0]->sw_if_index,
4017 fib_index,
4018 1,
4019 NULL,
4020 FIB_ROUTE_PATH_FLAG_NONE);
4021 FIB_TEST(fib_test_validate_entry(fei,
4022 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4023 1,
4024 &ip_o_10_10_10_3),
4025 "10.10.10.3 via 10.10.10.3/Eth0 only");
4026
4027 /*
4028 * remove the path that does not refine the cover
4029 */
4030 fib_table_entry_path_remove(fib_index,
4031 &pfx_10_10_10_3_s_32,
4032 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07004033 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004034 &nh_12_12_12_12,
4035 tm->hw[1]->sw_if_index,
4036 fib_index,
4037 1,
4038 FIB_ROUTE_PATH_FLAG_NONE);
4039 FIB_TEST(fib_test_validate_entry(fei,
4040 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4041 1,
4042 &ip_o_10_10_10_3),
4043 "10.10.10.3 via 10.10.10.3/Eth0 only");
4044
4045 /*
4046 * remove the path that does refine, it's the last path, so
4047 * the entry should be gone
4048 */
4049 fib_table_entry_path_remove(fib_index,
4050 &pfx_10_10_10_3_s_32,
4051 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07004052 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004053 &nh_10_10_10_3,
4054 tm->hw[0]->sw_if_index,
4055 fib_index,
4056 1,
4057 FIB_ROUTE_PATH_FLAG_NONE);
4058 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4059 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4060
4061 adj_unlock(ai_03);
4062
Neale Ranns227038a2017-04-21 01:07:59 -07004063 /*
4064 * change the table's flow-hash config - expect the update to propagete to
4065 * the entries' load-balance objects
4066 */
4067 flow_hash_config_t old_hash_config, new_hash_config;
4068
4069 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4070 FIB_PROTOCOL_IP4);
4071 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4072 IP_FLOW_HASH_DST_ADDR);
4073
4074 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4075 dpo = fib_entry_contribute_ip_forwarding(fei);
4076 lb = load_balance_get(dpo->dpoi_index);
4077 FIB_TEST((lb->lb_hash_config == old_hash_config),
4078 "Table and LB hash config match: %U",
4079 format_ip_flow_hash_config, lb->lb_hash_config);
4080
4081 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4082
4083 FIB_TEST((lb->lb_hash_config == new_hash_config),
4084 "Table and LB newhash config match: %U",
4085 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08004086
4087 /*
Neale Ranns6f631152017-10-03 08:20:21 -07004088 * A route via an L2 Bridge
4089 */
4090 fei = fib_table_entry_path_add(fib_index,
4091 &pfx_10_10_10_3_s_32,
4092 FIB_SOURCE_API,
4093 FIB_ENTRY_FLAG_NONE,
4094 DPO_PROTO_ETHERNET,
4095 &zero_addr,
4096 tm->hw[0]->sw_if_index,
4097 ~0,
4098 1,
4099 NULL,
4100 FIB_ROUTE_PATH_FLAG_NONE);
4101 dpo_id_t l2_dpo = DPO_INVALID;
4102 l2_bridge_dpo_add_or_lock(tm->hw[0]->sw_if_index, &l2_dpo);
4103 fib_test_lb_bucket_t ip_o_l2 = {
4104 .type = FT_LB_L2,
4105 .adj = {
4106 .adj = l2_dpo.dpoi_index,
4107 },
4108 };
4109
4110 FIB_TEST(fib_test_validate_entry(fei,
4111 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4112 1,
4113 &ip_o_l2),
4114 "10.10.10.3 via L2 on Eth0");
4115 fib_table_entry_path_remove(fib_index,
4116 &pfx_10_10_10_3_s_32,
4117 FIB_SOURCE_API,
4118 DPO_PROTO_ETHERNET,
4119 &zero_addr,
4120 tm->hw[0]->sw_if_index,
4121 fib_index,
4122 1,
4123 FIB_ROUTE_PATH_FLAG_NONE);
4124 dpo_reset(&l2_dpo);
4125
4126 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004127 * CLEANUP
4128 * remove adj-fibs:
4129 */
4130 fib_table_entry_delete(fib_index,
4131 &pfx_10_10_10_1_s_32,
4132 FIB_SOURCE_ADJ);
4133 fib_table_entry_delete(fib_index,
4134 &pfx_10_10_10_2_s_32,
4135 FIB_SOURCE_ADJ);
4136 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4137 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4138 "10.10.10.1/32 adj-fib removed");
4139 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4140 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4141 "10.10.10.2/32 adj-fib removed");
4142
4143 /*
4144 * -2 entries and -2 non-shared path-list
4145 */
4146 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4147 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004148 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004149 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004150 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004151 fib_entry_pool_size());
4152
4153 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01004154 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004155 * These are the last locks on these adjs. they should thus go away.
4156 */
4157 adj_unlock(ai_02);
4158 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01004159 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004160
4161 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4162 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00004163
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004164 /*
4165 * CLEANUP
4166 * remove the interface prefixes
4167 */
4168 local_pfx.fp_len = 32;
4169 fib_table_entry_special_remove(fib_index, &local_pfx,
4170 FIB_SOURCE_INTERFACE);
4171 fei = fib_table_lookup(fib_index, &local_pfx);
4172
4173 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4174 fib_table_lookup_exact_match(fib_index, &local_pfx),
4175 "10.10.10.10/32 adj-fib removed");
4176
4177 local_pfx.fp_len = 24;
4178 fib_table_entry_delete(fib_index, &local_pfx,
4179 FIB_SOURCE_INTERFACE);
4180
4181 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4182 fib_table_lookup_exact_match(fib_index, &local_pfx),
4183 "10.10.10.10/24 adj-fib removed");
4184
4185 /*
4186 * -2 entries and -2 non-shared path-list
4187 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07004188 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004189 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004190 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004191 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004192 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004193 fib_entry_pool_size());
4194
4195 /*
4196 * Last but not least, remove the VRF
4197 */
4198 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4199 FIB_PROTOCOL_IP4,
4200 FIB_SOURCE_API)),
4201 "NO API Source'd prefixes");
4202 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4203 FIB_PROTOCOL_IP4,
4204 FIB_SOURCE_RR)),
4205 "NO RR Source'd prefixes");
4206 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4207 FIB_PROTOCOL_IP4,
4208 FIB_SOURCE_INTERFACE)),
4209 "NO INterface Source'd prefixes");
4210
Neale Ranns15002542017-09-10 04:39:11 -07004211 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004212
4213 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4214 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004215 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004216 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004217 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004218 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004219 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01004220 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004221 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07004222 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004223 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4224 pool_elts(load_balance_pool));
Neale Ranns6f631152017-10-03 08:20:21 -07004225 FIB_TEST((0 == pool_elts(l2_bridge_dpo_pool)), "L2 DPO pool size is %d",
4226 pool_elts(l2_bridge_dpo_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004227
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004228 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004229}
4230
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004231static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004232fib_test_v6 (void)
4233{
4234 /*
4235 * In the default table check for the presence and correct forwarding
4236 * of the special entries
4237 */
4238 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4239 const dpo_id_t *dpo, *dpo_drop;
4240 const ip_adjacency_t *adj;
4241 const receive_dpo_t *rd;
4242 test_main_t *tm;
4243 u32 fib_index;
4244 int ii;
4245
4246 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4247 adj_nbr_db_size());
4248
4249 /* via 2001:0:0:1::2 */
4250 ip46_address_t nh_2001_2 = {
4251 .ip6 = {
4252 .as_u64 = {
4253 [0] = clib_host_to_net_u64(0x2001000000000001),
4254 [1] = clib_host_to_net_u64(0x0000000000000002),
4255 },
4256 },
4257 };
4258
4259 tm = &test_main;
4260
4261 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4262
4263 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -07004264 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4265 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004266
4267 for (ii = 0; ii < 4; ii++)
4268 {
4269 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4270 }
4271
4272 fib_prefix_t pfx_0_0 = {
4273 .fp_len = 0,
4274 .fp_proto = FIB_PROTOCOL_IP6,
4275 .fp_addr = {
4276 .ip6 = {
4277 {0, 0},
4278 },
4279 },
4280 };
4281
4282 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4283 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4284 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4285 "Default route is DROP");
4286
4287 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4288 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4289 &ip6_main,
4290 1,
4291 &pfx_0_0.fp_addr.ip6)),
4292 "default-route; fwd and non-fwd tables match");
4293
4294 // FIXME - check specials.
4295
4296 /*
4297 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004298 * each with 2 entries and a v6 mfib with 4 path-lists.
4299 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004300 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004301#define ENPS (5+4)
4302#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004303 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004304 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004305 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004306 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004307 fib_entry_pool_size());
4308
4309 /*
4310 * add interface routes.
4311 * validate presence of /64 attached and /128 recieve.
4312 * test for the presence of the receive address in the glean and local adj
4313 *
4314 * receive on 2001:0:0:1::1/128
4315 */
4316 fib_prefix_t local_pfx = {
4317 .fp_len = 64,
4318 .fp_proto = FIB_PROTOCOL_IP6,
4319 .fp_addr = {
4320 .ip6 = {
4321 .as_u64 = {
4322 [0] = clib_host_to_net_u64(0x2001000000000001),
4323 [1] = clib_host_to_net_u64(0x0000000000000001),
4324 },
4325 },
4326 }
4327 };
4328
4329 fib_table_entry_update_one_path(fib_index, &local_pfx,
4330 FIB_SOURCE_INTERFACE,
4331 (FIB_ENTRY_FLAG_CONNECTED |
4332 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004333 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004334 NULL,
4335 tm->hw[0]->sw_if_index,
4336 ~0,
4337 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004338 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004339 FIB_ROUTE_PATH_FLAG_NONE);
4340 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4341
4342 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4343
4344 ai = fib_entry_get_adj(fei);
4345 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4346 adj = adj_get(ai);
4347 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4348 "attached interface adj is glean");
4349 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4350 &adj->sub_type.glean.receive_addr)),
4351 "attached interface adj is receive ok");
4352 dpo = fib_entry_contribute_ip_forwarding(fei);
4353 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4354 &ip6_main,
4355 1,
4356 &local_pfx.fp_addr.ip6)),
4357 "attached-route; fwd and non-fwd tables match");
4358
4359 local_pfx.fp_len = 128;
4360 fib_table_entry_update_one_path(fib_index, &local_pfx,
4361 FIB_SOURCE_INTERFACE,
4362 (FIB_ENTRY_FLAG_CONNECTED |
4363 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004364 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004365 NULL,
4366 tm->hw[0]->sw_if_index,
4367 ~0, // invalid fib index
4368 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004369 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004370 FIB_ROUTE_PATH_FLAG_NONE);
4371 fei = fib_table_lookup(fib_index, &local_pfx);
4372
4373 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4374
4375 dpo = fib_entry_contribute_ip_forwarding(fei);
4376 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4377 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4378 "local interface adj is local");
4379 rd = receive_dpo_get(dpo->dpoi_index);
4380
4381 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4382 &rd->rd_addr)),
4383 "local interface adj is receive ok");
4384
4385 dpo = fib_entry_contribute_ip_forwarding(fei);
4386 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4387 &ip6_main,
4388 1,
4389 &local_pfx.fp_addr.ip6)),
4390 "local-route; fwd and non-fwd tables match");
4391
4392 /*
4393 * +2 entries. +2 unshared path-lists
4394 */
4395 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004396 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004397 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004398 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004399 fib_entry_pool_size());
4400
4401 /*
4402 * Modify the default route to be via an adj not yet known.
4403 * this sources the defalut route with the API source, which is
4404 * a higher preference to the DEFAULT_ROUTE source
4405 */
4406 fib_table_entry_path_add(fib_index, &pfx_0_0,
4407 FIB_SOURCE_API,
4408 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004409 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004410 &nh_2001_2,
4411 tm->hw[0]->sw_if_index,
4412 ~0,
4413 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004414 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004415 FIB_ROUTE_PATH_FLAG_NONE);
4416 fei = fib_table_lookup(fib_index, &pfx_0_0);
4417
4418 FIB_TEST((fei == dfrt), "default route same index");
4419 ai = fib_entry_get_adj(fei);
4420 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4421 adj = adj_get(ai);
4422 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4423 "adj is incomplete");
4424 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4425 "adj nbr next-hop ok");
4426
4427 /*
4428 * find the adj in the shared db
4429 */
4430 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004431 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004432 &nh_2001_2,
4433 tm->hw[0]->sw_if_index);
4434 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4435 adj_unlock(locked_ai);
4436
4437 /*
4438 * no more entires. +1 shared path-list
4439 */
4440 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4441 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004442 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004443 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004444 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004445 fib_entry_pool_size());
4446
4447 /*
4448 * remove the API source from the default route. We expected
4449 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4450 */
4451 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4452 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07004453 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004454 &nh_2001_2,
4455 tm->hw[0]->sw_if_index,
4456 ~0,
4457 1,
4458 FIB_ROUTE_PATH_FLAG_NONE);
4459 fei = fib_table_lookup(fib_index, &pfx_0_0);
4460
4461 FIB_TEST((fei == dfrt), "default route same index");
4462 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4463 "Default route is DROP");
4464
4465 /*
4466 * no more entires. -1 shared path-list
4467 */
4468 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4469 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004470 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004471 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004472 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004473 fib_entry_pool_size());
4474
4475 /*
4476 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4477 */
4478 fib_prefix_t pfx_2001_1_2_s_128 = {
4479 .fp_len = 128,
4480 .fp_proto = FIB_PROTOCOL_IP6,
4481 .fp_addr = {
4482 .ip6 = {
4483 .as_u64 = {
4484 [0] = clib_host_to_net_u64(0x2001000000000001),
4485 [1] = clib_host_to_net_u64(0x0000000000000002),
4486 },
4487 },
4488 }
4489 };
4490 fib_prefix_t pfx_2001_1_3_s_128 = {
4491 .fp_len = 128,
4492 .fp_proto = FIB_PROTOCOL_IP6,
4493 .fp_addr = {
4494 .ip6 = {
4495 .as_u64 = {
4496 [0] = clib_host_to_net_u64(0x2001000000000001),
4497 [1] = clib_host_to_net_u64(0x0000000000000003),
4498 },
4499 },
4500 }
4501 };
4502 u8 eth_addr[] = {
4503 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4504 };
4505
4506 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004507 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004508 &pfx_2001_1_2_s_128.fp_addr,
4509 tm->hw[0]->sw_if_index);
4510 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4511 adj = adj_get(ai_01);
4512 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4513 "adj is incomplete");
4514 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4515 &adj->sub_type.nbr.next_hop)),
4516 "adj nbr next-hop ok");
4517
Neale Rannsb80c5362016-10-08 13:03:40 +01004518 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4519 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004520 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4521 "adj is complete");
4522 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4523 &adj->sub_type.nbr.next_hop)),
4524 "adj nbr next-hop ok");
4525
Neale Ranns81424992017-05-18 03:03:22 -07004526 fib_table_entry_path_add(fib_index,
4527 &pfx_2001_1_2_s_128,
4528 FIB_SOURCE_ADJ,
4529 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004530 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004531 &pfx_2001_1_2_s_128.fp_addr,
4532 tm->hw[0]->sw_if_index,
4533 ~0,
4534 1,
4535 NULL,
4536 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004537
4538 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4539 ai = fib_entry_get_adj(fei);
4540 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4541
4542 eth_addr[5] = 0xb2;
4543
4544 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004545 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004546 &pfx_2001_1_3_s_128.fp_addr,
4547 tm->hw[0]->sw_if_index);
4548 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4549 adj = adj_get(ai_02);
4550 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4551 "adj is incomplete");
4552 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4553 &adj->sub_type.nbr.next_hop)),
4554 "adj nbr next-hop ok");
4555
Neale Rannsb80c5362016-10-08 13:03:40 +01004556 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4557 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004558 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4559 "adj is complete");
4560 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4561 &adj->sub_type.nbr.next_hop)),
4562 "adj nbr next-hop ok");
4563 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4564
Neale Ranns81424992017-05-18 03:03:22 -07004565 fib_table_entry_path_add(fib_index,
4566 &pfx_2001_1_3_s_128,
4567 FIB_SOURCE_ADJ,
4568 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004569 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004570 &pfx_2001_1_3_s_128.fp_addr,
4571 tm->hw[0]->sw_if_index,
4572 ~0,
4573 1,
4574 NULL,
4575 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004576
4577 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4578 ai = fib_entry_get_adj(fei);
4579 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4580
4581 /*
4582 * +2 entries, +2 unshread path-lists.
4583 */
4584 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4585 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004586 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004587 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004588 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004589 fib_entry_pool_size());
4590
4591 /*
4592 * Add a 2 routes via the first ADJ. ensure path-list sharing
4593 */
4594 fib_prefix_t pfx_2001_a_s_64 = {
4595 .fp_len = 64,
4596 .fp_proto = FIB_PROTOCOL_IP6,
4597 .fp_addr = {
4598 .ip6 = {
4599 .as_u64 = {
4600 [0] = clib_host_to_net_u64(0x200100000000000a),
4601 [1] = clib_host_to_net_u64(0x0000000000000000),
4602 },
4603 },
4604 }
4605 };
4606 fib_prefix_t pfx_2001_b_s_64 = {
4607 .fp_len = 64,
4608 .fp_proto = FIB_PROTOCOL_IP6,
4609 .fp_addr = {
4610 .ip6 = {
4611 .as_u64 = {
4612 [0] = clib_host_to_net_u64(0x200100000000000b),
4613 [1] = clib_host_to_net_u64(0x0000000000000000),
4614 },
4615 },
4616 }
4617 };
4618
4619 fib_table_entry_path_add(fib_index,
4620 &pfx_2001_a_s_64,
4621 FIB_SOURCE_API,
4622 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004623 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004624 &nh_2001_2,
4625 tm->hw[0]->sw_if_index,
4626 ~0,
4627 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004628 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004629 FIB_ROUTE_PATH_FLAG_NONE);
4630 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4631 ai = fib_entry_get_adj(fei);
4632 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4633 fib_table_entry_path_add(fib_index,
4634 &pfx_2001_b_s_64,
4635 FIB_SOURCE_API,
4636 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004637 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004638 &nh_2001_2,
4639 tm->hw[0]->sw_if_index,
4640 ~0,
4641 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004642 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004643 FIB_ROUTE_PATH_FLAG_NONE);
4644 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4645 ai = fib_entry_get_adj(fei);
4646 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4647
4648 /*
4649 * +2 entries, +1 shared path-list.
4650 */
4651 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4652 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004653 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004654 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004655 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004656 fib_entry_pool_size());
4657
4658 /*
4659 * add a v4 prefix via a v6 next-hop
4660 */
4661 fib_prefix_t pfx_1_1_1_1_s_32 = {
4662 .fp_len = 32,
4663 .fp_proto = FIB_PROTOCOL_IP4,
4664 .fp_addr = {
4665 .ip4.as_u32 = 0x01010101,
4666 },
4667 };
4668 fei = fib_table_entry_path_add(0, // default table
4669 &pfx_1_1_1_1_s_32,
4670 FIB_SOURCE_API,
4671 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004672 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004673 &nh_2001_2,
4674 tm->hw[0]->sw_if_index,
4675 ~0,
4676 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004677 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004678 FIB_ROUTE_PATH_FLAG_NONE);
4679 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4680 "1.1.1.1/32 o v6 route present");
4681 ai = fib_entry_get_adj(fei);
4682 adj = adj_get(ai);
4683 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4684 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004685 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004686 "1.1.1.1/32 ADJ-adj is link type v4");
4687 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4688 "1.1.1.1/32 ADJ-adj is NH proto v6");
4689 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4690
4691 /*
4692 * An attached route
4693 */
4694 fib_prefix_t pfx_2001_c_s_64 = {
4695 .fp_len = 64,
4696 .fp_proto = FIB_PROTOCOL_IP6,
4697 .fp_addr = {
4698 .ip6 = {
4699 .as_u64 = {
4700 [0] = clib_host_to_net_u64(0x200100000000000c),
4701 [1] = clib_host_to_net_u64(0x0000000000000000),
4702 },
4703 },
4704 }
4705 };
4706 fib_table_entry_path_add(fib_index,
4707 &pfx_2001_c_s_64,
4708 FIB_SOURCE_CLI,
4709 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004710 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004711 NULL,
4712 tm->hw[0]->sw_if_index,
4713 ~0,
4714 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004715 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004716 FIB_ROUTE_PATH_FLAG_NONE);
4717 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4718 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4719 ai = fib_entry_get_adj(fei);
4720 adj = adj_get(ai);
4721 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4722 "2001:0:0:c/64 attached resolves via glean");
4723
4724 fib_table_entry_path_remove(fib_index,
4725 &pfx_2001_c_s_64,
4726 FIB_SOURCE_CLI,
Neale Rannsda78f952017-05-24 09:15:43 -07004727 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004728 NULL,
4729 tm->hw[0]->sw_if_index,
4730 ~0,
4731 1,
4732 FIB_ROUTE_PATH_FLAG_NONE);
4733 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4734 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4735
4736 /*
4737 * Shutdown the interface on which we have a connected and through
4738 * which the routes are reachable.
4739 * This will result in the connected, adj-fibs, and routes linking to drop
4740 * The local/for-us prefix continues to receive.
4741 */
4742 clib_error_t * error;
4743
4744 error = vnet_sw_interface_set_flags(vnet_get_main(),
4745 tm->hw[0]->sw_if_index,
4746 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4747 FIB_TEST((NULL == error), "Interface shutdown OK");
4748
4749 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4750 dpo = fib_entry_contribute_ip_forwarding(fei);
4751 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4752 "2001::b/64 resolves via drop");
4753
4754 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4755 dpo = fib_entry_contribute_ip_forwarding(fei);
4756 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4757 "2001::a/64 resolves via drop");
4758 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4759 dpo = fib_entry_contribute_ip_forwarding(fei);
4760 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4761 "2001:0:0:1::3/64 resolves via drop");
4762 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4763 dpo = fib_entry_contribute_ip_forwarding(fei);
4764 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4765 "2001:0:0:1::2/64 resolves via drop");
4766 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4767 dpo = fib_entry_contribute_ip_forwarding(fei);
4768 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4769 "2001:0:0:1::1/128 not drop");
4770 local_pfx.fp_len = 64;
4771 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4772 dpo = fib_entry_contribute_ip_forwarding(fei);
4773 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4774 "2001:0:0:1/64 resolves via drop");
4775
4776 /*
4777 * no change
4778 */
4779 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4780 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004781 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004782 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004783 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004784 fib_entry_pool_size());
4785
4786 /*
4787 * shutdown one of the other interfaces, then add a connected.
4788 * and swap one of the routes to it.
4789 */
4790 error = vnet_sw_interface_set_flags(vnet_get_main(),
4791 tm->hw[1]->sw_if_index,
4792 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4793 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4794
4795 fib_prefix_t connected_pfx = {
4796 .fp_len = 64,
4797 .fp_proto = FIB_PROTOCOL_IP6,
4798 .fp_addr = {
4799 .ip6 = {
4800 /* 2001:0:0:2::1/64 */
4801 .as_u64 = {
4802 [0] = clib_host_to_net_u64(0x2001000000000002),
4803 [1] = clib_host_to_net_u64(0x0000000000000001),
4804 },
4805 },
4806 }
4807 };
4808 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4809 FIB_SOURCE_INTERFACE,
4810 (FIB_ENTRY_FLAG_CONNECTED |
4811 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004812 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004813 NULL,
4814 tm->hw[1]->sw_if_index,
4815 ~0,
4816 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004817 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004818 FIB_ROUTE_PATH_FLAG_NONE);
4819 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4820 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4821 dpo = fib_entry_contribute_ip_forwarding(fei);
4822 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4823 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4824 "2001:0:0:2/64 not resolves via drop");
4825
4826 connected_pfx.fp_len = 128;
4827 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4828 FIB_SOURCE_INTERFACE,
4829 (FIB_ENTRY_FLAG_CONNECTED |
4830 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004831 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004832 NULL,
4833 tm->hw[0]->sw_if_index,
4834 ~0, // invalid fib index
4835 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004836 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004837 FIB_ROUTE_PATH_FLAG_NONE);
4838 fei = fib_table_lookup(fib_index, &connected_pfx);
4839
4840 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4841 dpo = fib_entry_contribute_ip_forwarding(fei);
4842 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4843 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4844 "local interface adj is local");
4845 rd = receive_dpo_get(dpo->dpoi_index);
4846 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4847 &rd->rd_addr)),
4848 "local interface adj is receive ok");
4849
4850 /*
4851 * +2 entries, +2 unshared path-lists
4852 */
4853 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4854 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004855 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004856 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004857 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004858 fib_entry_pool_size());
4859
4860
4861 /*
4862 * bring the interface back up. we expected the routes to return
4863 * to normal forwarding.
4864 */
4865 error = vnet_sw_interface_set_flags(vnet_get_main(),
4866 tm->hw[0]->sw_if_index,
4867 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4868 FIB_TEST((NULL == error), "Interface bring-up OK");
4869 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4870 ai = fib_entry_get_adj(fei);
4871 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4872 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4873 ai = fib_entry_get_adj(fei);
4874 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4875 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4876 ai = fib_entry_get_adj(fei);
4877 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4878 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4879 ai = fib_entry_get_adj(fei);
4880 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4881 local_pfx.fp_len = 64;
4882 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4883 ai = fib_entry_get_adj(fei);
4884 adj = adj_get(ai);
4885 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4886 "attached interface adj is glean");
4887
4888 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004889 * Same test as above, but this time the HW interface goes down
4890 */
4891 error = vnet_hw_interface_set_flags(vnet_get_main(),
4892 tm->hw_if_indicies[0],
4893 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4894 FIB_TEST((NULL == error), "Interface shutdown OK");
4895
4896 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4897 dpo = fib_entry_contribute_ip_forwarding(fei);
4898 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4899 "2001::b/64 resolves via drop");
4900 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4901 dpo = fib_entry_contribute_ip_forwarding(fei);
4902 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4903 "2001::a/64 resolves via drop");
4904 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4905 dpo = fib_entry_contribute_ip_forwarding(fei);
4906 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4907 "2001:0:0:1::3/128 resolves via drop");
4908 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4909 dpo = fib_entry_contribute_ip_forwarding(fei);
4910 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4911 "2001:0:0:1::2/128 resolves via drop");
4912 local_pfx.fp_len = 128;
4913 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4914 dpo = fib_entry_contribute_ip_forwarding(fei);
4915 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4916 "2001:0:0:1::1/128 not drop");
4917 local_pfx.fp_len = 64;
4918 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4919 dpo = fib_entry_contribute_ip_forwarding(fei);
4920 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4921 "2001:0:0:1/64 resolves via drop");
4922
4923 error = vnet_hw_interface_set_flags(vnet_get_main(),
4924 tm->hw_if_indicies[0],
4925 VNET_HW_INTERFACE_FLAG_LINK_UP);
4926 FIB_TEST((NULL == error), "Interface bring-up OK");
4927 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4928 ai = fib_entry_get_adj(fei);
4929 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4930 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4931 ai = fib_entry_get_adj(fei);
4932 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4933 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4934 ai = fib_entry_get_adj(fei);
4935 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4936 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4937 ai = fib_entry_get_adj(fei);
4938 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4939 local_pfx.fp_len = 64;
4940 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4941 ai = fib_entry_get_adj(fei);
4942 adj = adj_get(ai);
4943 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4944 "attached interface adj is glean");
4945
4946 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004947 * Delete the interface that the routes reolve through.
4948 * Again no routes are removed. They all point to drop.
4949 *
4950 * This is considered an error case. The control plane should
4951 * not remove interfaces through which routes resolve, but
4952 * such things can happen. ALL affected routes will drop.
4953 */
4954 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4955
4956 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4957 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4958 "2001::b/64 resolves via drop");
4959 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4960 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4961 "2001::b/64 resolves via drop");
4962 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4963 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4964 "2001:0:0:1::3/64 resolves via drop");
4965 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4966 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4967 "2001:0:0:1::2/64 resolves via drop");
4968 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4969 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4970 "2001:0:0:1::1/128 is drop");
4971 local_pfx.fp_len = 64;
4972 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4973 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4974 "2001:0:0:1/64 resolves via drop");
4975
4976 /*
4977 * no change
4978 */
4979 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4980 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004981 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004982 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004983 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004984 fib_entry_pool_size());
4985
4986 /*
4987 * Add the interface back. routes stay unresolved.
4988 */
4989 error = ethernet_register_interface(vnet_get_main(),
4990 test_interface_device_class.index,
4991 0 /* instance */,
4992 hw_address,
4993 &tm->hw_if_indicies[0],
4994 /* flag change */ 0);
4995
4996 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4997 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4998 "2001::b/64 resolves via drop");
4999 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
5000 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5001 "2001::b/64 resolves via drop");
5002 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
5003 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5004 "2001:0:0:1::3/64 resolves via drop");
5005 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
5006 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5007 "2001:0:0:1::2/64 resolves via drop");
5008 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5009 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5010 "2001:0:0:1::1/128 is drop");
5011 local_pfx.fp_len = 64;
5012 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5013 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
5014 "2001:0:0:1/64 resolves via drop");
5015
5016 /*
5017 * CLEANUP ALL the routes
5018 */
5019 fib_table_entry_delete(fib_index,
5020 &pfx_2001_c_s_64,
5021 FIB_SOURCE_API);
5022 fib_table_entry_delete(fib_index,
5023 &pfx_2001_a_s_64,
5024 FIB_SOURCE_API);
5025 fib_table_entry_delete(fib_index,
5026 &pfx_2001_b_s_64,
5027 FIB_SOURCE_API);
5028 fib_table_entry_delete(fib_index,
5029 &pfx_2001_1_3_s_128,
5030 FIB_SOURCE_ADJ);
5031 fib_table_entry_delete(fib_index,
5032 &pfx_2001_1_2_s_128,
5033 FIB_SOURCE_ADJ);
5034 local_pfx.fp_len = 64;
5035 fib_table_entry_delete(fib_index, &local_pfx,
5036 FIB_SOURCE_INTERFACE);
5037 local_pfx.fp_len = 128;
5038 fib_table_entry_special_remove(fib_index, &local_pfx,
5039 FIB_SOURCE_INTERFACE);
5040 connected_pfx.fp_len = 64;
5041 fib_table_entry_delete(fib_index, &connected_pfx,
5042 FIB_SOURCE_INTERFACE);
5043 connected_pfx.fp_len = 128;
5044 fib_table_entry_special_remove(fib_index, &connected_pfx,
5045 FIB_SOURCE_INTERFACE);
5046
5047 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5048 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5049 "2001::a/64 removed");
5050 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5051 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5052 "2001::b/64 removed");
5053 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5054 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5055 "2001:0:0:1::3/128 removed");
5056 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5057 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5058 "2001:0:0:1::3/128 removed");
5059 local_pfx.fp_len = 64;
5060 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5061 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5062 "2001:0:0:1/64 removed");
5063 local_pfx.fp_len = 128;
5064 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5065 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5066 "2001:0:0:1::1/128 removed");
5067 connected_pfx.fp_len = 64;
5068 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5069 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5070 "2001:0:0:2/64 removed");
5071 connected_pfx.fp_len = 128;
5072 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5073 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5074 "2001:0:0:2::1/128 removed");
5075
5076 /*
5077 * -8 entries. -7 path-lists (1 was shared).
5078 */
5079 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5080 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005081 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005082 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005083 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005084 fib_entry_pool_size());
5085
5086 /*
5087 * now remove the VRF
5088 */
Neale Ranns15002542017-09-10 04:39:11 -07005089 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005090
5091 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5092 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005093 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005094 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005095 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005096 fib_entry_pool_size());
5097
5098 adj_unlock(ai_02);
5099 adj_unlock(ai_01);
5100
5101 /*
5102 * return the interfaces to up state
5103 */
5104 error = vnet_sw_interface_set_flags(vnet_get_main(),
5105 tm->hw[0]->sw_if_index,
5106 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5107 error = vnet_sw_interface_set_flags(vnet_get_main(),
5108 tm->hw[1]->sw_if_index,
5109 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5110
5111 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5112 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005113
5114 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005115}
5116
5117/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005118 * Test Attached Exports
5119 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005120static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005121fib_test_ae (void)
5122{
5123 const dpo_id_t *dpo, *dpo_drop;
5124 const u32 fib_index = 0;
5125 fib_node_index_t fei;
5126 test_main_t *tm;
5127 ip4_main_t *im;
5128
5129 tm = &test_main;
5130 im = &ip4_main;
5131
5132 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5133 adj_nbr_db_size());
5134
5135 /*
5136 * add interface routes. We'll assume this works. It's more rigorously
5137 * tested elsewhere.
5138 */
5139 fib_prefix_t local_pfx = {
5140 .fp_len = 24,
5141 .fp_proto = FIB_PROTOCOL_IP4,
5142 .fp_addr = {
5143 .ip4 = {
5144 /* 10.10.10.10 */
5145 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5146 },
5147 },
5148 };
5149
5150 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5151 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5152
5153 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5154
5155 fib_table_entry_update_one_path(fib_index, &local_pfx,
5156 FIB_SOURCE_INTERFACE,
5157 (FIB_ENTRY_FLAG_CONNECTED |
5158 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005159 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005160 NULL,
5161 tm->hw[0]->sw_if_index,
5162 ~0,
5163 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005164 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005165 FIB_ROUTE_PATH_FLAG_NONE);
5166 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5167 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5168 "attached interface route present");
5169
5170 local_pfx.fp_len = 32;
5171 fib_table_entry_update_one_path(fib_index, &local_pfx,
5172 FIB_SOURCE_INTERFACE,
5173 (FIB_ENTRY_FLAG_CONNECTED |
5174 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07005175 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005176 NULL,
5177 tm->hw[0]->sw_if_index,
5178 ~0, // invalid fib index
5179 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005180 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005181 FIB_ROUTE_PATH_FLAG_NONE);
5182 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5183
5184 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5185 "local interface route present");
5186
5187 /*
5188 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5189 */
5190 fib_prefix_t pfx_10_10_10_1_s_32 = {
5191 .fp_len = 32,
5192 .fp_proto = FIB_PROTOCOL_IP4,
5193 .fp_addr = {
5194 /* 10.10.10.1 */
5195 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5196 },
5197 };
5198 fib_node_index_t ai;
5199
Neale Ranns81424992017-05-18 03:03:22 -07005200 fib_table_entry_path_add(fib_index,
5201 &pfx_10_10_10_1_s_32,
5202 FIB_SOURCE_ADJ,
5203 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005204 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005205 &pfx_10_10_10_1_s_32.fp_addr,
5206 tm->hw[0]->sw_if_index,
5207 ~0, // invalid fib index
5208 1,
5209 NULL,
5210 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005211
5212 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5213 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5214 ai = fib_entry_get_adj(fei);
5215
5216 /*
5217 * create another FIB table into which routes will be imported
5218 */
5219 u32 import_fib_index1;
5220
Neale Ranns15002542017-09-10 04:39:11 -07005221 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5222 11,
5223 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005224
5225 /*
5226 * Add an attached route in the import FIB
5227 */
5228 local_pfx.fp_len = 24;
5229 fib_table_entry_update_one_path(import_fib_index1,
5230 &local_pfx,
5231 FIB_SOURCE_API,
5232 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005233 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005234 NULL,
5235 tm->hw[0]->sw_if_index,
5236 ~0, // invalid fib index
5237 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005238 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005239 FIB_ROUTE_PATH_FLAG_NONE);
5240 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5241 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5242
5243 /*
5244 * check for the presence of the adj-fibs in the import table
5245 */
5246 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5247 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5248 FIB_TEST((ai == fib_entry_get_adj(fei)),
5249 "adj-fib1 Import uses same adj as export");
5250
5251 /*
5252 * check for the presence of the local in the import table
5253 */
5254 local_pfx.fp_len = 32;
5255 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5256 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5257
5258 /*
5259 * Add another adj-fin in the export table. Expect this
5260 * to get magically exported;
5261 */
5262 fib_prefix_t pfx_10_10_10_2_s_32 = {
5263 .fp_len = 32,
5264 .fp_proto = FIB_PROTOCOL_IP4,
5265 .fp_addr = {
5266 /* 10.10.10.2 */
5267 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5268 },
5269 };
5270
Neale Ranns81424992017-05-18 03:03:22 -07005271 fib_table_entry_path_add(fib_index,
5272 &pfx_10_10_10_2_s_32,
5273 FIB_SOURCE_ADJ,
5274 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005275 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005276 &pfx_10_10_10_2_s_32.fp_addr,
5277 tm->hw[0]->sw_if_index,
5278 ~0, // invalid fib index
5279 1,
5280 NULL,
5281 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005282 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5283 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5284 ai = fib_entry_get_adj(fei);
5285
5286 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5287 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5288 FIB_TEST((ai == fib_entry_get_adj(fei)),
5289 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005290 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5291 "ADJ-fib2 imported flags %d",
5292 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005293
5294 /*
5295 * create a 2nd FIB table into which routes will be imported
5296 */
5297 u32 import_fib_index2;
5298
Neale Ranns15002542017-09-10 04:39:11 -07005299 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5300 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005301
5302 /*
5303 * Add an attached route in the import FIB
5304 */
5305 local_pfx.fp_len = 24;
5306 fib_table_entry_update_one_path(import_fib_index2,
5307 &local_pfx,
5308 FIB_SOURCE_API,
5309 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005310 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005311 NULL,
5312 tm->hw[0]->sw_if_index,
5313 ~0, // invalid fib index
5314 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005315 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005316 FIB_ROUTE_PATH_FLAG_NONE);
5317 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5318 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5319
5320 /*
5321 * check for the presence of all the adj-fibs and local in the import table
5322 */
5323 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5324 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5325 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5326 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5327 local_pfx.fp_len = 32;
5328 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5329 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5330
5331 /*
5332 * add a 3rd adj-fib. expect it to be exported to both tables.
5333 */
5334 fib_prefix_t pfx_10_10_10_3_s_32 = {
5335 .fp_len = 32,
5336 .fp_proto = FIB_PROTOCOL_IP4,
5337 .fp_addr = {
5338 /* 10.10.10.3 */
5339 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5340 },
5341 };
5342
Neale Ranns81424992017-05-18 03:03:22 -07005343 fib_table_entry_path_add(fib_index,
5344 &pfx_10_10_10_3_s_32,
5345 FIB_SOURCE_ADJ,
5346 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005347 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005348 &pfx_10_10_10_3_s_32.fp_addr,
5349 tm->hw[0]->sw_if_index,
5350 ~0, // invalid fib index
5351 1,
5352 NULL,
5353 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005354 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5355 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5356 ai = fib_entry_get_adj(fei);
5357
5358 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5359 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5360 FIB_TEST((ai == fib_entry_get_adj(fei)),
5361 "Import uses same adj as export");
5362 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5363 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5364 FIB_TEST((ai == fib_entry_get_adj(fei)),
5365 "Import uses same adj as export");
5366
5367 /*
5368 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5369 */
5370 fib_table_entry_delete(fib_index,
5371 &pfx_10_10_10_3_s_32,
5372 FIB_SOURCE_ADJ);
5373
5374 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5375 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5376
5377 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5378 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5379
5380 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5381 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5382
5383 /*
5384 * remove the attached route from the 2nd FIB. expect the imported
5385 * entires to be removed
5386 */
5387 local_pfx.fp_len = 24;
5388 fib_table_entry_delete(import_fib_index2,
5389 &local_pfx,
5390 FIB_SOURCE_API);
5391 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5392 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5393
5394 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5395 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5396 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5397 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5398 local_pfx.fp_len = 32;
5399 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5400 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5401
5402 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5403 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5404 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5405 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5406 local_pfx.fp_len = 32;
5407 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5408 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5409
5410 /*
5411 * modify the route in FIB1 so it is no longer attached. expect the imported
5412 * entires to be removed
5413 */
5414 local_pfx.fp_len = 24;
5415 fib_table_entry_update_one_path(import_fib_index1,
5416 &local_pfx,
5417 FIB_SOURCE_API,
5418 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005419 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005420 &pfx_10_10_10_2_s_32.fp_addr,
5421 tm->hw[0]->sw_if_index,
5422 ~0, // invalid fib index
5423 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005424 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005425 FIB_ROUTE_PATH_FLAG_NONE);
5426 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5427 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5428 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5429 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5430 local_pfx.fp_len = 32;
5431 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5432 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5433
5434 /*
5435 * modify it back to attached. expect the adj-fibs back
5436 */
5437 local_pfx.fp_len = 24;
5438 fib_table_entry_update_one_path(import_fib_index1,
5439 &local_pfx,
5440 FIB_SOURCE_API,
5441 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005442 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005443 NULL,
5444 tm->hw[0]->sw_if_index,
5445 ~0, // invalid fib index
5446 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005447 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005448 FIB_ROUTE_PATH_FLAG_NONE);
5449 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5450 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5451 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5452 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5453 local_pfx.fp_len = 32;
5454 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5455 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5456
5457 /*
5458 * add a covering attached next-hop for the interface address, so we have
5459 * a valid adj to find when we check the forwarding tables
5460 */
5461 fib_prefix_t pfx_10_0_0_0_s_8 = {
5462 .fp_len = 8,
5463 .fp_proto = FIB_PROTOCOL_IP4,
5464 .fp_addr = {
5465 /* 10.0.0.0 */
5466 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5467 },
5468 };
5469
5470 fei = fib_table_entry_update_one_path(fib_index,
5471 &pfx_10_0_0_0_s_8,
5472 FIB_SOURCE_API,
5473 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005474 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005475 &pfx_10_10_10_3_s_32.fp_addr,
5476 tm->hw[0]->sw_if_index,
5477 ~0, // invalid fib index
5478 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005479 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005480 FIB_ROUTE_PATH_FLAG_NONE);
5481 dpo = fib_entry_contribute_ip_forwarding(fei);
5482
5483 /*
5484 * remove the route in the export fib. expect the adj-fibs to be removed
5485 */
5486 local_pfx.fp_len = 24;
5487 fib_table_entry_delete(fib_index,
5488 &local_pfx,
5489 FIB_SOURCE_INTERFACE);
5490
5491 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5492 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5493 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5494 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5495 local_pfx.fp_len = 32;
5496 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5497 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5498
5499 /*
5500 * the adj-fibs in the export VRF are present in the FIB table,
5501 * but not installed in forwarding, since they have no attached cover.
5502 * Consequently a lookup in the MTRIE gives the adj for the covering
5503 * route 10.0.0.0/8.
5504 */
5505 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5506 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5507
5508 index_t lbi;
5509 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5510 FIB_TEST(lbi == dpo->dpoi_index,
5511 "10.10.10.1 forwards on \n%U not \n%U",
5512 format_load_balance, lbi, 0,
5513 format_dpo_id, dpo, 0);
5514 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5515 FIB_TEST(lbi == dpo->dpoi_index,
5516 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5517 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5518 FIB_TEST(lbi == dpo->dpoi_index,
5519 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5520
5521 /*
5522 * add the export prefix back, but not as attached.
5523 * No adj-fibs in export nor import tables
5524 */
5525 local_pfx.fp_len = 24;
5526 fei = fib_table_entry_update_one_path(fib_index,
5527 &local_pfx,
5528 FIB_SOURCE_API,
5529 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005530 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005531 &pfx_10_10_10_1_s_32.fp_addr,
5532 tm->hw[0]->sw_if_index,
5533 ~0, // invalid fib index
5534 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005535 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005536 FIB_ROUTE_PATH_FLAG_NONE);
5537 dpo = fib_entry_contribute_ip_forwarding(fei);
5538
5539 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5540 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5541 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5542 FIB_TEST(lbi == dpo->dpoi_index,
5543 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5544 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5545 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5546 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5547 FIB_TEST(lbi == dpo->dpoi_index,
5548 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5549
5550 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5551 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5552 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5553 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5554 local_pfx.fp_len = 32;
5555 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5556 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5557
5558 /*
5559 * modify the export prefix so it is attached. expect all covereds to return
5560 */
5561 local_pfx.fp_len = 24;
5562 fib_table_entry_update_one_path(fib_index,
5563 &local_pfx,
5564 FIB_SOURCE_API,
5565 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005566 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005567 NULL,
5568 tm->hw[0]->sw_if_index,
5569 ~0, // invalid fib index
5570 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005571 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005572 FIB_ROUTE_PATH_FLAG_NONE);
5573
5574 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5575 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5576 dpo = fib_entry_contribute_ip_forwarding(fei);
5577 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5578 "Adj-fib1 is not drop in export");
5579 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5580 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5581 local_pfx.fp_len = 32;
5582 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5583 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5584 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5585 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5586 dpo = fib_entry_contribute_ip_forwarding(fei);
5587 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5588 "Adj-fib1 is not drop in export");
5589 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5590 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5591 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5592 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5593 local_pfx.fp_len = 32;
5594 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5595 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5596
5597 /*
5598 * modify the export prefix so connected. no change.
5599 */
5600 local_pfx.fp_len = 24;
5601 fib_table_entry_update_one_path(fib_index, &local_pfx,
5602 FIB_SOURCE_INTERFACE,
5603 (FIB_ENTRY_FLAG_CONNECTED |
5604 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005605 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005606 NULL,
5607 tm->hw[0]->sw_if_index,
5608 ~0,
5609 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005610 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005611 FIB_ROUTE_PATH_FLAG_NONE);
5612
5613 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5614 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5615 dpo = fib_entry_contribute_ip_forwarding(fei);
5616 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5617 "Adj-fib1 is not drop in export");
5618 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5619 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5620 local_pfx.fp_len = 32;
5621 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5622 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5623 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5624 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5625 dpo = fib_entry_contribute_ip_forwarding(fei);
5626 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5627 "Adj-fib1 is not drop in export");
5628 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5629 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5630 local_pfx.fp_len = 32;
5631 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5632 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5633
5634 /*
5635 * CLEANUP
5636 */
5637 fib_table_entry_delete(fib_index,
5638 &pfx_10_0_0_0_s_8,
5639 FIB_SOURCE_API);
5640 fib_table_entry_delete(fib_index,
5641 &pfx_10_10_10_1_s_32,
5642 FIB_SOURCE_ADJ);
5643 fib_table_entry_delete(fib_index,
5644 &pfx_10_10_10_2_s_32,
5645 FIB_SOURCE_ADJ);
5646 local_pfx.fp_len = 32;
5647 fib_table_entry_delete(fib_index,
5648 &local_pfx,
5649 FIB_SOURCE_INTERFACE);
5650 local_pfx.fp_len = 24;
5651 fib_table_entry_delete(fib_index,
5652 &local_pfx,
5653 FIB_SOURCE_API);
5654 fib_table_entry_delete(fib_index,
5655 &local_pfx,
5656 FIB_SOURCE_INTERFACE);
5657 local_pfx.fp_len = 24;
5658 fib_table_entry_delete(import_fib_index1,
5659 &local_pfx,
5660 FIB_SOURCE_API);
5661
Neale Ranns15002542017-09-10 04:39:11 -07005662 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5663 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005664
5665 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5666 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005667
5668 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005669}
5670
Neale Ranns57b58602017-07-15 07:37:25 -07005671/*
5672 * Test Path Preference
5673 */
5674static int
5675fib_test_pref (void)
5676{
5677 test_main_t *tm = &test_main;
5678
5679 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5680 .fp_len = 32,
5681 .fp_proto = FIB_PROTOCOL_IP4,
5682 .fp_addr = {
5683 .ip4 = {
5684 .as_u32 = clib_host_to_net_u32(0x01010101),
5685 },
5686 },
5687 };
5688
5689 /*
5690 * 2 high, 2 medium and 2 low preference non-recursive paths
5691 */
5692 fib_route_path_t nr_path_hi_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005693 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005694 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5695 .frp_fib_index = ~0,
5696 .frp_weight = 1,
5697 .frp_preference = 0,
5698 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5699 .frp_addr = {
5700 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5701 },
5702 };
5703 fib_route_path_t nr_path_hi_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005704 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005705 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5706 .frp_fib_index = ~0,
5707 .frp_weight = 1,
5708 .frp_preference = 0,
5709 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5710 .frp_addr = {
5711 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5712 },
5713 };
5714 fib_route_path_t nr_path_med_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005715 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005716 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5717 .frp_fib_index = ~0,
5718 .frp_weight = 1,
5719 .frp_preference = 1,
5720 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5721 .frp_addr = {
5722 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5723 },
5724 };
5725 fib_route_path_t nr_path_med_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005726 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005727 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5728 .frp_fib_index = ~0,
5729 .frp_weight = 1,
5730 .frp_preference = 1,
5731 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5732 .frp_addr = {
5733 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5734 },
5735 };
5736 fib_route_path_t nr_path_low_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005737 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005738 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5739 .frp_fib_index = ~0,
5740 .frp_weight = 1,
5741 .frp_preference = 2,
5742 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5743 .frp_addr = {
5744 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5745 },
5746 };
5747 fib_route_path_t nr_path_low_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005748 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005749 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5750 .frp_fib_index = ~0,
5751 .frp_weight = 1,
5752 .frp_preference = 2,
5753 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5754 .frp_addr = {
5755 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5756 },
5757 };
5758 fib_route_path_t *nr_paths = NULL;
5759
5760 vec_add1(nr_paths, nr_path_hi_1);
5761 vec_add1(nr_paths, nr_path_hi_2);
5762 vec_add1(nr_paths, nr_path_med_1);
5763 vec_add1(nr_paths, nr_path_med_2);
5764 vec_add1(nr_paths, nr_path_low_1);
5765 vec_add1(nr_paths, nr_path_low_2);
5766
5767 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5768 VNET_LINK_IP4,
5769 &nr_path_hi_1.frp_addr,
5770 nr_path_hi_1.frp_sw_if_index);
5771 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5772 VNET_LINK_IP4,
5773 &nr_path_hi_2.frp_addr,
5774 nr_path_hi_2.frp_sw_if_index);
5775 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5776 VNET_LINK_IP4,
5777 &nr_path_med_1.frp_addr,
5778 nr_path_med_1.frp_sw_if_index);
5779 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5780 VNET_LINK_IP4,
5781 &nr_path_med_2.frp_addr,
5782 nr_path_med_2.frp_sw_if_index);
5783 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5784 VNET_LINK_IP4,
5785 &nr_path_low_1.frp_addr,
5786 nr_path_low_1.frp_sw_if_index);
5787 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5788 VNET_LINK_IP4,
5789 &nr_path_low_2.frp_addr,
5790 nr_path_low_2.frp_sw_if_index);
5791
5792 fib_test_lb_bucket_t ip_hi_1 = {
5793 .type = FT_LB_ADJ,
5794 .adj = {
5795 .adj = ai_hi_1,
5796 },
5797 };
5798 fib_test_lb_bucket_t ip_hi_2 = {
5799 .type = FT_LB_ADJ,
5800 .adj = {
5801 .adj = ai_hi_2,
5802 },
5803 };
5804 fib_test_lb_bucket_t ip_med_1 = {
5805 .type = FT_LB_ADJ,
5806 .adj = {
5807 .adj = ai_med_1,
5808 },
5809 };
5810 fib_test_lb_bucket_t ip_med_2 = {
5811 .type = FT_LB_ADJ,
5812 .adj = {
5813 .adj = ai_med_2,
5814 },
5815 };
5816 fib_test_lb_bucket_t ip_low_1 = {
5817 .type = FT_LB_ADJ,
5818 .adj = {
5819 .adj = ai_low_1,
5820 },
5821 };
5822 fib_test_lb_bucket_t ip_low_2 = {
5823 .type = FT_LB_ADJ,
5824 .adj = {
5825 .adj = ai_low_2,
5826 },
5827 };
5828
5829 fib_node_index_t fei;
5830
5831 fei = fib_table_entry_path_add2(0,
5832 &pfx_1_1_1_1_s_32,
5833 FIB_SOURCE_API,
5834 FIB_ENTRY_FLAG_NONE,
5835 nr_paths);
5836
5837 FIB_TEST(fib_test_validate_entry(fei,
5838 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5839 2,
5840 &ip_hi_1,
5841 &ip_hi_2),
5842 "1.1.1.1/32 via high preference paths");
5843
5844 /*
5845 * bring down the interface on which the high preference path lie
5846 */
5847 vnet_sw_interface_set_flags(vnet_get_main(),
5848 tm->hw[0]->sw_if_index,
5849 0);
5850
5851 FIB_TEST(fib_test_validate_entry(fei,
5852 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5853 2,
5854 &ip_med_1,
5855 &ip_med_2),
5856 "1.1.1.1/32 via medium preference paths");
5857
5858 /*
5859 * bring down the interface on which the medium preference path lie
5860 */
5861 vnet_sw_interface_set_flags(vnet_get_main(),
5862 tm->hw[1]->sw_if_index,
5863 0);
5864
5865 FIB_TEST(fib_test_validate_entry(fei,
5866 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5867 2,
5868 &ip_low_1,
5869 &ip_low_2),
5870 "1.1.1.1/32 via low preference paths");
5871
5872 /*
5873 * bring up the interface on which the high preference path lie
5874 */
5875 vnet_sw_interface_set_flags(vnet_get_main(),
5876 tm->hw[0]->sw_if_index,
5877 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5878
5879 FIB_TEST(fib_test_validate_entry(fei,
5880 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5881 2,
5882 &ip_hi_1,
5883 &ip_hi_2),
5884 "1.1.1.1/32 via high preference paths");
5885
5886 /*
5887 * bring up the interface on which the medium preference path lie
5888 */
5889 vnet_sw_interface_set_flags(vnet_get_main(),
5890 tm->hw[1]->sw_if_index,
5891 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5892
5893 FIB_TEST(fib_test_validate_entry(fei,
5894 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5895 2,
5896 &ip_hi_1,
5897 &ip_hi_2),
5898 "1.1.1.1/32 via high preference paths");
5899
5900 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5901 fib_entry_contribute_forwarding(fei,
5902 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5903 &ip_1_1_1_1);
5904
5905 /*
5906 * 3 recursive paths of different preference
5907 */
5908 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5909 .fp_len = 32,
5910 .fp_proto = FIB_PROTOCOL_IP4,
5911 .fp_addr = {
5912 .ip4 = {
5913 .as_u32 = clib_host_to_net_u32(0x01010102),
5914 },
5915 },
5916 };
5917 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5918 .fp_len = 32,
5919 .fp_proto = FIB_PROTOCOL_IP4,
5920 .fp_addr = {
5921 .ip4 = {
5922 .as_u32 = clib_host_to_net_u32(0x01010103),
5923 },
5924 },
5925 };
5926 fei = fib_table_entry_path_add2(0,
5927 &pfx_1_1_1_2_s_32,
5928 FIB_SOURCE_API,
5929 FIB_ENTRY_FLAG_NONE,
5930 nr_paths);
5931 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5932 fib_entry_contribute_forwarding(fei,
5933 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5934 &ip_1_1_1_2);
5935 fei = fib_table_entry_path_add2(0,
5936 &pfx_1_1_1_3_s_32,
5937 FIB_SOURCE_API,
5938 FIB_ENTRY_FLAG_NONE,
5939 nr_paths);
5940 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
5941 fib_entry_contribute_forwarding(fei,
5942 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5943 &ip_1_1_1_3);
5944
5945 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
5946 .type = FT_LB_O_LB,
5947 .lb = {
5948 .lb = ip_1_1_1_1.dpoi_index,
5949 },
5950 };
5951 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
5952 .type = FT_LB_O_LB,
5953 .lb = {
5954 .lb = ip_1_1_1_2.dpoi_index,
5955 },
5956 };
5957 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
5958 .type = FT_LB_O_LB,
5959 .lb = {
5960 .lb = ip_1_1_1_3.dpoi_index,
5961 },
5962 };
5963 fib_route_path_t r_path_hi = {
Neale Rannsda78f952017-05-24 09:15:43 -07005964 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005965 .frp_sw_if_index = ~0,
5966 .frp_fib_index = 0,
5967 .frp_weight = 1,
5968 .frp_preference = 0,
5969 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5970 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
5971 };
5972 fib_route_path_t r_path_med = {
Neale Rannsda78f952017-05-24 09:15:43 -07005973 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005974 .frp_sw_if_index = ~0,
5975 .frp_fib_index = 0,
5976 .frp_weight = 1,
5977 .frp_preference = 10,
5978 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5979 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
5980 };
5981 fib_route_path_t r_path_low = {
Neale Rannsda78f952017-05-24 09:15:43 -07005982 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005983 .frp_sw_if_index = ~0,
5984 .frp_fib_index = 0,
5985 .frp_weight = 1,
Neale Rannsa0a908f2017-08-01 11:40:03 -07005986 .frp_preference = 255,
Neale Ranns57b58602017-07-15 07:37:25 -07005987 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5988 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
5989 };
5990 fib_route_path_t *r_paths = NULL;
5991
5992 vec_add1(r_paths, r_path_hi);
5993 vec_add1(r_paths, r_path_low);
5994 vec_add1(r_paths, r_path_med);
5995
5996 /*
5997 * add many recursive so we get the LB MAp created
5998 */
5999 #define N_PFXS 64
6000 fib_prefix_t pfx_r[N_PFXS];
Marek Gradzkiaf095512017-08-15 07:38:26 +02006001 unsigned int n_pfxs;
Neale Ranns57b58602017-07-15 07:37:25 -07006002 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6003 {
6004 pfx_r[n_pfxs].fp_len = 32;
6005 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
6006 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
6007 clib_host_to_net_u32(0x02000000 + n_pfxs);
6008
6009 fei = fib_table_entry_path_add2(0,
6010 &pfx_r[n_pfxs],
6011 FIB_SOURCE_API,
6012 FIB_ENTRY_FLAG_NONE,
6013 r_paths);
6014
6015 FIB_TEST(fib_test_validate_entry(fei,
6016 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6017 1,
6018 &ip_o_1_1_1_1),
6019 "recursive via high preference paths");
6020
6021 /*
6022 * withdraw hig pref resolving entry
6023 */
6024 fib_table_entry_delete(0,
6025 &pfx_1_1_1_1_s_32,
6026 FIB_SOURCE_API);
6027
6028 /* suspend so the update walk kicks int */
6029 vlib_process_suspend(vlib_get_main(), 1e-5);
6030
6031 FIB_TEST(fib_test_validate_entry(fei,
6032 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6033 1,
6034 &ip_o_1_1_1_2),
6035 "recursive via medium preference paths");
6036
6037 /*
6038 * withdraw medium pref resolving entry
6039 */
6040 fib_table_entry_delete(0,
6041 &pfx_1_1_1_2_s_32,
6042 FIB_SOURCE_API);
6043
6044 /* suspend so the update walk kicks int */
6045 vlib_process_suspend(vlib_get_main(), 1e-5);
6046
6047 FIB_TEST(fib_test_validate_entry(fei,
6048 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6049 1,
6050 &ip_o_1_1_1_3),
6051 "recursive via low preference paths");
6052
6053 /*
6054 * add back paths for next iteration
6055 */
6056 fei = fib_table_entry_update(0,
6057 &pfx_1_1_1_2_s_32,
6058 FIB_SOURCE_API,
6059 FIB_ENTRY_FLAG_NONE,
6060 nr_paths);
6061 fei = fib_table_entry_update(0,
6062 &pfx_1_1_1_1_s_32,
6063 FIB_SOURCE_API,
6064 FIB_ENTRY_FLAG_NONE,
6065 nr_paths);
6066
6067 /* suspend so the update walk kicks int */
6068 vlib_process_suspend(vlib_get_main(), 1e-5);
6069
6070 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6071 FIB_TEST(fib_test_validate_entry(fei,
6072 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6073 1,
6074 &ip_o_1_1_1_1),
6075 "recursive via high preference paths");
6076 }
6077
6078
6079 fib_table_entry_delete(0,
6080 &pfx_1_1_1_1_s_32,
6081 FIB_SOURCE_API);
6082
6083 /* suspend so the update walk kicks int */
6084 vlib_process_suspend(vlib_get_main(), 1e-5);
6085
6086 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6087 {
6088 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6089
6090 FIB_TEST(fib_test_validate_entry(fei,
6091 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6092 1,
6093 &ip_o_1_1_1_2),
6094 "recursive via medium preference paths");
6095 }
6096 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6097 {
6098 fib_table_entry_delete(0,
6099 &pfx_r[n_pfxs],
6100 FIB_SOURCE_API);
6101 }
6102
6103 /*
6104 * Cleanup
6105 */
6106 fib_table_entry_delete(0,
6107 &pfx_1_1_1_2_s_32,
6108 FIB_SOURCE_API);
6109 fib_table_entry_delete(0,
6110 &pfx_1_1_1_3_s_32,
6111 FIB_SOURCE_API);
6112
6113 dpo_reset(&ip_1_1_1_1);
6114 dpo_reset(&ip_1_1_1_2);
6115 dpo_reset(&ip_1_1_1_3);
6116 adj_unlock(ai_low_2);
6117 adj_unlock(ai_low_1);
6118 adj_unlock(ai_med_2);
6119 adj_unlock(ai_med_1);
6120 adj_unlock(ai_hi_2);
6121 adj_unlock(ai_hi_1);
6122 return (0);
6123}
Neale Rannsad422ed2016-11-02 14:20:04 +00006124
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006125/*
6126 * Test the recursive route route handling for GRE tunnels
6127 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006128static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006129fib_test_label (void)
6130{
6131 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;
6132 const u32 fib_index = 0;
6133 test_main_t *tm;
6134 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00006135 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006136
6137 lb_count = pool_elts(load_balance_pool);
6138 tm = &test_main;
6139 im = &ip4_main;
6140
6141 /*
6142 * add interface routes. We'll assume this works. It's more rigorously
6143 * tested elsewhere.
6144 */
6145 fib_prefix_t local0_pfx = {
6146 .fp_len = 24,
6147 .fp_proto = FIB_PROTOCOL_IP4,
6148 .fp_addr = {
6149 .ip4 = {
6150 /* 10.10.10.10 */
6151 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6152 },
6153 },
6154 };
6155
6156 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6157 adj_nbr_db_size());
6158
6159 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6160 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6161
6162 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6163 FIB_SOURCE_INTERFACE,
6164 (FIB_ENTRY_FLAG_CONNECTED |
6165 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006166 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006167 NULL,
6168 tm->hw[0]->sw_if_index,
6169 ~0,
6170 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006171 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006172 FIB_ROUTE_PATH_FLAG_NONE);
6173 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6174 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6175 "attached interface route present");
6176
6177 local0_pfx.fp_len = 32;
6178 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6179 FIB_SOURCE_INTERFACE,
6180 (FIB_ENTRY_FLAG_CONNECTED |
6181 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006182 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006183 NULL,
6184 tm->hw[0]->sw_if_index,
6185 ~0, // invalid fib index
6186 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006187 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006188 FIB_ROUTE_PATH_FLAG_NONE);
6189 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6190
6191 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6192 "local interface route present");
6193
6194 fib_prefix_t local1_pfx = {
6195 .fp_len = 24,
6196 .fp_proto = FIB_PROTOCOL_IP4,
6197 .fp_addr = {
6198 .ip4 = {
6199 /* 10.10.11.10 */
6200 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6201 },
6202 },
6203 };
6204
6205 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6206 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6207
6208 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6209 FIB_SOURCE_INTERFACE,
6210 (FIB_ENTRY_FLAG_CONNECTED |
6211 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006212 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006213 NULL,
6214 tm->hw[1]->sw_if_index,
6215 ~0,
6216 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006217 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006218 FIB_ROUTE_PATH_FLAG_NONE);
6219 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6220 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6221 "attached interface route present");
6222
6223 local1_pfx.fp_len = 32;
6224 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6225 FIB_SOURCE_INTERFACE,
6226 (FIB_ENTRY_FLAG_CONNECTED |
6227 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006228 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006229 NULL,
6230 tm->hw[1]->sw_if_index,
6231 ~0, // invalid fib index
6232 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006233 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006234 FIB_ROUTE_PATH_FLAG_NONE);
6235 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6236
6237 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6238 "local interface route present");
6239
6240 ip46_address_t nh_10_10_10_1 = {
6241 .ip4 = {
6242 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6243 },
6244 };
6245 ip46_address_t nh_10_10_11_1 = {
6246 .ip4 = {
6247 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6248 },
6249 };
6250 ip46_address_t nh_10_10_11_2 = {
6251 .ip4 = {
6252 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6253 },
6254 };
6255
6256 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006257 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006258 &nh_10_10_11_1,
6259 tm->hw[1]->sw_if_index);
6260 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006261 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006262 &nh_10_10_11_2,
6263 tm->hw[1]->sw_if_index);
6264 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006265 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006266 &nh_10_10_10_1,
6267 tm->hw[0]->sw_if_index);
6268 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006269 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006270 &nh_10_10_11_2,
6271 tm->hw[1]->sw_if_index);
6272 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006273 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006274 &nh_10_10_11_1,
6275 tm->hw[1]->sw_if_index);
6276
6277 /*
6278 * Add an etry with one path with a real out-going label
6279 */
6280 fib_prefix_t pfx_1_1_1_1_s_32 = {
6281 .fp_len = 32,
6282 .fp_proto = FIB_PROTOCOL_IP4,
6283 .fp_addr = {
6284 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6285 },
6286 };
6287 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6288 .type = FT_LB_LABEL_O_ADJ,
6289 .label_o_adj = {
6290 .adj = ai_mpls_10_10_10_1,
6291 .label = 99,
6292 .eos = MPLS_EOS,
6293 },
6294 };
6295 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6296 .type = FT_LB_LABEL_O_ADJ,
6297 .label_o_adj = {
6298 .adj = ai_mpls_10_10_10_1,
6299 .label = 99,
6300 .eos = MPLS_NON_EOS,
6301 },
6302 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006303 mpls_label_t *l99 = NULL;
6304 vec_add1(l99, 99);
6305
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006306 fib_table_entry_update_one_path(fib_index,
6307 &pfx_1_1_1_1_s_32,
6308 FIB_SOURCE_API,
6309 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006310 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006311 &nh_10_10_10_1,
6312 tm->hw[0]->sw_if_index,
6313 ~0, // invalid fib index
6314 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006315 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006316 FIB_ROUTE_PATH_FLAG_NONE);
6317
6318 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6319 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6320
6321 FIB_TEST(fib_test_validate_entry(fei,
6322 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6323 1,
6324 &l99_eos_o_10_10_10_1),
6325 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6326
6327 /*
6328 * add a path with an implicit NULL label
6329 */
6330 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6331 .type = FT_LB_ADJ,
6332 .adj = {
6333 .adj = ai_v4_10_10_11_1,
6334 },
6335 };
6336 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6337 .type = FT_LB_ADJ,
6338 .adj = {
6339 .adj = ai_mpls_10_10_11_1,
6340 },
6341 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006342 mpls_label_t *l_imp_null = NULL;
6343 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006344
6345 fei = fib_table_entry_path_add(fib_index,
6346 &pfx_1_1_1_1_s_32,
6347 FIB_SOURCE_API,
6348 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006349 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006350 &nh_10_10_11_1,
6351 tm->hw[1]->sw_if_index,
6352 ~0, // invalid fib index
6353 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006354 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006355 FIB_ROUTE_PATH_FLAG_NONE);
6356
6357 FIB_TEST(fib_test_validate_entry(fei,
6358 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6359 2,
6360 &l99_eos_o_10_10_10_1,
6361 &a_o_10_10_11_1),
6362 "1.1.1.1/32 LB 2 buckets via: "
6363 "label 99 over 10.10.10.1, "
6364 "adj over 10.10.11.1");
6365
6366 /*
6367 * assign the route a local label
6368 */
6369 fib_table_entry_local_label_add(fib_index,
6370 &pfx_1_1_1_1_s_32,
6371 24001);
6372
6373 fib_prefix_t pfx_24001_eos = {
6374 .fp_proto = FIB_PROTOCOL_MPLS,
6375 .fp_label = 24001,
6376 .fp_eos = MPLS_EOS,
6377 };
6378 fib_prefix_t pfx_24001_neos = {
6379 .fp_proto = FIB_PROTOCOL_MPLS,
6380 .fp_label = 24001,
6381 .fp_eos = MPLS_NON_EOS,
6382 };
6383
6384 /*
6385 * The EOS entry should link to both the paths,
6386 * and use an ip adj for the imp-null
6387 * The NON-EOS entry should link to both the paths,
6388 * and use an mpls adj for the imp-null
6389 */
6390 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6391 &pfx_24001_eos);
6392 FIB_TEST(fib_test_validate_entry(fei,
6393 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6394 2,
6395 &l99_eos_o_10_10_10_1,
6396 &a_o_10_10_11_1),
6397 "24001/eos LB 2 buckets via: "
6398 "label 99 over 10.10.10.1, "
6399 "adj over 10.10.11.1");
6400
6401
6402 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6403 &pfx_24001_neos);
6404 FIB_TEST(fib_test_validate_entry(fei,
6405 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6406 2,
6407 &l99_neos_o_10_10_10_1,
6408 &a_mpls_o_10_10_11_1),
6409 "24001/neos LB 1 bucket via: "
6410 "label 99 over 10.10.10.1 ",
6411 "mpls-adj via 10.10.11.1");
6412
6413 /*
6414 * add an unlabelled path, this is excluded from the neos chains,
6415 */
6416 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6417 .type = FT_LB_ADJ,
6418 .adj = {
6419 .adj = ai_v4_10_10_11_2,
6420 },
6421 };
6422
6423 fei = fib_table_entry_path_add(fib_index,
6424 &pfx_1_1_1_1_s_32,
6425 FIB_SOURCE_API,
6426 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006427 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006428 &nh_10_10_11_2,
6429 tm->hw[1]->sw_if_index,
6430 ~0, // invalid fib index
6431 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006432 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006433 FIB_ROUTE_PATH_FLAG_NONE);
6434
6435 FIB_TEST(fib_test_validate_entry(fei,
6436 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6437 16, // 3 choices spread over 16 buckets
6438 &l99_eos_o_10_10_10_1,
6439 &l99_eos_o_10_10_10_1,
6440 &l99_eos_o_10_10_10_1,
6441 &l99_eos_o_10_10_10_1,
6442 &l99_eos_o_10_10_10_1,
6443 &l99_eos_o_10_10_10_1,
6444 &a_o_10_10_11_1,
6445 &a_o_10_10_11_1,
6446 &a_o_10_10_11_1,
6447 &a_o_10_10_11_1,
6448 &a_o_10_10_11_1,
6449 &adj_o_10_10_11_2,
6450 &adj_o_10_10_11_2,
6451 &adj_o_10_10_11_2,
6452 &adj_o_10_10_11_2,
6453 &adj_o_10_10_11_2),
6454 "1.1.1.1/32 LB 16 buckets via: "
6455 "label 99 over 10.10.10.1, "
6456 "adj over 10.10.11.1",
6457 "adj over 10.10.11.2");
6458
6459 /*
6460 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6461 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006462 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006463 fib_entry_contribute_forwarding(fei,
6464 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6465 &non_eos_1_1_1_1);
6466
6467 /*
6468 * n-eos has only the 2 labelled paths
6469 */
6470 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6471 &pfx_24001_neos);
6472
6473 FIB_TEST(fib_test_validate_entry(fei,
6474 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6475 2,
6476 &l99_neos_o_10_10_10_1,
6477 &a_mpls_o_10_10_11_1),
6478 "24001/neos LB 2 buckets via: "
6479 "label 99 over 10.10.10.1, "
6480 "adj-mpls over 10.10.11.2");
6481
6482 /*
6483 * A labelled recursive
6484 */
6485 fib_prefix_t pfx_2_2_2_2_s_32 = {
6486 .fp_len = 32,
6487 .fp_proto = FIB_PROTOCOL_IP4,
6488 .fp_addr = {
6489 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6490 },
6491 };
6492 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6493 .type = FT_LB_LABEL_O_LB,
6494 .label_o_lb = {
6495 .lb = non_eos_1_1_1_1.dpoi_index,
6496 .label = 1600,
6497 .eos = MPLS_EOS,
6498 },
6499 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006500 mpls_label_t *l1600 = NULL;
6501 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006502
6503 fib_table_entry_update_one_path(fib_index,
6504 &pfx_2_2_2_2_s_32,
6505 FIB_SOURCE_API,
6506 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006507 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006508 &pfx_1_1_1_1_s_32.fp_addr,
6509 ~0,
6510 fib_index,
6511 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006512 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006513 FIB_ROUTE_PATH_FLAG_NONE);
6514
6515 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6516 FIB_TEST(fib_test_validate_entry(fei,
6517 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6518 1,
6519 &l1600_eos_o_1_1_1_1),
6520 "2.2.2.2.2/32 LB 1 buckets via: "
6521 "label 1600 over 1.1.1.1");
6522
Neale Ranns948e00f2016-10-20 13:39:34 +01006523 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01006524 index_t urpfi;
6525
6526 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6527 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6528
6529 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6530 "uRPF check for 2.2.2.2/32 on %d OK",
6531 tm->hw[0]->sw_if_index);
6532 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6533 "uRPF check for 2.2.2.2/32 on %d OK",
6534 tm->hw[1]->sw_if_index);
6535 FIB_TEST(!fib_urpf_check(urpfi, 99),
6536 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6537 99);
6538
6539 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6540 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6541 "Shared uRPF on IP and non-EOS chain");
6542
6543 dpo_reset(&dpo_44);
6544
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006545 /*
6546 * we are holding a lock on the non-eos LB of the via-entry.
6547 * do a PIC-core failover by shutting the link of the via-entry.
6548 *
6549 * shut down the link with the valid label
6550 */
6551 vnet_sw_interface_set_flags(vnet_get_main(),
6552 tm->hw[0]->sw_if_index,
6553 0);
6554
6555 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6556 FIB_TEST(fib_test_validate_entry(fei,
6557 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6558 2,
6559 &a_o_10_10_11_1,
6560 &adj_o_10_10_11_2),
6561 "1.1.1.1/32 LB 2 buckets via: "
6562 "adj over 10.10.11.1, ",
6563 "adj-v4 over 10.10.11.2");
6564
6565 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6566 &pfx_24001_eos);
6567 FIB_TEST(fib_test_validate_entry(fei,
6568 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6569 2,
6570 &a_o_10_10_11_1,
6571 &adj_o_10_10_11_2),
6572 "24001/eos LB 2 buckets via: "
6573 "adj over 10.10.11.1, ",
6574 "adj-v4 over 10.10.11.2");
6575
6576 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6577 &pfx_24001_neos);
6578 FIB_TEST(fib_test_validate_entry(fei,
6579 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6580 1,
6581 &a_mpls_o_10_10_11_1),
6582 "24001/neos LB 1 buckets via: "
6583 "adj-mpls over 10.10.11.2");
6584
6585 /*
6586 * test that the pre-failover load-balance has been in-place
6587 * modified
6588 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006589 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006590 fib_entry_contribute_forwarding(fei,
6591 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6592 &current);
6593
6594 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6595 &current),
6596 "PIC-core LB inplace modified %U %U",
6597 format_dpo_id, &non_eos_1_1_1_1, 0,
6598 format_dpo_id, &current, 0);
6599
6600 dpo_reset(&non_eos_1_1_1_1);
6601 dpo_reset(&current);
6602
6603 /*
6604 * no-shut the link with the valid label
6605 */
6606 vnet_sw_interface_set_flags(vnet_get_main(),
6607 tm->hw[0]->sw_if_index,
6608 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6609
6610 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6611 FIB_TEST(fib_test_validate_entry(fei,
6612 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6613 16, // 3 choices spread over 16 buckets
6614 &l99_eos_o_10_10_10_1,
6615 &l99_eos_o_10_10_10_1,
6616 &l99_eos_o_10_10_10_1,
6617 &l99_eos_o_10_10_10_1,
6618 &l99_eos_o_10_10_10_1,
6619 &l99_eos_o_10_10_10_1,
6620 &a_o_10_10_11_1,
6621 &a_o_10_10_11_1,
6622 &a_o_10_10_11_1,
6623 &a_o_10_10_11_1,
6624 &a_o_10_10_11_1,
6625 &adj_o_10_10_11_2,
6626 &adj_o_10_10_11_2,
6627 &adj_o_10_10_11_2,
6628 &adj_o_10_10_11_2,
6629 &adj_o_10_10_11_2),
6630 "1.1.1.1/32 LB 16 buckets via: "
6631 "label 99 over 10.10.10.1, "
6632 "adj over 10.10.11.1",
6633 "adj-v4 over 10.10.11.2");
6634
6635
6636 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6637 &pfx_24001_eos);
6638 FIB_TEST(fib_test_validate_entry(fei,
6639 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6640 16, // 3 choices spread over 16 buckets
6641 &l99_eos_o_10_10_10_1,
6642 &l99_eos_o_10_10_10_1,
6643 &l99_eos_o_10_10_10_1,
6644 &l99_eos_o_10_10_10_1,
6645 &l99_eos_o_10_10_10_1,
6646 &l99_eos_o_10_10_10_1,
6647 &a_o_10_10_11_1,
6648 &a_o_10_10_11_1,
6649 &a_o_10_10_11_1,
6650 &a_o_10_10_11_1,
6651 &a_o_10_10_11_1,
6652 &adj_o_10_10_11_2,
6653 &adj_o_10_10_11_2,
6654 &adj_o_10_10_11_2,
6655 &adj_o_10_10_11_2,
6656 &adj_o_10_10_11_2),
6657 "24001/eos LB 16 buckets via: "
6658 "label 99 over 10.10.10.1, "
6659 "adj over 10.10.11.1",
6660 "adj-v4 over 10.10.11.2");
6661
6662 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6663 &pfx_24001_neos);
6664 FIB_TEST(fib_test_validate_entry(fei,
6665 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6666 2,
6667 &l99_neos_o_10_10_10_1,
6668 &a_mpls_o_10_10_11_1),
6669 "24001/neos LB 2 buckets via: "
6670 "label 99 over 10.10.10.1, "
6671 "adj-mpls over 10.10.11.2");
6672
6673 /*
6674 * remove the first path with the valid label
6675 */
6676 fib_table_entry_path_remove(fib_index,
6677 &pfx_1_1_1_1_s_32,
6678 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006679 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006680 &nh_10_10_10_1,
6681 tm->hw[0]->sw_if_index,
6682 ~0, // invalid fib index
6683 1,
6684 FIB_ROUTE_PATH_FLAG_NONE);
6685
6686 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6687 FIB_TEST(fib_test_validate_entry(fei,
6688 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6689 2,
6690 &a_o_10_10_11_1,
6691 &adj_o_10_10_11_2),
6692 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006693 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006694 "adj-v4 over 10.10.11.2");
6695
6696 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6697 &pfx_24001_eos);
6698 FIB_TEST(fib_test_validate_entry(fei,
6699 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6700 2,
6701 &a_o_10_10_11_1,
6702 &adj_o_10_10_11_2),
6703 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006704 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006705 "adj-v4 over 10.10.11.2");
6706
6707 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6708 &pfx_24001_neos);
6709
6710 FIB_TEST(fib_test_validate_entry(fei,
6711 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6712 1,
6713 &a_mpls_o_10_10_11_1),
6714 "24001/neos LB 1 buckets via: "
6715 "adj-mpls over 10.10.11.2");
6716
6717 /*
6718 * remove the other path with a valid label
6719 */
6720 fib_test_lb_bucket_t bucket_drop = {
Neale Rannsd792d9c2017-10-21 10:53:20 -07006721 .type = FT_LB_DROP,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006722 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006723 fib_test_lb_bucket_t mpls_bucket_drop = {
Neale Rannsd792d9c2017-10-21 10:53:20 -07006724 .type = FT_LB_DROP,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006725 .special = {
6726 .adj = DPO_PROTO_MPLS,
6727 },
6728 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006729
6730 fib_table_entry_path_remove(fib_index,
6731 &pfx_1_1_1_1_s_32,
6732 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006733 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006734 &nh_10_10_11_1,
6735 tm->hw[1]->sw_if_index,
6736 ~0, // invalid fib index
6737 1,
6738 FIB_ROUTE_PATH_FLAG_NONE);
6739
6740 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6741 FIB_TEST(fib_test_validate_entry(fei,
6742 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6743 1,
6744 &adj_o_10_10_11_2),
6745 "1.1.1.1/32 LB 1 buckets via: "
6746 "adj over 10.10.11.2");
6747
6748 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6749 &pfx_24001_eos);
6750 FIB_TEST(fib_test_validate_entry(fei,
6751 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6752 1,
6753 &adj_o_10_10_11_2),
6754 "24001/eos LB 1 buckets via: "
6755 "adj over 10.10.11.2");
6756
6757 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6758 &pfx_24001_neos);
6759 FIB_TEST(fib_test_validate_entry(fei,
6760 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006761 1,
6762 &mpls_bucket_drop),
6763 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006764
6765 /*
6766 * add back the path with the valid label
6767 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006768 l99 = NULL;
6769 vec_add1(l99, 99);
6770
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006771 fib_table_entry_path_add(fib_index,
6772 &pfx_1_1_1_1_s_32,
6773 FIB_SOURCE_API,
6774 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006775 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006776 &nh_10_10_10_1,
6777 tm->hw[0]->sw_if_index,
6778 ~0, // invalid fib index
6779 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006780 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006781 FIB_ROUTE_PATH_FLAG_NONE);
6782
6783 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6784 FIB_TEST(fib_test_validate_entry(fei,
6785 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6786 2,
6787 &l99_eos_o_10_10_10_1,
6788 &adj_o_10_10_11_2),
6789 "1.1.1.1/32 LB 2 buckets via: "
6790 "label 99 over 10.10.10.1, "
6791 "adj over 10.10.11.2");
6792
6793 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6794 &pfx_24001_eos);
6795 FIB_TEST(fib_test_validate_entry(fei,
6796 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6797 2,
6798 &l99_eos_o_10_10_10_1,
6799 &adj_o_10_10_11_2),
6800 "24001/eos LB 2 buckets via: "
6801 "label 99 over 10.10.10.1, "
6802 "adj over 10.10.11.2");
6803
6804 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6805 &pfx_24001_neos);
6806 FIB_TEST(fib_test_validate_entry(fei,
6807 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6808 1,
6809 &l99_neos_o_10_10_10_1),
6810 "24001/neos LB 1 buckets via: "
6811 "label 99 over 10.10.10.1");
6812
6813 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006814 * change the local label
6815 */
6816 fib_table_entry_local_label_add(fib_index,
6817 &pfx_1_1_1_1_s_32,
6818 25005);
6819
6820 fib_prefix_t pfx_25005_eos = {
6821 .fp_proto = FIB_PROTOCOL_MPLS,
6822 .fp_label = 25005,
6823 .fp_eos = MPLS_EOS,
6824 };
6825 fib_prefix_t pfx_25005_neos = {
6826 .fp_proto = FIB_PROTOCOL_MPLS,
6827 .fp_label = 25005,
6828 .fp_eos = MPLS_NON_EOS,
6829 };
6830
6831 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6832 fib_table_lookup(fib_index, &pfx_24001_eos)),
6833 "24001/eos removed after label change");
6834 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6835 fib_table_lookup(fib_index, &pfx_24001_neos)),
6836 "24001/eos removed after label change");
6837
6838 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6839 &pfx_25005_eos);
6840 FIB_TEST(fib_test_validate_entry(fei,
6841 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6842 2,
6843 &l99_eos_o_10_10_10_1,
6844 &adj_o_10_10_11_2),
6845 "25005/eos LB 2 buckets via: "
6846 "label 99 over 10.10.10.1, "
6847 "adj over 10.10.11.2");
6848
6849 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6850 &pfx_25005_neos);
6851 FIB_TEST(fib_test_validate_entry(fei,
6852 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6853 1,
6854 &l99_neos_o_10_10_10_1),
6855 "25005/neos LB 1 buckets via: "
6856 "label 99 over 10.10.10.1");
6857
6858 /*
6859 * remove the local label.
6860 * the check that the MPLS entries are gone is done by the fact the
6861 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006862 */
6863 fib_table_entry_local_label_remove(fib_index,
6864 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006865 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006866
6867 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6868 FIB_TEST(fib_test_validate_entry(fei,
6869 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6870 2,
6871 &l99_eos_o_10_10_10_1,
6872 &adj_o_10_10_11_2),
6873 "24001/eos LB 2 buckets via: "
6874 "label 99 over 10.10.10.1, "
6875 "adj over 10.10.11.2");
6876
6877 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6878 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6879 "No more MPLS FIB entries => table removed");
6880
6881 /*
6882 * add another via-entry for the recursive
6883 */
6884 fib_prefix_t pfx_1_1_1_2_s_32 = {
6885 .fp_len = 32,
6886 .fp_proto = FIB_PROTOCOL_IP4,
6887 .fp_addr = {
6888 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6889 },
6890 };
6891 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6892 .type = FT_LB_LABEL_O_ADJ,
6893 .label_o_adj = {
6894 .adj = ai_mpls_10_10_10_1,
6895 .label = 101,
6896 .eos = MPLS_EOS,
6897 },
6898 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006899 mpls_label_t *l101 = NULL;
6900 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006901
6902 fei = fib_table_entry_update_one_path(fib_index,
6903 &pfx_1_1_1_2_s_32,
6904 FIB_SOURCE_API,
6905 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006906 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006907 &nh_10_10_10_1,
6908 tm->hw[0]->sw_if_index,
6909 ~0, // invalid fib index
6910 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006911 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006912 FIB_ROUTE_PATH_FLAG_NONE);
6913
6914 FIB_TEST(fib_test_validate_entry(fei,
6915 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6916 1,
6917 &l101_eos_o_10_10_10_1),
6918 "1.1.1.2/32 LB 1 buckets via: "
6919 "label 101 over 10.10.10.1");
6920
Neale Ranns948e00f2016-10-20 13:39:34 +01006921 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006922 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6923 &pfx_1_1_1_1_s_32),
6924 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6925 &non_eos_1_1_1_1);
6926 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6927 &pfx_1_1_1_2_s_32),
6928 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6929 &non_eos_1_1_1_2);
6930
6931 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6932 .type = FT_LB_LABEL_O_LB,
6933 .label_o_lb = {
6934 .lb = non_eos_1_1_1_2.dpoi_index,
6935 .label = 1601,
6936 .eos = MPLS_EOS,
6937 },
6938 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006939 mpls_label_t *l1601 = NULL;
6940 vec_add1(l1601, 1601);
6941
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006942 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6943
6944 fei = fib_table_entry_path_add(fib_index,
6945 &pfx_2_2_2_2_s_32,
6946 FIB_SOURCE_API,
6947 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006948 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006949 &pfx_1_1_1_2_s_32.fp_addr,
6950 ~0,
6951 fib_index,
6952 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006953 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006954 FIB_ROUTE_PATH_FLAG_NONE);
6955
6956 FIB_TEST(fib_test_validate_entry(fei,
6957 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6958 2,
6959 &l1600_eos_o_1_1_1_1,
6960 &l1601_eos_o_1_1_1_2),
6961 "2.2.2.2/32 LB 2 buckets via: "
6962 "label 1600 via 1.1,1.1, "
6963 "label 16001 via 1.1.1.2");
6964
6965 /*
6966 * update the via-entry so it no longer has an imp-null path.
6967 * the LB for the recursive can use an imp-null
6968 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006969 l_imp_null = NULL;
6970 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6971
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006972 fei = fib_table_entry_update_one_path(fib_index,
6973 &pfx_1_1_1_2_s_32,
6974 FIB_SOURCE_API,
6975 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006976 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006977 &nh_10_10_11_1,
6978 tm->hw[1]->sw_if_index,
6979 ~0, // invalid fib index
6980 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006981 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006982 FIB_ROUTE_PATH_FLAG_NONE);
6983
6984 FIB_TEST(fib_test_validate_entry(fei,
6985 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6986 1,
6987 &a_o_10_10_11_1),
6988 "1.1.1.2/32 LB 1 buckets via: "
6989 "adj 10.10.11.1");
6990
6991 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6992 FIB_TEST(fib_test_validate_entry(fei,
6993 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6994 2,
6995 &l1600_eos_o_1_1_1_1,
6996 &l1601_eos_o_1_1_1_2),
6997 "2.2.2.2/32 LB 2 buckets via: "
6998 "label 1600 via 1.1,1.1, "
6999 "label 16001 via 1.1.1.2");
7000
7001 /*
7002 * update the via-entry so it no longer has labelled paths.
7003 * the LB for the recursive should exclue this via form its LB
7004 */
7005 fei = fib_table_entry_update_one_path(fib_index,
7006 &pfx_1_1_1_2_s_32,
7007 FIB_SOURCE_API,
7008 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007009 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007010 &nh_10_10_11_1,
7011 tm->hw[1]->sw_if_index,
7012 ~0, // invalid fib index
7013 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007014 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007015 FIB_ROUTE_PATH_FLAG_NONE);
7016
7017 FIB_TEST(fib_test_validate_entry(fei,
7018 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7019 1,
7020 &a_o_10_10_11_1),
7021 "1.1.1.2/32 LB 1 buckets via: "
7022 "adj 10.10.11.1");
7023
7024 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7025 FIB_TEST(fib_test_validate_entry(fei,
7026 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7027 1,
7028 &l1600_eos_o_1_1_1_1),
7029 "2.2.2.2/32 LB 1 buckets via: "
7030 "label 1600 via 1.1,1.1");
7031
7032 dpo_reset(&non_eos_1_1_1_1);
7033 dpo_reset(&non_eos_1_1_1_2);
7034
7035 /*
7036 * Add a recursive with no out-labels. We expect to use the IP of the via
7037 */
7038 fib_prefix_t pfx_2_2_2_3_s_32 = {
7039 .fp_len = 32,
7040 .fp_proto = FIB_PROTOCOL_IP4,
7041 .fp_addr = {
7042 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7043 },
7044 };
Neale Ranns948e00f2016-10-20 13:39:34 +01007045 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007046
7047 fib_table_entry_update_one_path(fib_index,
7048 &pfx_2_2_2_3_s_32,
7049 FIB_SOURCE_API,
7050 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007051 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007052 &pfx_1_1_1_1_s_32.fp_addr,
7053 ~0,
7054 fib_index,
7055 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007056 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007057 FIB_ROUTE_PATH_FLAG_NONE);
7058
7059 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7060 &pfx_1_1_1_1_s_32),
7061 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7062 &ip_1_1_1_1);
7063
7064 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7065 .type = FT_LB_O_LB,
7066 .lb = {
7067 .lb = ip_1_1_1_1.dpoi_index,
7068 },
7069 };
7070
7071 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7072 FIB_TEST(fib_test_validate_entry(fei,
7073 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7074 1,
7075 &ip_o_1_1_1_1),
7076 "2.2.2.2.3/32 LB 1 buckets via: "
7077 "ip 1.1.1.1");
7078
7079 /*
7080 * Add a recursive with an imp-null out-label.
7081 * We expect to use the IP of the via
7082 */
7083 fib_prefix_t pfx_2_2_2_4_s_32 = {
7084 .fp_len = 32,
7085 .fp_proto = FIB_PROTOCOL_IP4,
7086 .fp_addr = {
7087 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7088 },
7089 };
7090
7091 fib_table_entry_update_one_path(fib_index,
7092 &pfx_2_2_2_4_s_32,
7093 FIB_SOURCE_API,
7094 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007095 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007096 &pfx_1_1_1_1_s_32.fp_addr,
7097 ~0,
7098 fib_index,
7099 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007100 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007101 FIB_ROUTE_PATH_FLAG_NONE);
7102
7103 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7104 FIB_TEST(fib_test_validate_entry(fei,
7105 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7106 1,
7107 &ip_o_1_1_1_1),
7108 "2.2.2.2.4/32 LB 1 buckets via: "
7109 "ip 1.1.1.1");
7110
7111 dpo_reset(&ip_1_1_1_1);
7112
7113 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00007114 * Create an entry with a deep label stack
7115 */
7116 fib_prefix_t pfx_2_2_5_5_s_32 = {
7117 .fp_len = 32,
7118 .fp_proto = FIB_PROTOCOL_IP4,
7119 .fp_addr = {
7120 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7121 },
7122 };
7123 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7124 .type = FT_LB_LABEL_STACK_O_ADJ,
7125 .label_stack_o_adj = {
7126 .adj = ai_mpls_10_10_11_1,
7127 .label_stack_size = 8,
7128 .label_stack = {
7129 200, 201, 202, 203, 204, 205, 206, 207
7130 },
7131 .eos = MPLS_EOS,
7132 },
7133 };
7134 mpls_label_t *label_stack = NULL;
7135 vec_validate(label_stack, 7);
7136 for (ii = 0; ii < 8; ii++)
7137 {
7138 label_stack[ii] = ii + 200;
7139 }
7140
7141 fei = fib_table_entry_update_one_path(fib_index,
7142 &pfx_2_2_5_5_s_32,
7143 FIB_SOURCE_API,
7144 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007145 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00007146 &nh_10_10_11_1,
7147 tm->hw[1]->sw_if_index,
7148 ~0, // invalid fib index
7149 1,
7150 label_stack,
7151 FIB_ROUTE_PATH_FLAG_NONE);
7152
7153 FIB_TEST(fib_test_validate_entry(fei,
7154 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7155 1,
7156 &ls_eos_o_10_10_10_1),
7157 "2.2.5.5/32 LB 1 buckets via: "
7158 "adj 10.10.11.1");
7159 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7160
7161 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007162 * cleanup
7163 */
7164 fib_table_entry_delete(fib_index,
7165 &pfx_1_1_1_2_s_32,
7166 FIB_SOURCE_API);
7167
7168 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7169 FIB_TEST(fib_test_validate_entry(fei,
7170 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7171 1,
7172 &l1600_eos_o_1_1_1_1),
7173 "2.2.2.2/32 LB 1 buckets via: "
7174 "label 1600 via 1.1,1.1");
7175
7176 fib_table_entry_delete(fib_index,
7177 &pfx_1_1_1_1_s_32,
7178 FIB_SOURCE_API);
7179
7180 FIB_TEST(fib_test_validate_entry(fei,
7181 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7182 1,
7183 &bucket_drop),
7184 "2.2.2.2/32 LB 1 buckets via: DROP");
7185
7186 fib_table_entry_delete(fib_index,
7187 &pfx_2_2_2_2_s_32,
7188 FIB_SOURCE_API);
7189 fib_table_entry_delete(fib_index,
7190 &pfx_2_2_2_3_s_32,
7191 FIB_SOURCE_API);
7192 fib_table_entry_delete(fib_index,
7193 &pfx_2_2_2_4_s_32,
7194 FIB_SOURCE_API);
7195
7196 adj_unlock(ai_mpls_10_10_10_1);
7197 adj_unlock(ai_mpls_10_10_11_2);
7198 adj_unlock(ai_v4_10_10_11_1);
7199 adj_unlock(ai_v4_10_10_11_2);
7200 adj_unlock(ai_mpls_10_10_11_1);
7201
7202 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7203 adj_nbr_db_size());
7204
7205 local0_pfx.fp_len = 32;
7206 fib_table_entry_delete(fib_index,
7207 &local0_pfx,
7208 FIB_SOURCE_INTERFACE);
7209 local0_pfx.fp_len = 24;
7210 fib_table_entry_delete(fib_index,
7211 &local0_pfx,
7212 FIB_SOURCE_INTERFACE);
7213 local1_pfx.fp_len = 32;
7214 fib_table_entry_delete(fib_index,
7215 &local1_pfx,
7216 FIB_SOURCE_INTERFACE);
7217 local1_pfx.fp_len = 24;
7218 fib_table_entry_delete(fib_index,
7219 &local1_pfx,
7220 FIB_SOURCE_INTERFACE);
7221
7222 /*
7223 * +1 for the drop LB in the MPLS tables.
7224 */
7225 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7226 "Load-balance resources freed %d of %d",
7227 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007228
7229 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007230}
7231
7232#define N_TEST_CHILDREN 4
7233#define PARENT_INDEX 0
7234
7235typedef struct fib_node_test_t_
7236{
7237 fib_node_t node;
7238 u32 sibling;
7239 u32 index;
7240 fib_node_back_walk_ctx_t *ctxs;
7241 u32 destroyed;
7242} fib_node_test_t;
7243
7244static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7245
7246#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7247
7248#define FOR_EACH_TEST_CHILD(_tc) \
7249 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7250 ii < N_TEST_CHILDREN+1; \
7251 ii++, (_tc) = &fib_test_nodes[ii])
7252
7253static fib_node_t *
7254fib_test_child_get_node (fib_node_index_t index)
7255{
7256 return (&fib_test_nodes[index].node);
7257}
7258
7259static int fib_test_walk_spawns_walks;
7260
7261static fib_node_back_walk_rc_t
7262fib_test_child_back_walk_notify (fib_node_t *node,
7263 fib_node_back_walk_ctx_t *ctx)
7264{
7265 fib_node_test_t *tc = (fib_node_test_t*) node;
7266
7267 vec_add1(tc->ctxs, *ctx);
7268
7269 if (1 == fib_test_walk_spawns_walks)
7270 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7271 if (2 == fib_test_walk_spawns_walks)
7272 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7273 FIB_WALK_PRIORITY_HIGH, ctx);
7274
7275 return (FIB_NODE_BACK_WALK_CONTINUE);
7276}
7277
7278static void
7279fib_test_child_last_lock_gone (fib_node_t *node)
7280{
7281 fib_node_test_t *tc = (fib_node_test_t *)node;
7282
7283 tc->destroyed = 1;
7284}
7285
7286/**
7287 * The FIB walk's graph node virtual function table
7288 */
7289static const fib_node_vft_t fib_test_child_vft = {
7290 .fnv_get = fib_test_child_get_node,
7291 .fnv_last_lock = fib_test_child_last_lock_gone,
7292 .fnv_back_walk = fib_test_child_back_walk_notify,
7293};
7294
7295/*
7296 * the function (that should have been static but isn't so I can do this)
7297 * that processes the walk from the async queue,
7298 */
7299f64 fib_walk_process_queues(vlib_main_t * vm,
7300 const f64 quota);
7301u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7302
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007303static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007304fib_test_walk (void)
7305{
7306 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7307 fib_node_test_t *tc;
7308 vlib_main_t *vm;
7309 u32 ii;
7310
7311 vm = vlib_get_main();
7312 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7313
7314 /*
7315 * init a fake node on which we will add children
7316 */
7317 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7318 FIB_NODE_TYPE_TEST);
7319
7320 FOR_EACH_TEST_CHILD(tc)
7321 {
7322 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7323 fib_node_lock(&tc->node);
7324 tc->ctxs = NULL;
7325 tc->index = ii;
7326 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7327 PARENT_INDEX,
7328 FIB_NODE_TYPE_TEST, ii);
7329 }
7330
7331 /*
7332 * enqueue a walk across the parents children.
7333 */
Neale Ranns450cd302016-11-09 17:49:42 +00007334 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007335
7336 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7337 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7338 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7339 "Parent has %d children pre-walk",
7340 fib_node_list_get_size(PARENT()->fn_children));
7341
7342 /*
7343 * give the walk a large amount of time so it gets to the end
7344 */
7345 fib_walk_process_queues(vm, 1);
7346
7347 FOR_EACH_TEST_CHILD(tc)
7348 {
7349 FIB_TEST(1 == vec_len(tc->ctxs),
7350 "%d child visitsed %d times",
7351 ii, vec_len(tc->ctxs));
7352 vec_free(tc->ctxs);
7353 }
7354 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7355 "Queue is empty post walk");
7356 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7357 "Parent has %d children post walk",
7358 fib_node_list_get_size(PARENT()->fn_children));
7359
7360 /*
7361 * walk again. should be no increase in the number of visits, since
7362 * the walk will have terminated.
7363 */
7364 fib_walk_process_queues(vm, 1);
7365
7366 FOR_EACH_TEST_CHILD(tc)
7367 {
7368 FIB_TEST(0 == vec_len(tc->ctxs),
7369 "%d child visitsed %d times",
7370 ii, vec_len(tc->ctxs));
7371 }
7372
7373 /*
7374 * schedule a low and hig priority walk. expect the high to be performed
7375 * before the low.
7376 * schedule the high prio walk first so that it is further from the head
7377 * of the dependency list. that way it won't merge with the low one.
7378 */
7379 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7380 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7381
7382 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7383 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7384 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7385 FIB_WALK_PRIORITY_LOW, &low_ctx);
7386
7387 fib_walk_process_queues(vm, 1);
7388
7389 FOR_EACH_TEST_CHILD(tc)
7390 {
7391 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7392 "%d child visitsed by high prio walk", ii);
7393 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7394 "%d child visitsed by low prio walk", ii);
7395 vec_free(tc->ctxs);
7396 }
7397 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7398 "Queue is empty post prio walk");
7399 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7400 "Parent has %d children post prio walk",
7401 fib_node_list_get_size(PARENT()->fn_children));
7402
7403 /*
7404 * schedule 2 walks of the same priority that can be megred.
7405 * expect that each child is thus visited only once.
7406 */
7407 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7408 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7409
7410 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7411 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7412 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7413 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7414
7415 fib_walk_process_queues(vm, 1);
7416
7417 FOR_EACH_TEST_CHILD(tc)
7418 {
7419 FIB_TEST(1 == vec_len(tc->ctxs),
7420 "%d child visitsed %d times during merge walk",
7421 ii, vec_len(tc->ctxs));
7422 vec_free(tc->ctxs);
7423 }
7424 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7425 "Queue is empty post merge walk");
7426 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7427 "Parent has %d children post merge walk",
7428 fib_node_list_get_size(PARENT()->fn_children));
7429
7430 /*
7431 * schedule 2 walks of the same priority that cannot be megred.
7432 * expect that each child is thus visited twice and in the order
7433 * in which the walks were scheduled.
7434 */
7435 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7436 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7437
7438 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7439 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7440 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7441 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7442
7443 fib_walk_process_queues(vm, 1);
7444
7445 FOR_EACH_TEST_CHILD(tc)
7446 {
7447 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7448 "%d child visitsed by high prio walk", ii);
7449 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7450 "%d child visitsed by low prio walk", ii);
7451 vec_free(tc->ctxs);
7452 }
7453 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7454 "Queue is empty post no-merge walk");
7455 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7456 "Parent has %d children post no-merge walk",
7457 fib_node_list_get_size(PARENT()->fn_children));
7458
7459 /*
7460 * schedule a walk that makes one one child progress.
7461 * we do this by giving the queue draining process zero
7462 * time quanta. it's a do..while loop, so it does something.
7463 */
Neale Ranns450cd302016-11-09 17:49:42 +00007464 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007465
7466 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7467 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7468 fib_walk_process_queues(vm, 0);
7469
7470 FOR_EACH_TEST_CHILD(tc)
7471 {
7472 if (ii == N_TEST_CHILDREN)
7473 {
7474 FIB_TEST(1 == vec_len(tc->ctxs),
7475 "%d child visitsed %d times in zero quanta walk",
7476 ii, vec_len(tc->ctxs));
7477 }
7478 else
7479 {
7480 FIB_TEST(0 == vec_len(tc->ctxs),
7481 "%d child visitsed %d times in 0 quanta walk",
7482 ii, vec_len(tc->ctxs));
7483 }
7484 }
7485 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7486 "Queue is not empty post zero quanta walk");
7487 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7488 "Parent has %d children post zero qunta walk",
7489 fib_node_list_get_size(PARENT()->fn_children));
7490
7491 /*
7492 * another one step
7493 */
7494 fib_walk_process_queues(vm, 0);
7495
7496 FOR_EACH_TEST_CHILD(tc)
7497 {
7498 if (ii >= N_TEST_CHILDREN-1)
7499 {
7500 FIB_TEST(1 == vec_len(tc->ctxs),
7501 "%d child visitsed %d times in 2nd zero quanta walk",
7502 ii, vec_len(tc->ctxs));
7503 }
7504 else
7505 {
7506 FIB_TEST(0 == vec_len(tc->ctxs),
7507 "%d child visitsed %d times in 2nd 0 quanta walk",
7508 ii, vec_len(tc->ctxs));
7509 }
7510 }
7511 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7512 "Queue is not empty post zero quanta walk");
7513 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7514 "Parent has %d children post zero qunta walk",
7515 fib_node_list_get_size(PARENT()->fn_children));
7516
7517 /*
7518 * schedule another walk that will catch-up and merge.
7519 */
7520 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7521 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7522 fib_walk_process_queues(vm, 1);
7523
7524 FOR_EACH_TEST_CHILD(tc)
7525 {
7526 if (ii >= N_TEST_CHILDREN-1)
7527 {
7528 FIB_TEST(2 == vec_len(tc->ctxs),
7529 "%d child visitsed %d times in 2nd zero quanta merge walk",
7530 ii, vec_len(tc->ctxs));
7531 vec_free(tc->ctxs);
7532 }
7533 else
7534 {
7535 FIB_TEST(1 == vec_len(tc->ctxs),
7536 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7537 ii, vec_len(tc->ctxs));
7538 vec_free(tc->ctxs);
7539 }
7540 }
7541 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7542 "Queue is not empty post 2nd zero quanta merge walk");
7543 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7544 "Parent has %d children post 2nd zero qunta merge walk",
7545 fib_node_list_get_size(PARENT()->fn_children));
7546
7547 /*
7548 * park a async walk in the middle of the list, then have an sync walk catch
7549 * it. same expectations as async catches async.
7550 */
Neale Ranns450cd302016-11-09 17:49:42 +00007551 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007552
7553 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7554 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7555
7556 fib_walk_process_queues(vm, 0);
7557 fib_walk_process_queues(vm, 0);
7558
7559 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7560
7561 FOR_EACH_TEST_CHILD(tc)
7562 {
7563 if (ii >= N_TEST_CHILDREN-1)
7564 {
7565 FIB_TEST(2 == vec_len(tc->ctxs),
7566 "%d child visitsed %d times in sync catches async walk",
7567 ii, vec_len(tc->ctxs));
7568 vec_free(tc->ctxs);
7569 }
7570 else
7571 {
7572 FIB_TEST(1 == vec_len(tc->ctxs),
7573 "%d child visitsed %d times in sync catches async walk",
7574 ii, vec_len(tc->ctxs));
7575 vec_free(tc->ctxs);
7576 }
7577 }
7578 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7579 "Queue is not empty post 2nd zero quanta merge walk");
7580 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7581 "Parent has %d children post 2nd zero qunta merge walk",
7582 fib_node_list_get_size(PARENT()->fn_children));
7583
7584 /*
7585 * make the parent a child of one of its children, thus inducing a routing loop.
7586 */
7587 fib_test_nodes[PARENT_INDEX].sibling =
7588 fib_node_child_add(FIB_NODE_TYPE_TEST,
7589 1, // the first child
7590 FIB_NODE_TYPE_TEST,
7591 PARENT_INDEX);
7592
7593 /*
7594 * execute a sync walk from the parent. each child visited spawns more sync
7595 * walks. we expect the walk to terminate.
7596 */
7597 fib_test_walk_spawns_walks = 1;
7598
7599 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7600
7601 FOR_EACH_TEST_CHILD(tc)
7602 {
7603 /*
7604 * child 1 - which is last in the list - has the loop.
7605 * the other children a re thus visitsed first. the we meet
7606 * child 1. we go round the loop again, visting the other children.
7607 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7608 * again.
7609 */
7610 if (1 == ii)
7611 {
7612 FIB_TEST(1 == vec_len(tc->ctxs),
7613 "child %d visitsed %d times during looped sync walk",
7614 ii, vec_len(tc->ctxs));
7615 }
7616 else
7617 {
7618 FIB_TEST(2 == vec_len(tc->ctxs),
7619 "child %d visitsed %d times during looped sync walk",
7620 ii, vec_len(tc->ctxs));
7621 }
7622 vec_free(tc->ctxs);
7623 }
7624 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7625 "Parent has %d children post sync loop walk",
7626 fib_node_list_get_size(PARENT()->fn_children));
7627
7628 /*
7629 * the walk doesn't reach the max depth because the infra knows that sync
7630 * meets sync implies a loop and bails early.
7631 */
7632 FIB_TEST(high_ctx.fnbw_depth == 9,
7633 "Walk context depth %d post sync loop walk",
7634 high_ctx.fnbw_depth);
7635
7636 /*
7637 * execute an async walk of the graph loop, with each child spawns sync walks
7638 */
7639 high_ctx.fnbw_depth = 0;
7640 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7641 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7642
7643 fib_walk_process_queues(vm, 1);
7644
7645 FOR_EACH_TEST_CHILD(tc)
7646 {
7647 /*
7648 * we don't really care how many times the children are visisted, as long as
7649 * it is more than once.
7650 */
7651 FIB_TEST(1 <= vec_len(tc->ctxs),
7652 "child %d visitsed %d times during looped aync spawns sync walk",
7653 ii, vec_len(tc->ctxs));
7654 vec_free(tc->ctxs);
7655 }
7656
7657 /*
7658 * execute an async walk of the graph loop, with each child spawns async walks
7659 */
7660 fib_test_walk_spawns_walks = 2;
7661 high_ctx.fnbw_depth = 0;
7662 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7663 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7664
7665 fib_walk_process_queues(vm, 1);
7666
7667 FOR_EACH_TEST_CHILD(tc)
7668 {
7669 /*
7670 * we don't really care how many times the children are visisted, as long as
7671 * it is more than once.
7672 */
7673 FIB_TEST(1 <= vec_len(tc->ctxs),
7674 "child %d visitsed %d times during looped async spawns async walk",
7675 ii, vec_len(tc->ctxs));
7676 vec_free(tc->ctxs);
7677 }
7678
7679
7680 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7681 1, // the first child
7682 fib_test_nodes[PARENT_INDEX].sibling);
7683
7684 /*
7685 * cleanup
7686 */
7687 FOR_EACH_TEST_CHILD(tc)
7688 {
7689 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7690 tc->sibling);
7691 fib_node_deinit(&tc->node);
7692 fib_node_unlock(&tc->node);
7693 }
7694 fib_node_deinit(PARENT());
7695
7696 /*
7697 * The parent will be destroyed when the last lock on it goes.
7698 * this test ensures all the walk objects are unlocking it.
7699 */
7700 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7701 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007702
7703 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007704}
7705
Neale Ranns88fc83e2017-04-05 08:11:14 -07007706/*
7707 * declaration of the otherwise static callback functions
7708 */
7709void fib_bfd_notify (bfd_listen_event_e event,
7710 const bfd_session_t *session);
7711void adj_bfd_notify (bfd_listen_event_e event,
7712 const bfd_session_t *session);
7713
7714/**
7715 * Test BFD session interaction with FIB
7716 */
7717static int
7718fib_test_bfd (void)
7719{
7720 fib_node_index_t fei;
7721 test_main_t *tm;
7722 int n_feis;
7723
7724 /* via 10.10.10.1 */
7725 ip46_address_t nh_10_10_10_1 = {
7726 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7727 };
7728 /* via 10.10.10.2 */
7729 ip46_address_t nh_10_10_10_2 = {
7730 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7731 };
7732 /* via 10.10.10.10 */
7733 ip46_address_t nh_10_10_10_10 = {
7734 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7735 };
7736 n_feis = fib_entry_pool_size();
7737
7738 tm = &test_main;
7739
7740 /*
7741 * add interface routes. we'll assume this works. it's tested elsewhere
7742 */
7743 fib_prefix_t pfx_10_10_10_10_s_24 = {
7744 .fp_len = 24,
7745 .fp_proto = FIB_PROTOCOL_IP4,
7746 .fp_addr = nh_10_10_10_10,
7747 };
7748
7749 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7750 FIB_SOURCE_INTERFACE,
7751 (FIB_ENTRY_FLAG_CONNECTED |
7752 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07007753 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007754 NULL,
7755 tm->hw[0]->sw_if_index,
7756 ~0, // invalid fib index
7757 1, // weight
7758 NULL,
7759 FIB_ROUTE_PATH_FLAG_NONE);
7760
7761 fib_prefix_t pfx_10_10_10_10_s_32 = {
7762 .fp_len = 32,
7763 .fp_proto = FIB_PROTOCOL_IP4,
7764 .fp_addr = nh_10_10_10_10,
7765 };
7766 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7767 FIB_SOURCE_INTERFACE,
7768 (FIB_ENTRY_FLAG_CONNECTED |
7769 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07007770 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007771 NULL,
7772 tm->hw[0]->sw_if_index,
7773 ~0, // invalid fib index
7774 1, // weight
7775 NULL,
7776 FIB_ROUTE_PATH_FLAG_NONE);
7777
7778 /*
7779 * A BFD session via a neighbour we do not yet know
7780 */
7781 bfd_session_t bfd_10_10_10_1 = {
7782 .udp = {
7783 .key = {
7784 .fib_index = 0,
7785 .peer_addr = nh_10_10_10_1,
7786 },
7787 },
7788 .hop_type = BFD_HOP_TYPE_MULTI,
7789 .local_state = BFD_STATE_init,
7790 };
7791
7792 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7793
7794 /*
7795 * A new entry will be created that forwards via the adj
7796 */
7797 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7798 VNET_LINK_IP4,
7799 &nh_10_10_10_1,
7800 tm->hw[0]->sw_if_index);
7801 fib_prefix_t pfx_10_10_10_1_s_32 = {
7802 .fp_addr = nh_10_10_10_1,
7803 .fp_len = 32,
7804 .fp_proto = FIB_PROTOCOL_IP4,
7805 };
7806 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7807 .type = FT_LB_ADJ,
7808 .adj = {
7809 .adj = ai_10_10_10_1,
7810 },
7811 };
7812
7813 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7814 FIB_TEST(fib_test_validate_entry(fei,
7815 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7816 1,
7817 &adj_o_10_10_10_1),
7818 "BFD sourced %U via %U",
7819 format_fib_prefix, &pfx_10_10_10_1_s_32,
7820 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7821
7822 /*
7823 * Delete the BFD session. Expect the fib_entry to be removed
7824 */
7825 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7826
7827 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7828 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7829 "BFD sourced %U removed",
7830 format_fib_prefix, &pfx_10_10_10_1_s_32);
7831
7832 /*
7833 * Add the BFD source back
7834 */
7835 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7836
7837 /*
7838 * source the entry via the ADJ fib
7839 */
Neale Ranns81424992017-05-18 03:03:22 -07007840 fei = fib_table_entry_path_add(0,
7841 &pfx_10_10_10_1_s_32,
7842 FIB_SOURCE_ADJ,
7843 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007844 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007845 &nh_10_10_10_1,
7846 tm->hw[0]->sw_if_index,
7847 ~0, // invalid fib index
7848 1,
7849 NULL,
7850 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007851
7852 /*
7853 * Delete the BFD session. Expect the fib_entry to remain
7854 */
7855 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7856
7857 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7858 FIB_TEST(fib_test_validate_entry(fei,
7859 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7860 1,
7861 &adj_o_10_10_10_1),
7862 "BFD sourced %U remains via %U",
7863 format_fib_prefix, &pfx_10_10_10_1_s_32,
7864 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7865
7866 /*
7867 * Add the BFD source back
7868 */
7869 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7870
7871 /*
7872 * Create another ADJ FIB
7873 */
7874 fib_prefix_t pfx_10_10_10_2_s_32 = {
7875 .fp_addr = nh_10_10_10_2,
7876 .fp_len = 32,
7877 .fp_proto = FIB_PROTOCOL_IP4,
7878 };
Neale Ranns81424992017-05-18 03:03:22 -07007879 fib_table_entry_path_add(0,
7880 &pfx_10_10_10_2_s_32,
7881 FIB_SOURCE_ADJ,
7882 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007883 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007884 &nh_10_10_10_2,
7885 tm->hw[0]->sw_if_index,
7886 ~0, // invalid fib index
7887 1,
7888 NULL,
7889 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007890 /*
7891 * A BFD session for the new ADJ FIB
7892 */
7893 bfd_session_t bfd_10_10_10_2 = {
7894 .udp = {
7895 .key = {
7896 .fib_index = 0,
7897 .peer_addr = nh_10_10_10_2,
7898 },
7899 },
7900 .hop_type = BFD_HOP_TYPE_MULTI,
7901 .local_state = BFD_STATE_init,
7902 };
7903
7904 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7905
7906 /*
7907 * remove the adj-fib source whilst the session is present
7908 * then add it back
7909 */
7910 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07007911 fib_table_entry_path_add(0,
7912 &pfx_10_10_10_2_s_32,
7913 FIB_SOURCE_ADJ,
7914 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007915 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007916 &nh_10_10_10_2,
7917 tm->hw[0]->sw_if_index,
7918 ~0, // invalid fib index
7919 1,
7920 NULL,
7921 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007922
7923 /*
7924 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7925 * bring one of the sessions UP, leave the other down
7926 */
7927 bfd_10_10_10_1.local_state = BFD_STATE_up;
7928 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7929 bfd_10_10_10_2.local_state = BFD_STATE_down;
7930 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7931
7932 /*
7933 * A recursive prefix via both of the ADJ FIBs
7934 */
7935 fib_prefix_t pfx_200_0_0_0_s_24 = {
7936 .fp_proto = FIB_PROTOCOL_IP4,
7937 .fp_len = 32,
7938 .fp_addr = {
7939 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7940 },
7941 };
7942 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7943
7944 dpo_10_10_10_1 =
7945 fib_entry_contribute_ip_forwarding(
7946 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7947 dpo_10_10_10_2 =
7948 fib_entry_contribute_ip_forwarding(
7949 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7950
7951 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7952 .type = FT_LB_O_LB,
7953 .lb = {
7954 .lb = dpo_10_10_10_1->dpoi_index,
7955 },
7956 };
7957 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7958 .type = FT_LB_O_LB,
7959 .lb = {
7960 .lb = dpo_10_10_10_2->dpoi_index,
7961 },
7962 };
7963
7964 /*
7965 * A prefix via the adj-fib that is BFD down => DROP
7966 */
7967 fei = fib_table_entry_path_add(0,
7968 &pfx_200_0_0_0_s_24,
7969 FIB_SOURCE_API,
7970 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007971 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007972 &nh_10_10_10_2,
7973 ~0, // recursive
7974 0, // default fib index
7975 1,
7976 NULL,
7977 FIB_ROUTE_PATH_FLAG_NONE);
7978 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7979 "%U resolves via drop",
7980 format_fib_prefix, &pfx_200_0_0_0_s_24);
7981
7982 /*
7983 * add a path via the UP BFD adj-fib.
7984 * we expect that the DOWN BFD ADJ FIB is not used.
7985 */
7986 fei = fib_table_entry_path_add(0,
7987 &pfx_200_0_0_0_s_24,
7988 FIB_SOURCE_API,
7989 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007990 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007991 &nh_10_10_10_1,
7992 ~0, // recursive
7993 0, // default fib index
7994 1,
7995 NULL,
7996 FIB_ROUTE_PATH_FLAG_NONE);
7997
7998 FIB_TEST(fib_test_validate_entry(fei,
7999 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8000 1,
8001 &lb_o_10_10_10_1),
8002 "Recursive %U only UP BFD adj-fibs",
8003 format_fib_prefix, &pfx_200_0_0_0_s_24);
8004
8005 /*
8006 * Send a BFD state change to UP - both sessions are now up
8007 * the recursive prefix should LB over both
8008 */
8009 bfd_10_10_10_2.local_state = BFD_STATE_up;
8010 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8011
8012
8013 FIB_TEST(fib_test_validate_entry(fei,
8014 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8015 2,
8016 &lb_o_10_10_10_1,
8017 &lb_o_10_10_10_2),
8018 "Recursive %U via both UP BFD adj-fibs",
8019 format_fib_prefix, &pfx_200_0_0_0_s_24);
8020
8021 /*
8022 * Send a BFD state change to DOWN
8023 * the recursive prefix should exclude the down
8024 */
8025 bfd_10_10_10_2.local_state = BFD_STATE_down;
8026 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
8027
8028
8029 FIB_TEST(fib_test_validate_entry(fei,
8030 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8031 1,
8032 &lb_o_10_10_10_1),
8033 "Recursive %U via only UP",
8034 format_fib_prefix, &pfx_200_0_0_0_s_24);
8035
8036 /*
8037 * Delete the BFD session while it is in the DOWN state.
8038 * FIB should consider the entry's state as back up
8039 */
8040 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8041
8042 FIB_TEST(fib_test_validate_entry(fei,
8043 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8044 2,
8045 &lb_o_10_10_10_1,
8046 &lb_o_10_10_10_2),
8047 "Recursive %U via both UP BFD adj-fibs post down session delete",
8048 format_fib_prefix, &pfx_200_0_0_0_s_24);
8049
8050 /*
8051 * Delete the BFD other session while it is in the UP state.
8052 */
8053 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8054
8055 FIB_TEST(fib_test_validate_entry(fei,
8056 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8057 2,
8058 &lb_o_10_10_10_1,
8059 &lb_o_10_10_10_2),
8060 "Recursive %U via both UP BFD adj-fibs post up session delete",
8061 format_fib_prefix, &pfx_200_0_0_0_s_24);
8062
8063 /*
8064 * cleaup
8065 */
8066 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8067 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8068 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8069
8070 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8071 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8072
8073 adj_unlock(ai_10_10_10_1);
8074 /*
8075 * test no-one left behind
8076 */
8077 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8078 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8079
8080 /*
8081 * Single-hop BFD tests
8082 */
8083 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8084 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8085
8086 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8087
8088 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8089 VNET_LINK_IP4,
8090 &nh_10_10_10_1,
8091 tm->hw[0]->sw_if_index);
8092 /*
8093 * whilst the BFD session is not signalled, the adj is up
8094 */
8095 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8096
8097 /*
8098 * bring the BFD session up
8099 */
8100 bfd_10_10_10_1.local_state = BFD_STATE_up;
8101 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8102 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8103
8104 /*
8105 * bring the BFD session down
8106 */
8107 bfd_10_10_10_1.local_state = BFD_STATE_down;
8108 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8109 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8110
8111
8112 /*
8113 * add an attached next hop FIB entry via the down adj
8114 */
8115 fib_prefix_t pfx_5_5_5_5_s_32 = {
8116 .fp_addr = {
8117 .ip4 = {
8118 .as_u32 = clib_host_to_net_u32(0x05050505),
8119 },
8120 },
8121 .fp_len = 32,
8122 .fp_proto = FIB_PROTOCOL_IP4,
8123 };
8124
8125 fei = fib_table_entry_path_add(0,
8126 &pfx_5_5_5_5_s_32,
8127 FIB_SOURCE_CLI,
8128 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008129 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008130 &nh_10_10_10_1,
8131 tm->hw[0]->sw_if_index,
8132 ~0, // invalid fib index
8133 1,
8134 NULL,
8135 FIB_ROUTE_PATH_FLAG_NONE);
8136 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8137 "%U resolves via drop",
8138 format_fib_prefix, &pfx_5_5_5_5_s_32);
8139
8140 /*
8141 * Add a path via an ADJ that is up
8142 */
8143 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8144 VNET_LINK_IP4,
8145 &nh_10_10_10_2,
8146 tm->hw[0]->sw_if_index);
8147
8148 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8149 .type = FT_LB_ADJ,
8150 .adj = {
8151 .adj = ai_10_10_10_2,
8152 },
8153 };
8154 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8155
8156 fei = fib_table_entry_path_add(0,
8157 &pfx_5_5_5_5_s_32,
8158 FIB_SOURCE_CLI,
8159 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008160 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008161 &nh_10_10_10_2,
8162 tm->hw[0]->sw_if_index,
8163 ~0, // invalid fib index
8164 1,
8165 NULL,
8166 FIB_ROUTE_PATH_FLAG_NONE);
8167
8168 FIB_TEST(fib_test_validate_entry(fei,
8169 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8170 1,
8171 &adj_o_10_10_10_2),
8172 "BFD sourced %U via %U",
8173 format_fib_prefix, &pfx_5_5_5_5_s_32,
8174 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8175
8176 /*
8177 * Bring up the down session - should now LB
8178 */
8179 bfd_10_10_10_1.local_state = BFD_STATE_up;
8180 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8181 FIB_TEST(fib_test_validate_entry(fei,
8182 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8183 2,
8184 &adj_o_10_10_10_1,
8185 &adj_o_10_10_10_2),
8186 "BFD sourced %U via noth adjs",
8187 format_fib_prefix, &pfx_5_5_5_5_s_32);
8188
8189 /*
8190 * remove the BFD session state from the adj
8191 */
8192 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8193
8194 /*
8195 * clean-up
8196 */
8197 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8198 adj_unlock(ai_10_10_10_1);
8199 adj_unlock(ai_10_10_10_2);
8200
8201 /*
8202 * test no-one left behind
8203 */
8204 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8205 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8206 return (0);
8207}
8208
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008209static int
8210lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008211{
8212 const mpls_label_t deag_label = 50;
8213 const u32 lfib_index = 0;
8214 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01008215 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008216 const dpo_id_t *dpo1;
8217 fib_node_index_t lfe;
8218 lookup_dpo_t *lkd;
8219 test_main_t *tm;
8220 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00008221 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008222
8223 tm = &test_main;
8224 lb_count = pool_elts(load_balance_pool);
8225
8226 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8227 adj_nbr_db_size());
8228
8229 /*
8230 * MPLS enable an interface so we get the MPLS table created
8231 */
Neale Ranns2297af02017-09-12 09:45:04 -07008232 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008233 mpls_sw_interface_enable_disable(&mpls_main,
8234 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008235 1, 1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008236
Neale Rannsad422ed2016-11-02 14:20:04 +00008237 ip46_address_t nh_10_10_10_1 = {
8238 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8239 };
8240 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8241 VNET_LINK_MPLS,
8242 &nh_10_10_10_1,
8243 tm->hw[0]->sw_if_index);
8244
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008245 /*
8246 * Test the specials stack properly.
8247 */
8248 fib_prefix_t exp_null_v6_pfx = {
8249 .fp_proto = FIB_PROTOCOL_MPLS,
8250 .fp_eos = MPLS_EOS,
8251 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8252 .fp_payload_proto = DPO_PROTO_IP6,
8253 };
8254 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8255 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8256 "%U/%U present",
8257 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8258 format_mpls_eos_bit, MPLS_EOS);
8259 fib_entry_contribute_forwarding(lfe,
8260 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8261 &dpo);
8262 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8263 lkd = lookup_dpo_get(dpo1->dpoi_index);
8264
8265 FIB_TEST((fib_index == lkd->lkd_fib_index),
8266 "%U/%U is deag in %d %U",
8267 format_mpls_unicast_label, deag_label,
8268 format_mpls_eos_bit, MPLS_EOS,
8269 lkd->lkd_fib_index,
8270 format_dpo_id, &dpo, 0);
8271 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8272 "%U/%U is dst deag",
8273 format_mpls_unicast_label, deag_label,
8274 format_mpls_eos_bit, MPLS_EOS);
8275 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8276 "%U/%U is lookup in interface's table",
8277 format_mpls_unicast_label, deag_label,
8278 format_mpls_eos_bit, MPLS_EOS);
8279 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8280 "%U/%U is %U dst deag",
8281 format_mpls_unicast_label, deag_label,
8282 format_mpls_eos_bit, MPLS_EOS,
8283 format_dpo_proto, lkd->lkd_proto);
8284
8285
8286 /*
8287 * A route deag route for EOS
8288 */
8289 fib_prefix_t pfx = {
8290 .fp_proto = FIB_PROTOCOL_MPLS,
8291 .fp_eos = MPLS_EOS,
8292 .fp_label = deag_label,
8293 .fp_payload_proto = DPO_PROTO_IP4,
8294 };
8295 lfe = fib_table_entry_path_add(lfib_index,
8296 &pfx,
8297 FIB_SOURCE_CLI,
8298 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008299 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008300 &zero_addr,
8301 ~0,
8302 fib_index,
8303 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008304 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008305 FIB_ROUTE_PATH_FLAG_NONE);
8306
8307 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8308 "%U/%U present",
8309 format_mpls_unicast_label, deag_label,
8310 format_mpls_eos_bit, MPLS_EOS);
8311
8312 fib_entry_contribute_forwarding(lfe,
8313 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8314 &dpo);
8315 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8316 lkd = lookup_dpo_get(dpo1->dpoi_index);
8317
8318 FIB_TEST((fib_index == lkd->lkd_fib_index),
8319 "%U/%U is deag in %d %U",
8320 format_mpls_unicast_label, deag_label,
8321 format_mpls_eos_bit, MPLS_EOS,
8322 lkd->lkd_fib_index,
8323 format_dpo_id, &dpo, 0);
8324 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8325 "%U/%U is dst deag",
8326 format_mpls_unicast_label, deag_label,
8327 format_mpls_eos_bit, MPLS_EOS);
8328 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8329 "%U/%U is %U dst deag",
8330 format_mpls_unicast_label, deag_label,
8331 format_mpls_eos_bit, MPLS_EOS,
8332 format_dpo_proto, lkd->lkd_proto);
8333
8334 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8335
8336 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8337 &pfx)),
8338 "%U/%U not present",
8339 format_mpls_unicast_label, deag_label,
8340 format_mpls_eos_bit, MPLS_EOS);
8341
8342 /*
8343 * A route deag route for non-EOS
8344 */
8345 pfx.fp_eos = MPLS_NON_EOS;
8346 lfe = fib_table_entry_path_add(lfib_index,
8347 &pfx,
8348 FIB_SOURCE_CLI,
8349 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008350 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008351 &zero_addr,
8352 ~0,
8353 lfib_index,
8354 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008355 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008356 FIB_ROUTE_PATH_FLAG_NONE);
8357
8358 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8359 "%U/%U present",
8360 format_mpls_unicast_label, deag_label,
8361 format_mpls_eos_bit, MPLS_NON_EOS);
8362
8363 fib_entry_contribute_forwarding(lfe,
8364 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8365 &dpo);
8366 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8367 lkd = lookup_dpo_get(dpo1->dpoi_index);
8368
8369 FIB_TEST((fib_index == lkd->lkd_fib_index),
8370 "%U/%U is deag in %d %U",
8371 format_mpls_unicast_label, deag_label,
8372 format_mpls_eos_bit, MPLS_NON_EOS,
8373 lkd->lkd_fib_index,
8374 format_dpo_id, &dpo, 0);
8375 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8376 "%U/%U is dst deag",
8377 format_mpls_unicast_label, deag_label,
8378 format_mpls_eos_bit, MPLS_NON_EOS);
8379
8380 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8381 "%U/%U is %U dst deag",
8382 format_mpls_unicast_label, deag_label,
8383 format_mpls_eos_bit, MPLS_NON_EOS,
8384 format_dpo_proto, lkd->lkd_proto);
8385
8386 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8387
8388 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8389 &pfx)),
8390 "%U/%U not present",
8391 format_mpls_unicast_label, deag_label,
8392 format_mpls_eos_bit, MPLS_EOS);
8393
Neale Rannsad422ed2016-11-02 14:20:04 +00008394 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008395
Neale Rannsad422ed2016-11-02 14:20:04 +00008396 /*
8397 * An MPLS x-connect
8398 */
8399 fib_prefix_t pfx_1200 = {
8400 .fp_len = 21,
8401 .fp_proto = FIB_PROTOCOL_MPLS,
8402 .fp_label = 1200,
8403 .fp_eos = MPLS_NON_EOS,
8404 };
8405 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8406 .type = FT_LB_LABEL_STACK_O_ADJ,
8407 .label_stack_o_adj = {
8408 .adj = ai_mpls_10_10_10_1,
8409 .label_stack_size = 4,
8410 .label_stack = {
8411 200, 300, 400, 500,
8412 },
8413 .eos = MPLS_NON_EOS,
8414 },
8415 };
8416 dpo_id_t neos_1200 = DPO_INVALID;
8417 dpo_id_t ip_1200 = DPO_INVALID;
8418 mpls_label_t *l200 = NULL;
8419 vec_add1(l200, 200);
8420 vec_add1(l200, 300);
8421 vec_add1(l200, 400);
8422 vec_add1(l200, 500);
8423
8424 lfe = fib_table_entry_update_one_path(fib_index,
8425 &pfx_1200,
8426 FIB_SOURCE_API,
8427 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008428 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00008429 &nh_10_10_10_1,
8430 tm->hw[0]->sw_if_index,
8431 ~0, // invalid fib index
8432 1,
8433 l200,
8434 FIB_ROUTE_PATH_FLAG_NONE);
8435
8436 FIB_TEST(fib_test_validate_entry(lfe,
8437 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8438 1,
8439 &neos_o_10_10_10_1),
8440 "1200/0 LB 1 buckets via: "
8441 "adj 10.10.11.1");
8442
8443 /*
8444 * A recursive route via the MPLS x-connect
8445 */
8446 fib_prefix_t pfx_2_2_2_3_s_32 = {
8447 .fp_len = 32,
8448 .fp_proto = FIB_PROTOCOL_IP4,
8449 .fp_addr = {
8450 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8451 },
8452 };
8453 fib_route_path_t *rpaths = NULL, rpath = {
Neale Rannsda78f952017-05-24 09:15:43 -07008454 .frp_proto = DPO_PROTO_MPLS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008455 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008456 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008457 .frp_sw_if_index = ~0, // recurive
8458 .frp_fib_index = 0, // Default MPLS fib
8459 .frp_weight = 1,
8460 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8461 .frp_label_stack = NULL,
8462 };
8463 vec_add1(rpaths, rpath);
8464
8465 fib_table_entry_path_add2(fib_index,
8466 &pfx_2_2_2_3_s_32,
8467 FIB_SOURCE_API,
8468 FIB_ENTRY_FLAG_NONE,
8469 rpaths);
8470
8471 /*
8472 * A labelled recursive route via the MPLS x-connect
8473 */
8474 fib_prefix_t pfx_2_2_2_4_s_32 = {
8475 .fp_len = 32,
8476 .fp_proto = FIB_PROTOCOL_IP4,
8477 .fp_addr = {
8478 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8479 },
8480 };
8481 mpls_label_t *l999 = NULL;
8482 vec_add1(l999, 999);
8483 rpaths[0].frp_label_stack = l999,
8484
8485 fib_table_entry_path_add2(fib_index,
8486 &pfx_2_2_2_4_s_32,
8487 FIB_SOURCE_API,
8488 FIB_ENTRY_FLAG_NONE,
8489 rpaths);
8490
8491 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8492 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8493 &ip_1200);
8494 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8495 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8496 &neos_1200);
8497
8498 fib_test_lb_bucket_t ip_o_1200 = {
8499 .type = FT_LB_O_LB,
8500 .lb = {
8501 .lb = ip_1200.dpoi_index,
8502 },
8503 };
8504 fib_test_lb_bucket_t mpls_o_1200 = {
8505 .type = FT_LB_LABEL_O_LB,
8506 .label_o_lb = {
8507 .lb = neos_1200.dpoi_index,
8508 .label = 999,
8509 .eos = MPLS_EOS,
8510 },
8511 };
8512
8513 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8514 FIB_TEST(fib_test_validate_entry(lfe,
8515 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8516 1,
8517 &ip_o_1200),
8518 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8519 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8520 FIB_TEST(fib_test_validate_entry(lfe,
8521 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8522 1,
8523 &mpls_o_1200),
8524 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8525
8526 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8527 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8528 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8529
8530 dpo_reset(&neos_1200);
8531 dpo_reset(&ip_1200);
8532
8533 /*
8534 * A recursive via a label that does not exist
8535 */
8536 fib_test_lb_bucket_t bucket_drop = {
Neale Rannsd792d9c2017-10-21 10:53:20 -07008537 .type = FT_LB_DROP,
Neale Rannsad422ed2016-11-02 14:20:04 +00008538 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07008539 .adj = DPO_PROTO_IP4,
8540 },
8541 };
8542 fib_test_lb_bucket_t mpls_bucket_drop = {
Neale Rannsd792d9c2017-10-21 10:53:20 -07008543 .type = FT_LB_DROP,
Neale Rannsf12a83f2017-04-18 09:09:40 -07008544 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00008545 .adj = DPO_PROTO_MPLS,
8546 },
8547 };
8548
8549 rpaths[0].frp_label_stack = NULL;
8550 lfe = fib_table_entry_path_add2(fib_index,
8551 &pfx_2_2_2_4_s_32,
8552 FIB_SOURCE_API,
8553 FIB_ENTRY_FLAG_NONE,
8554 rpaths);
8555
8556 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8557 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8558 &ip_1200);
8559 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8560
8561 FIB_TEST(fib_test_validate_entry(lfe,
8562 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8563 1,
Neale Ranns57b58602017-07-15 07:37:25 -07008564 &bucket_drop),
8565 "2.2.2.2.4/32 LB 1 buckets via: drop");
Neale Rannsad422ed2016-11-02 14:20:04 +00008566 lfe = fib_table_lookup(fib_index, &pfx_1200);
8567 FIB_TEST(fib_test_validate_entry(lfe,
8568 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8569 1,
8570 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07008571 "1200/neos LB 1 buckets via: ip4-DROP");
8572 FIB_TEST(fib_test_validate_entry(lfe,
8573 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8574 1,
8575 &mpls_bucket_drop),
8576 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00008577
8578 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8579
8580 dpo_reset(&ip_1200);
8581
8582 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008583 * An rx-interface route.
8584 * like the tail of an mcast LSP
8585 */
8586 dpo_id_t idpo = DPO_INVALID;
8587
Neale Ranns43161a82017-08-12 02:12:00 -07008588 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008589 tm->hw[0]->sw_if_index,
8590 &idpo);
8591
8592 fib_prefix_t pfx_2500 = {
8593 .fp_len = 21,
8594 .fp_proto = FIB_PROTOCOL_MPLS,
8595 .fp_label = 2500,
8596 .fp_eos = MPLS_EOS,
8597 .fp_payload_proto = DPO_PROTO_IP4,
8598 };
8599 fib_test_lb_bucket_t rx_intf_0 = {
8600 .type = FT_LB_INTF,
8601 .adj = {
8602 .adj = idpo.dpoi_index,
8603 },
8604 };
8605
8606 lfe = fib_table_entry_update_one_path(fib_index,
8607 &pfx_2500,
8608 FIB_SOURCE_API,
8609 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008610 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008611 NULL,
8612 tm->hw[0]->sw_if_index,
8613 ~0, // invalid fib index
8614 0,
8615 NULL,
8616 FIB_ROUTE_PATH_INTF_RX);
8617 FIB_TEST(fib_test_validate_entry(lfe,
8618 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8619 1,
8620 &rx_intf_0),
8621 "2500 rx-interface 0");
8622 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8623
8624 /*
8625 * An MPLS mulicast entry
8626 */
8627 fib_prefix_t pfx_3500 = {
8628 .fp_len = 21,
8629 .fp_proto = FIB_PROTOCOL_MPLS,
8630 .fp_label = 3500,
8631 .fp_eos = MPLS_EOS,
8632 .fp_payload_proto = DPO_PROTO_IP4,
8633 };
8634 fib_test_rep_bucket_t mc_0 = {
8635 .type = FT_REP_LABEL_O_ADJ,
8636 .label_o_adj = {
8637 .adj = ai_mpls_10_10_10_1,
8638 .label = 3300,
8639 .eos = MPLS_EOS,
8640 },
8641 };
8642 fib_test_rep_bucket_t mc_intf_0 = {
8643 .type = FT_REP_INTF,
8644 .adj = {
8645 .adj = idpo.dpoi_index,
8646 },
8647 };
8648 mpls_label_t *l3300 = NULL;
8649 vec_add1(l3300, 3300);
8650
8651 lfe = fib_table_entry_update_one_path(lfib_index,
8652 &pfx_3500,
8653 FIB_SOURCE_API,
8654 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008655 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008656 &nh_10_10_10_1,
8657 tm->hw[0]->sw_if_index,
8658 ~0, // invalid fib index
8659 1,
8660 l3300,
8661 FIB_ROUTE_PATH_FLAG_NONE);
8662 FIB_TEST(fib_test_validate_entry(lfe,
8663 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8664 1,
8665 &mc_0),
8666 "3500 via replicate over 10.10.10.1");
8667
8668 /*
8669 * MPLS Bud-node. Add a replication via an interface-receieve path
8670 */
8671 lfe = fib_table_entry_path_add(lfib_index,
8672 &pfx_3500,
8673 FIB_SOURCE_API,
8674 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008675 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008676 NULL,
8677 tm->hw[0]->sw_if_index,
8678 ~0, // invalid fib index
8679 0,
8680 NULL,
8681 FIB_ROUTE_PATH_INTF_RX);
8682 FIB_TEST(fib_test_validate_entry(lfe,
8683 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8684 2,
8685 &mc_0,
8686 &mc_intf_0),
8687 "3500 via replicate over 10.10.10.1 and interface-rx");
8688
8689 /*
8690 * Add a replication via an interface-free for-us path
8691 */
8692 fib_test_rep_bucket_t mc_disp = {
8693 .type = FT_REP_DISP_MFIB_LOOKUP,
8694 .adj = {
8695 .adj = idpo.dpoi_index,
8696 },
8697 };
8698 lfe = fib_table_entry_path_add(lfib_index,
8699 &pfx_3500,
8700 FIB_SOURCE_API,
8701 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008702 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008703 NULL,
8704 5, // rpf-id
8705 0, // default table
8706 0,
8707 NULL,
8708 FIB_ROUTE_PATH_RPF_ID);
8709 FIB_TEST(fib_test_validate_entry(lfe,
8710 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8711 3,
8712 &mc_0,
8713 &mc_disp,
8714 &mc_intf_0),
8715 "3500 via replicate over 10.10.10.1 and interface-rx");
8716
8717
8718
8719 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8720 dpo_reset(&idpo);
8721
8722 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008723 * cleanup
8724 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008725 mpls_sw_interface_enable_disable(&mpls_main,
8726 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008727 0, 1);
8728 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008729
Neale Rannsad422ed2016-11-02 14:20:04 +00008730 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008731 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008732 lb_count, pool_elts(load_balance_pool));
Neale Ranns43161a82017-08-12 02:12:00 -07008733 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
8734 "interface_rx_dpo resources freed %d of %d",
8735 0, pool_elts(interface_rx_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008736
8737 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008738}
8739
8740static clib_error_t *
8741fib_test (vlib_main_t * vm,
8742 unformat_input_t * input,
8743 vlib_cli_command_t * cmd_arg)
8744{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008745 int res;
8746
8747 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008748 fib_test_mk_intf(4);
8749
Neale Ranns88fc83e2017-04-05 08:11:14 -07008750 if (unformat (input, "debug"))
8751 {
8752 fib_test_do_debug = 1;
8753 }
8754
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008755 if (unformat (input, "ip"))
8756 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008757 res += fib_test_v4();
8758 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008759 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008760 else if (unformat (input, "label"))
8761 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008762 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008763 }
8764 else if (unformat (input, "ae"))
8765 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008766 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008767 }
Neale Ranns57b58602017-07-15 07:37:25 -07008768 else if (unformat (input, "pref"))
8769 {
8770 res += fib_test_pref();
8771 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008772 else if (unformat (input, "lfib"))
8773 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008774 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008775 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008776 else if (unformat (input, "walk"))
8777 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008778 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008779 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008780 else if (unformat (input, "bfd"))
8781 {
8782 res += fib_test_bfd();
8783 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008784 else
8785 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008786 res += fib_test_v4();
8787 res += fib_test_v6();
8788 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008789 res += fib_test_bfd();
Neale Ranns57b58602017-07-15 07:37:25 -07008790 res += fib_test_pref();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008791 res += fib_test_label();
8792 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008793
8794 /*
8795 * fib-walk process must be disabled in order for the walk tests to work
8796 */
8797 fib_walk_process_disable();
8798 res += fib_test_walk();
8799 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008800 }
8801
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008802 if (res)
8803 {
8804 return clib_error_return(0, "FIB Unit Test Failed");
8805 }
8806 else
8807 {
8808 return (NULL);
8809 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008810}
8811
8812VLIB_CLI_COMMAND (test_fib_command, static) = {
8813 .path = "test fib",
8814 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8815 .function = fib_test,
8816};
8817
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008818clib_error_t *
8819fib_test_init (vlib_main_t *vm)
8820{
8821 return 0;
8822}
8823
8824VLIB_INIT_FUNCTION (fib_test_init);