blob: 66a38236216de558ba8a2453edd18e7c9bf5a750 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/fib/ip6_fib.h>
17#include <vnet/fib/ip4_fib.h>
18#include <vnet/fib/mpls_fib.h>
19#include <vnet/adj/adj.h>
20#include <vnet/dpo/load_balance.h>
21#include <vnet/dpo/load_balance_map.h>
22#include <vnet/dpo/mpls_label_dpo.h>
23#include <vnet/dpo/lookup_dpo.h>
24#include <vnet/dpo/drop_dpo.h>
25#include <vnet/dpo/receive_dpo.h>
Neale Ranns948e00f2016-10-20 13:39:34 +010026#include <vnet/dpo/ip_null_dpo.h>
Neale Ranns88fc83e2017-04-05 08:11:14 -070027#include <vnet/bfd/bfd_main.h>
Neale Ranns43161a82017-08-12 02:12:00 -070028#include <vnet/dpo/interface_rx_dpo.h>
Neale Ranns0f26c5a2017-03-01 15:12:11 -080029#include <vnet/dpo/replicate_dpo.h>
Neale Ranns6f631152017-10-03 08:20:21 -070030#include <vnet/dpo/l2_bridge_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010031
32#include <vnet/mpls/mpls.h>
33
Neale Ranns6f631152017-10-03 08:20:21 -070034#include <vnet/fib/fib_test.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010035#include <vnet/fib/fib_path_list.h>
Neale Rannsad422ed2016-11-02 14:20:04 +000036#include <vnet/fib/fib_entry_src.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010037#include <vnet/fib/fib_walk.h>
38#include <vnet/fib/fib_node_list.h>
Neale Ranns3ee44042016-10-03 13:05:48 +010039#include <vnet/fib/fib_urpf_list.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010040
Neale Ranns88fc83e2017-04-05 08:11:14 -070041/*
42 * Add debugs for passing tests
43 */
44static int fib_test_do_debug;
45
Neale Ranns0bfe5d82016-08-25 15:29:12 +010046#define FIB_TEST_I(_cond, _comment, _args...) \
47({ \
48 int _evald = (_cond); \
49 if (!(_evald)) { \
50 fformat(stderr, "FAIL:%d: " _comment "\n", \
51 __LINE__, ##_args); \
52 } else { \
Neale Ranns88fc83e2017-04-05 08:11:14 -070053 if (fib_test_do_debug) \
54 fformat(stderr, "PASS:%d: " _comment "\n", \
55 __LINE__, ##_args); \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010056 } \
57 _evald; \
58})
59#define FIB_TEST(_cond, _comment, _args...) \
60{ \
61 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
Neale Ranns0ebe8d72016-12-08 19:48:11 +000062 return 1; \
Neale Ranns0bfe5d82016-08-25 15:29:12 +010063 ASSERT(!("FAIL: " _comment)); \
64 } \
65}
66
67/**
68 * A 'i'm not fussed is this is not efficient' store of test data
69 */
70typedef struct test_main_t_ {
71 /**
72 * HW if indicies
73 */
74 u32 hw_if_indicies[4];
75 /**
76 * HW interfaces
77 */
78 vnet_hw_interface_t * hw[4];
79
80} test_main_t;
81static test_main_t test_main;
82
83/* fake ethernet device class, distinct from "fake-ethX" */
84static u8 * format_test_interface_name (u8 * s, va_list * args)
85{
86 u32 dev_instance = va_arg (*args, u32);
87 return format (s, "test-eth%d", dev_instance);
88}
89
90static uword dummy_interface_tx (vlib_main_t * vm,
91 vlib_node_runtime_t * node,
92 vlib_frame_t * frame)
93{
94 clib_warning ("you shouldn't be here, leaking buffers...");
95 return frame->n_vectors;
96}
97
Neale Ranns8b37b872016-11-21 12:25:22 +000098static clib_error_t *
99test_interface_admin_up_down (vnet_main_t * vnm,
100 u32 hw_if_index,
101 u32 flags)
102{
103 u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
104 VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
105 vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
106 return 0;
107}
108
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100109VNET_DEVICE_CLASS (test_interface_device_class,static) = {
110 .name = "Test interface",
111 .format_device_name = format_test_interface_name,
112 .tx_function = dummy_interface_tx,
Neale Ranns8b37b872016-11-21 12:25:22 +0000113 .admin_up_down_function = test_interface_admin_up_down,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100114};
115
116static u8 *hw_address;
117
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000118static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100119fib_test_mk_intf (u32 ninterfaces)
120{
121 clib_error_t * error = NULL;
122 test_main_t *tm = &test_main;
123 u8 byte;
124 u32 i;
125
126 ASSERT(ninterfaces <= ARRAY_LEN(tm->hw_if_indicies));
127
128 for (i=0; i<6; i++)
129 {
130 byte = 0xd0+i;
131 vec_add1(hw_address, byte);
132 }
133
134 for (i = 0; i < ninterfaces; i++)
135 {
136 hw_address[5] = i;
137
138 error = ethernet_register_interface(vnet_get_main(),
Neale Ranns8b37b872016-11-21 12:25:22 +0000139 test_interface_device_class.index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100140 i /* instance */,
141 hw_address,
142 &tm->hw_if_indicies[i],
143 /* flag change */ 0);
144
145 FIB_TEST((NULL == error), "ADD interface %d", i);
146
Neale Ranns8b37b872016-11-21 12:25:22 +0000147 error = vnet_hw_interface_set_flags(vnet_get_main(),
148 tm->hw_if_indicies[i],
149 VNET_HW_INTERFACE_FLAG_LINK_UP);
150 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100151 tm->hw_if_indicies[i]);
Neale Ranns8b37b872016-11-21 12:25:22 +0000152 vec_validate (ip4_main.fib_index_by_sw_if_index,
153 tm->hw[i]->sw_if_index);
154 vec_validate (ip6_main.fib_index_by_sw_if_index,
155 tm->hw[i]->sw_if_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100156 ip4_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
157 ip6_main.fib_index_by_sw_if_index[tm->hw[i]->sw_if_index] = 0;
Neale Ranns8b37b872016-11-21 12:25:22 +0000158
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100159 error = vnet_sw_interface_set_flags(vnet_get_main(),
160 tm->hw[i]->sw_if_index,
161 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
162 FIB_TEST((NULL == error), "UP interface %d", i);
163 }
164 /*
165 * re-eval after the inevitable realloc
166 */
167 for (i = 0; i < ninterfaces; i++)
168 {
169 tm->hw[i] = vnet_get_hw_interface(vnet_get_main(),
170 tm->hw_if_indicies[i]);
171 }
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000172
173 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100174}
175
Neale Ranns3ee44042016-10-03 13:05:48 +0100176#define FIB_TEST_REC_FORW(_rec_prefix, _via_prefix, _bucket) \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100177{ \
178 const dpo_id_t *_rec_dpo = fib_entry_contribute_ip_forwarding( \
179 fib_table_lookup_exact_match(fib_index, (_rec_prefix))); \
180 const dpo_id_t *_via_dpo = fib_entry_contribute_ip_forwarding( \
181 fib_table_lookup(fib_index, (_via_prefix))); \
182 FIB_TEST(!dpo_cmp(_via_dpo, \
Neale Ranns3ee44042016-10-03 13:05:48 +0100183 load_balance_get_bucket(_rec_dpo->dpoi_index, \
184 _bucket)), \
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100185 "%U is recursive via %U", \
186 format_fib_prefix, (_rec_prefix), \
187 format_fib_prefix, _via_prefix); \
188}
189
190#define FIB_TEST_LB_BUCKET_VIA_ADJ(_prefix, _bucket, _ai) \
191{ \
192 const dpo_id_t *_dpo = fib_entry_contribute_ip_forwarding( \
193 fib_table_lookup_exact_match(fib_index, (_prefix))); \
194 const dpo_id_t *_dpo1 = \
195 load_balance_get_bucket(_dpo->dpoi_index, _bucket); \
196 FIB_TEST(DPO_ADJACENCY == _dpo1->dpoi_type, "type is %U", \
197 format_dpo_type, _dpo1->dpoi_type); \
198 FIB_TEST((_ai == _dpo1->dpoi_index), \
199 "%U bucket %d resolves via %U", \
200 format_fib_prefix, (_prefix), \
201 _bucket, \
202 format_dpo_id, _dpo1, 0); \
203}
204
Neale Ranns3ee44042016-10-03 13:05:48 +0100205#define FIB_TEST_RPF(_cond, _comment, _args...) \
206{ \
207 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
208 return (0); \
209 } \
210}
211
212static int
213fib_test_urpf_is_equal (fib_node_index_t fei,
214 fib_forward_chain_type_t fct,
215 u32 num, ...)
216{
Neale Ranns948e00f2016-10-20 13:39:34 +0100217 dpo_id_t dpo = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +0100218 fib_urpf_list_t *urpf;
219 index_t ui;
220 va_list ap;
221 int ii;
222
223 va_start(ap, num);
224
225 fib_entry_contribute_forwarding(fei, fct, &dpo);
226 ui = load_balance_get_urpf(dpo.dpoi_index);
227
228 urpf = fib_urpf_list_get(ui);
229
230 FIB_TEST_RPF(num == vec_len(urpf->furpf_itfs),
231 "RPF:%U len %d == %d",
232 format_fib_urpf_list, ui,
233 num, vec_len(urpf->furpf_itfs));
234 FIB_TEST_RPF(num == fib_urpf_check_size(ui),
235 "RPF:%U check-size %d == %d",
236 format_fib_urpf_list, ui,
237 num, vec_len(urpf->furpf_itfs));
238
239 for (ii = 0; ii < num; ii++)
240 {
241 adj_index_t ai = va_arg(ap, adj_index_t);
242
243 FIB_TEST_RPF(ai == urpf->furpf_itfs[ii],
244 "RPF:%d item:%d - %d == %d",
245 ui, ii, ai, urpf->furpf_itfs[ii]);
246 FIB_TEST_RPF(fib_urpf_check(ui, ai),
247 "RPF:%d %d found",
248 ui, ai);
249 }
250
251 dpo_reset(&dpo);
252
Neale Ranns5899fde2016-10-12 13:51:05 +0100253 va_end(ap);
254
Neale Ranns3ee44042016-10-03 13:05:48 +0100255 return (1);
256}
257
Neale Rannsb80c5362016-10-08 13:03:40 +0100258static u8*
259fib_test_build_rewrite (u8 *eth_addr)
260{
261 u8* rewrite = NULL;
262
263 vec_validate(rewrite, 13);
264
265 memcpy(rewrite, eth_addr, 6);
266 memcpy(rewrite+6, eth_addr, 6);
267
268 return (rewrite);
269}
270
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000271#define FIB_TEST_LB(_cond, _comment, _args...) \
272{ \
273 if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
274 return (0); \
275 } \
276}
277
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800278int
279fib_test_validate_rep_v (const replicate_t *rep,
280 u16 n_buckets,
Christophe Fontained3c008d2017-10-02 18:10:54 +0200281 va_list *ap)
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800282{
283 const fib_test_rep_bucket_t *exp;
284 const dpo_id_t *dpo;
285 int bucket;
286
287 FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
288 "n_buckets = %d", rep->rep_n_buckets);
289
290 for (bucket = 0; bucket < n_buckets; bucket++)
291 {
Christophe Fontained3c008d2017-10-02 18:10:54 +0200292 exp = va_arg(*ap, fib_test_rep_bucket_t*);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800293
294 dpo = replicate_get_bucket_i(rep, bucket);
295
296 switch (exp->type)
297 {
298 case FT_REP_LABEL_O_ADJ:
299 {
300 const mpls_label_dpo_t *mld;
301 mpls_label_t hdr;
302 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
303 "bucket %d stacks on %U",
304 bucket,
305 format_dpo_type, dpo->dpoi_type);
306
307 mld = mpls_label_dpo_get(dpo->dpoi_index);
308 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
309
310 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
311 exp->label_o_adj.label),
312 "bucket %d stacks on label %d",
313 bucket,
314 exp->label_o_adj.label);
315
316 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
317 exp->label_o_adj.eos),
318 "bucket %d stacks on label %d %U",
319 bucket,
320 exp->label_o_adj.label,
321 format_mpls_eos_bit, exp->label_o_adj.eos);
322
323 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
324 "bucket %d label stacks on %U",
325 bucket,
326 format_dpo_type, mld->mld_dpo.dpoi_type);
327
328 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
329 "bucket %d label stacks on adj %d",
330 bucket,
331 exp->label_o_adj.adj);
332 }
333 break;
334 case FT_REP_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700335 FIB_TEST_LB((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800336 "bucket %d stacks on %U",
337 bucket,
338 format_dpo_type, dpo->dpoi_type);
339
340 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
341 "bucket %d stacks on adj %d",
342 bucket,
343 exp->adj.adj);
344 break;
345 case FT_REP_DISP_MFIB_LOOKUP:
346// ASSERT(0);
347 break;
348 }
349 }
350
351 return (!0);
352}
353
354int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000355fib_test_validate_lb_v (const load_balance_t *lb,
356 u16 n_buckets,
Christophe Fontained3c008d2017-10-02 18:10:54 +0200357 va_list *ap)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000358{
359 const dpo_id_t *dpo;
360 int bucket;
361
362 FIB_TEST_LB((n_buckets == lb->lb_n_buckets), "n_buckets = %d", lb->lb_n_buckets);
363
364 for (bucket = 0; bucket < n_buckets; bucket++)
365 {
366 const fib_test_lb_bucket_t *exp;
367
Christophe Fontained3c008d2017-10-02 18:10:54 +0200368 exp = va_arg(*ap, fib_test_lb_bucket_t*);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000369 dpo = load_balance_get_bucket_i(lb, bucket);
370
371 switch (exp->type)
372 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000373 case FT_LB_LABEL_STACK_O_ADJ:
374 {
375 const mpls_label_dpo_t *mld;
376 mpls_label_t hdr;
377 u32 ii;
378
379 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
380 "bucket %d stacks on %U",
381 bucket,
382 format_dpo_type, dpo->dpoi_type);
383
384 mld = mpls_label_dpo_get(dpo->dpoi_index);
385
386 FIB_TEST_LB(exp->label_stack_o_adj.label_stack_size == mld->mld_n_labels,
387 "label stack size",
388 mld->mld_n_labels);
389
390 for (ii = 0; ii < mld->mld_n_labels; ii++)
391 {
392 hdr = clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
393 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
394 exp->label_stack_o_adj.label_stack[ii]),
395 "bucket %d stacks on label %d",
396 bucket,
397 exp->label_stack_o_adj.label_stack[ii]);
398
399 if (ii == mld->mld_n_labels-1)
400 {
401 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
402 exp->label_o_adj.eos),
403 "bucket %d stacks on label %d %U!=%U",
404 bucket,
405 exp->label_stack_o_adj.label_stack[ii],
406 format_mpls_eos_bit, exp->label_o_adj.eos,
407 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
408 }
409 else
410 {
411 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) == MPLS_NON_EOS),
412 "bucket %d stacks on label %d %U",
413 bucket,
414 exp->label_stack_o_adj.label_stack[ii],
415 format_mpls_eos_bit, vnet_mpls_uc_get_s(hdr));
416 }
417 }
418
419 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
420 "bucket %d label stacks on %U",
421 bucket,
422 format_dpo_type, mld->mld_dpo.dpoi_type);
423
424 FIB_TEST_LB((exp->label_stack_o_adj.adj == mld->mld_dpo.dpoi_index),
425 "bucket %d label stacks on adj %d",
426 bucket,
427 exp->label_stack_o_adj.adj);
428 }
429 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000430 case FT_LB_LABEL_O_ADJ:
431 {
432 const mpls_label_dpo_t *mld;
433 mpls_label_t hdr;
434 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
435 "bucket %d stacks on %U",
436 bucket,
437 format_dpo_type, dpo->dpoi_type);
438
439 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000440 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000441
442 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
443 exp->label_o_adj.label),
444 "bucket %d stacks on label %d",
445 bucket,
446 exp->label_o_adj.label);
447
448 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
449 exp->label_o_adj.eos),
450 "bucket %d stacks on label %d %U",
451 bucket,
452 exp->label_o_adj.label,
453 format_mpls_eos_bit, exp->label_o_adj.eos);
454
455 FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
456 "bucket %d label stacks on %U",
457 bucket,
458 format_dpo_type, mld->mld_dpo.dpoi_type);
459
460 FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
461 "bucket %d label stacks on adj %d",
462 bucket,
463 exp->label_o_adj.adj);
464 }
465 break;
466 case FT_LB_LABEL_O_LB:
467 {
468 const mpls_label_dpo_t *mld;
469 mpls_label_t hdr;
470
471 FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
472 "bucket %d stacks on %U",
473 bucket,
474 format_dpo_type, dpo->dpoi_type);
Neale Rannsad422ed2016-11-02 14:20:04 +0000475
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000476 mld = mpls_label_dpo_get(dpo->dpoi_index);
Neale Rannsad422ed2016-11-02 14:20:04 +0000477 hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000478
Neale Rannsad422ed2016-11-02 14:20:04 +0000479 FIB_TEST_LB(1 == mld->mld_n_labels, "label stack size",
480 mld->mld_n_labels);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000481 FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
482 exp->label_o_lb.label),
483 "bucket %d stacks on label %d",
484 bucket,
485 exp->label_o_lb.label);
486
487 FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
488 exp->label_o_lb.eos),
489 "bucket %d stacks on label %d %U",
490 bucket,
491 exp->label_o_lb.label,
492 format_mpls_eos_bit, exp->label_o_lb.eos);
493
494 FIB_TEST_LB((DPO_LOAD_BALANCE == mld->mld_dpo.dpoi_type),
495 "bucket %d label stacks on %U",
496 bucket,
497 format_dpo_type, mld->mld_dpo.dpoi_type);
498
499 FIB_TEST_LB((exp->label_o_lb.lb == mld->mld_dpo.dpoi_index),
500 "bucket %d label stacks on LB %d",
501 bucket,
502 exp->label_o_lb.lb);
503 }
504 break;
505 case FT_LB_ADJ:
506 FIB_TEST_I(((DPO_ADJACENCY == dpo->dpoi_type) ||
507 (DPO_ADJACENCY_INCOMPLETE == dpo->dpoi_type)),
508 "bucket %d stacks on %U",
509 bucket,
510 format_dpo_type, dpo->dpoi_type);
511 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
512 "bucket %d stacks on adj %d",
513 bucket,
514 exp->adj.adj);
515 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800516 case FT_LB_INTF:
Neale Ranns43161a82017-08-12 02:12:00 -0700517 FIB_TEST_I((DPO_INTERFACE_RX == dpo->dpoi_type),
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800518 "bucket %d stacks on %U",
519 bucket,
520 format_dpo_type, dpo->dpoi_type);
521 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
522 "bucket %d stacks on adj %d",
523 bucket,
524 exp->adj.adj);
525 break;
Neale Ranns6f631152017-10-03 08:20:21 -0700526 case FT_LB_L2:
527 FIB_TEST_I((DPO_L2_BRIDGE == dpo->dpoi_type),
528 "bucket %d stacks on %U",
529 bucket,
530 format_dpo_type, dpo->dpoi_type);
531 FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
532 "bucket %d stacks on adj %d",
533 bucket,
534 exp->adj.adj);
535 break;
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000536 case FT_LB_O_LB:
537 FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
538 "bucket %d stacks on %U",
539 bucket,
540 format_dpo_type, dpo->dpoi_type);
541 FIB_TEST_LB((exp->lb.lb == dpo->dpoi_index),
Neale Ranns57b58602017-07-15 07:37:25 -0700542 "bucket %d stacks on lb %d not %d",
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000543 bucket,
Neale Ranns57b58602017-07-15 07:37:25 -0700544 dpo->dpoi_index,
545 exp->lb.lb);
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000546 break;
547 case FT_LB_SPECIAL:
548 FIB_TEST_I((DPO_DROP == dpo->dpoi_type),
549 "bucket %d stacks on %U",
550 bucket,
551 format_dpo_type, dpo->dpoi_type);
552 FIB_TEST_LB((exp->special.adj == dpo->dpoi_index),
553 "bucket %d stacks on drop %d",
554 bucket,
555 exp->special.adj);
556 break;
557 }
558 }
559 return (!0);
560}
561
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800562int
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000563fib_test_validate_entry (fib_node_index_t fei,
564 fib_forward_chain_type_t fct,
Gabriel Ganned71e0fc2017-10-26 10:35:28 +0200565 int n_buckets,
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000566 ...)
567{
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000568 dpo_id_t dpo = DPO_INVALID;
569 fib_prefix_t pfx;
570 index_t fw_lbi;
571 u32 fib_index;
572 va_list ap;
573 int res;
574
575 va_start(ap, n_buckets);
576
577 fib_entry_get_prefix(fei, &pfx);
578 fib_index = fib_entry_get_fib_index(fei);
579 fib_entry_contribute_forwarding(fei, fct, &dpo);
580
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800581 if (DPO_REPLICATE == dpo.dpoi_type)
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000582 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800583 const replicate_t *rep;
584
585 rep = replicate_get(dpo.dpoi_index);
Christophe Fontained3c008d2017-10-02 18:10:54 +0200586 res = fib_test_validate_rep_v(rep, n_buckets, &ap);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800587 }
588 else
589 {
590 const load_balance_t *lb;
591
592 FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
593 "Entry links to %U",
594 format_dpo_type, dpo.dpoi_type);
595
596 lb = load_balance_get(dpo.dpoi_index);
Christophe Fontained3c008d2017-10-02 18:10:54 +0200597 res = fib_test_validate_lb_v(lb, n_buckets, &ap);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800598
599 /*
600 * ensure that the LB contributed by the entry is the
601 * same as the LB in the forwarding tables
602 */
603 if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
Neale Rannsad422ed2016-11-02 14:20:04 +0000604 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800605 switch (pfx.fp_proto)
Neale Rannsad422ed2016-11-02 14:20:04 +0000606 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800607 case FIB_PROTOCOL_IP4:
608 fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
Neale Rannsad422ed2016-11-02 14:20:04 +0000609 break;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800610 case FIB_PROTOCOL_IP6:
611 fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
612 break;
613 case FIB_PROTOCOL_MPLS:
614 {
615 mpls_unicast_header_t hdr = {
616 .label_exp_s_ttl = 0,
617 };
618
619 vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
620 vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
621 hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
622
623 fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
624 break;
625 }
626 default:
627 fw_lbi = 0;
Neale Rannsad422ed2016-11-02 14:20:04 +0000628 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800629 FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
630 "Contributed LB = FW LB: %U\n %U",
631 format_load_balance, fw_lbi, 0,
632 format_load_balance, dpo.dpoi_index, 0);
Neale Rannsad422ed2016-11-02 14:20:04 +0000633 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000634 }
Neale Ranns0bd36ea2016-11-16 11:47:44 +0000635
636 dpo_reset(&dpo);
637
638 va_end(ap);
639
640 return (res);
641}
642
Neale Ranns0ebe8d72016-12-08 19:48:11 +0000643static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100644fib_test_v4 (void)
645{
646 /*
647 * In the default table check for the presence and correct forwarding
648 * of the special entries
649 */
650 fib_node_index_t dfrt, fei, ai, ai2, locked_ai, ai_01, ai_02, ai_03;
651 const dpo_id_t *dpo, *dpo1, *dpo2, *dpo_drop;
652 const ip_adjacency_t *adj;
653 const load_balance_t *lb;
654 test_main_t *tm;
655 u32 fib_index;
Neale Ranns994dab42017-04-18 12:56:45 -0700656 int lb_count;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100657 int ii;
658
659 /* via 10.10.10.1 */
660 ip46_address_t nh_10_10_10_1 = {
661 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
662 };
663 /* via 10.10.10.2 */
664 ip46_address_t nh_10_10_10_2 = {
665 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
666 };
667
Neale Rannsf12a83f2017-04-18 09:09:40 -0700668 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
669 pool_elts(load_balance_map_pool));
670
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100671 tm = &test_main;
672
Neale Ranns994dab42017-04-18 12:56:45 -0700673 /* record the nubmer of load-balances in use before we start */
674 lb_count = pool_elts(load_balance_pool);
675
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100676 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -0700677 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
678 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100679
680 for (ii = 0; ii < 4; ii++)
681 {
682 ip4_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
683 }
684
685 fib_prefix_t pfx_0_0_0_0_s_0 = {
686 .fp_len = 0,
687 .fp_proto = FIB_PROTOCOL_IP4,
688 .fp_addr = {
689 .ip4 = {
690 {0}
691 },
692 },
693 };
694
695 fib_prefix_t pfx = {
696 .fp_len = 0,
697 .fp_proto = FIB_PROTOCOL_IP4,
698 .fp_addr = {
699 .ip4 = {
700 {0}
701 },
702 },
703 };
704
705 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
706
707 dfrt = fib_table_lookup(fib_index, &pfx_0_0_0_0_s_0);
708 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
709 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
710 "Default route is DROP");
711
712 pfx.fp_len = 32;
713 fei = fib_table_lookup(fib_index, &pfx);
714 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all zeros route present");
715 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
716 "all 0s route is DROP");
717
718 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xffffffff);
719 pfx.fp_len = 32;
720 fei = fib_table_lookup(fib_index, &pfx);
721 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all ones route present");
722 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
723 "all 1s route is DROP");
724
725 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xe0000000);
726 pfx.fp_len = 8;
727 fei = fib_table_lookup(fib_index, &pfx);
728 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "all-mcast route present");
729 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
730 "all-mcast route is DROP");
731
732 pfx.fp_addr.ip4.as_u32 = clib_host_to_net_u32(0xf0000000);
733 pfx.fp_len = 8;
734 fei = fib_table_lookup(fib_index, &pfx);
735 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "class-e route present");
736 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
737 "class-e route is DROP");
738
739 /*
740 * at this stage there are 5 entries in the test FIB (plus 5 in the default),
741 * all of which are special sourced and so none of which share path-lists.
Neale Ranns32e1c012016-11-22 17:07:28 +0000742 * There are also 2 entries, and 2 non-shared path-lists, in the v6 default
743 * table, and 4 path-lists in the v6 MFIB table
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100744 */
Neale Ranns32e1c012016-11-22 17:07:28 +0000745#define ENBR (5+5+2)
746#define PNBR (5+5+6)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100747 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000748 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100749 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000750 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100751 fib_entry_pool_size());
752
753 /*
754 * add interface routes.
755 * validate presence of /24 attached and /32 recieve.
756 * test for the presence of the receive address in the glean and local adj
757 */
758 fib_prefix_t local_pfx = {
759 .fp_len = 24,
760 .fp_proto = FIB_PROTOCOL_IP4,
761 .fp_addr = {
762 .ip4 = {
763 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
764 },
765 },
766 };
767
768 fib_table_entry_update_one_path(fib_index, &local_pfx,
769 FIB_SOURCE_INTERFACE,
770 (FIB_ENTRY_FLAG_CONNECTED |
771 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -0700772 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100773 NULL,
774 tm->hw[0]->sw_if_index,
775 ~0, // invalid fib index
776 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000777 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100778 FIB_ROUTE_PATH_FLAG_NONE);
779 fei = fib_table_lookup(fib_index, &local_pfx);
780 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
781 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
782 fib_entry_get_flags(fei)),
783 "Flags set on attached interface");
784
785 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -0700786 FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
787 "attached interface route adj present %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100788 adj = adj_get(ai);
789 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
790 "attached interface adj is glean");
791 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
792 &adj->sub_type.glean.receive_addr)),
793 "attached interface adj is receive ok");
794
795 local_pfx.fp_len = 32;
796 fib_table_entry_update_one_path(fib_index, &local_pfx,
797 FIB_SOURCE_INTERFACE,
798 (FIB_ENTRY_FLAG_CONNECTED |
799 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -0700800 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100801 NULL,
802 tm->hw[0]->sw_if_index,
803 ~0, // invalid fib index
804 1, // weight
Neale Rannsad422ed2016-11-02 14:20:04 +0000805 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100806 FIB_ROUTE_PATH_FLAG_NONE);
807 fei = fib_table_lookup(fib_index, &local_pfx);
808 FIB_TEST(((FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_CONNECTED) ==
809 fib_entry_get_flags(fei)),
810 "Flags set on local interface");
811
812 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
813
814 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +0100815 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
816 "RPF list for local length 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100817 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
818 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
819 "local interface adj is local");
820 receive_dpo_t *rd = receive_dpo_get(dpo->dpoi_index);
821
822 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
823 &rd->rd_addr)),
824 "local interface adj is receive ok");
825
826 FIB_TEST((2 == fib_table_get_num_entries(fib_index,
827 FIB_PROTOCOL_IP4,
828 FIB_SOURCE_INTERFACE)),
829 "2 Interface Source'd prefixes");
830
831 /*
832 * +2 interface routes +2 non-shared path-lists
833 */
834 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000835 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100836 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000837 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100838 fib_entry_pool_size());
839
840 /*
841 * Modify the default route to be via an adj not yet known.
842 * this sources the defalut route with the API source, which is
843 * a higher preference to the DEFAULT_ROUTE source
844 */
845 pfx.fp_addr.ip4.as_u32 = 0;
846 pfx.fp_len = 0;
847 fib_table_entry_path_add(fib_index, &pfx,
848 FIB_SOURCE_API,
849 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -0700850 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100851 &nh_10_10_10_1,
852 tm->hw[0]->sw_if_index,
853 ~0, // invalid fib index
854 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000855 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100856 FIB_ROUTE_PATH_FLAG_NONE);
857 fei = fib_table_lookup(fib_index, &pfx);
858 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
859 "Flags set on API route");
860
861 FIB_TEST((fei == dfrt), "default route same index");
862 ai = fib_entry_get_adj(fei);
863 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
864 adj = adj_get(ai);
865 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
866 "adj is incomplete");
867 FIB_TEST((0 == ip46_address_cmp(&nh_10_10_10_1, &adj->sub_type.nbr.next_hop)),
868 "adj nbr next-hop ok");
869 FIB_TEST((1 == fib_table_get_num_entries(fib_index,
870 FIB_PROTOCOL_IP4,
871 FIB_SOURCE_API)),
872 "1 API Source'd prefixes");
873
874 /*
875 * find the adj in the shared db
876 */
877 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100878 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100879 &nh_10_10_10_1,
880 tm->hw[0]->sw_if_index);
881 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
882 adj_unlock(locked_ai);
883
884 /*
885 * +1 shared path-list
886 */
887 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
888 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000889 FIB_TEST((PNBR+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100890 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000891 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100892 fib_entry_pool_size());
893
894 /*
895 * remove the API source from the default route. We expected
896 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
897 */
898 pfx.fp_addr.ip4.as_u32 = 0;
899 pfx.fp_len = 0;
900 fib_table_entry_path_remove(fib_index, &pfx,
901 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -0700902 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100903 &nh_10_10_10_1,
904 tm->hw[0]->sw_if_index,
905 ~0, // non-recursive path, so no FIB index
906 1,
907 FIB_ROUTE_PATH_FLAG_NONE);
908
909 fei = fib_table_lookup(fib_index, &pfx);
910
911 FIB_TEST((fei == dfrt), "default route same index");
912 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
913 "Default route is DROP");
914
915 /*
916 * -1 shared-path-list
917 */
918 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +0000919 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100920 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +0000921 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100922 fib_entry_pool_size());
923
924 /*
925 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
926 */
927 fib_prefix_t pfx_10_10_10_1_s_32 = {
928 .fp_len = 32,
929 .fp_proto = FIB_PROTOCOL_IP4,
930 .fp_addr = {
931 /* 10.10.10.1 */
932 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
933 },
934 };
935 fib_prefix_t pfx_10_10_10_2_s_32 = {
936 .fp_len = 32,
937 .fp_proto = FIB_PROTOCOL_IP4,
938 .fp_addr = {
939 /* 10.10.10.2 */
940 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
941 },
942 };
943 fib_prefix_t pfx_11_11_11_11_s_32 = {
944 .fp_len = 32,
945 .fp_proto = FIB_PROTOCOL_IP4,
946 .fp_addr = {
947 /* 11.11.11.11 */
948 .ip4.as_u32 = clib_host_to_net_u32(0x0b0b0b0b),
949 },
950 };
951 u8 eth_addr[] = {
952 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
953 };
Neale Rannsb80c5362016-10-08 13:03:40 +0100954
Neale Ranns3ee44042016-10-03 13:05:48 +0100955 ip46_address_t nh_12_12_12_12 = {
956 .ip4.as_u32 = clib_host_to_net_u32(0x0c0c0c0c),
957 };
958 adj_index_t ai_12_12_12_12;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100959
960 /*
961 * Add a route via an incomplete ADJ. then complete the ADJ
962 * Expect the route LB is updated to use complete adj type.
963 */
964 fei = fib_table_entry_update_one_path(fib_index,
965 &pfx_11_11_11_11_s_32,
966 FIB_SOURCE_API,
967 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -0700968 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100969 &pfx_10_10_10_1_s_32.fp_addr,
970 tm->hw[0]->sw_if_index,
971 ~0, // invalid fib index
972 1,
Neale Rannsad422ed2016-11-02 14:20:04 +0000973 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100974 FIB_ROUTE_PATH_FLAG_NONE);
975
976 dpo = fib_entry_contribute_ip_forwarding(fei);
977 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
978 FIB_TEST(DPO_ADJACENCY_INCOMPLETE == dpo1->dpoi_type,
979 "11.11.11.11/32 via incomplete adj");
980
981 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +0100982 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100983 &pfx_10_10_10_1_s_32.fp_addr,
984 tm->hw[0]->sw_if_index);
985 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
986 adj = adj_get(ai_01);
987 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
988 "adj is incomplete");
989 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
990 &adj->sub_type.nbr.next_hop)),
991 "adj nbr next-hop ok");
992
Neale Rannsb80c5362016-10-08 13:03:40 +0100993 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
994 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100995 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
996 "adj is complete");
997 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_1_s_32.fp_addr,
998 &adj->sub_type.nbr.next_hop)),
999 "adj nbr next-hop ok");
1000 ai = fib_entry_get_adj(fei);
1001 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
1002
1003 dpo = fib_entry_contribute_ip_forwarding(fei);
1004 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1005 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type,
1006 "11.11.11.11/32 via complete adj");
Neale Ranns3ee44042016-10-03 13:05:48 +01001007 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1008 tm->hw[0]->sw_if_index),
1009 "RPF list for adj-fib contains adj");
1010
1011 ai_12_12_12_12 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001012 VNET_LINK_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001013 &nh_12_12_12_12,
1014 tm->hw[1]->sw_if_index);
1015 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_12_12_12_12), "adj created");
1016 adj = adj_get(ai_12_12_12_12);
1017 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1018 "adj is incomplete");
1019 FIB_TEST((0 == ip46_address_cmp(&nh_12_12_12_12,
1020 &adj->sub_type.nbr.next_hop)),
1021 "adj nbr next-hop ok");
Neale Rannsb80c5362016-10-08 13:03:40 +01001022 adj_nbr_update_rewrite(ai_12_12_12_12, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1023 fib_test_build_rewrite(eth_addr));
Neale Ranns3ee44042016-10-03 13:05:48 +01001024 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1025 "adj is complete");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001026
1027 /*
1028 * add the adj fib
1029 */
Neale Ranns81424992017-05-18 03:03:22 -07001030 fei = fib_table_entry_path_add(fib_index,
1031 &pfx_10_10_10_1_s_32,
1032 FIB_SOURCE_ADJ,
1033 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001034 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001035 &pfx_10_10_10_1_s_32.fp_addr,
1036 tm->hw[0]->sw_if_index,
1037 ~0, // invalid fib index
1038 1,
1039 NULL,
1040 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001041 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
1042 "Flags set on adj-fib");
1043 ai = fib_entry_get_adj(fei);
Neale Ranns81424992017-05-18 03:03:22 -07001044 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001045
1046 fib_table_entry_path_remove(fib_index,
1047 &pfx_11_11_11_11_s_32,
1048 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001049 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001050 &pfx_10_10_10_1_s_32.fp_addr,
1051 tm->hw[0]->sw_if_index,
1052 ~0, // invalid fib index
1053 1,
1054 FIB_ROUTE_PATH_FLAG_NONE);
1055
1056 eth_addr[5] = 0xb2;
1057
1058 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01001059 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001060 &pfx_10_10_10_2_s_32.fp_addr,
1061 tm->hw[0]->sw_if_index);
1062 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
1063 adj = adj_get(ai_02);
1064 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
1065 "adj is incomplete");
1066 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1067 &adj->sub_type.nbr.next_hop)),
1068 "adj nbr next-hop ok");
1069
Neale Rannsb80c5362016-10-08 13:03:40 +01001070 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
1071 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001072 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
1073 "adj is complete");
1074 FIB_TEST((0 == ip46_address_cmp(&pfx_10_10_10_2_s_32.fp_addr,
1075 &adj->sub_type.nbr.next_hop)),
1076 "adj nbr next-hop ok");
1077 FIB_TEST((ai_01 != ai_02), "ADJs are different");
1078
Neale Ranns81424992017-05-18 03:03:22 -07001079 fib_table_entry_path_add(fib_index,
1080 &pfx_10_10_10_2_s_32,
1081 FIB_SOURCE_ADJ,
1082 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07001083 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07001084 &pfx_10_10_10_2_s_32.fp_addr,
1085 tm->hw[0]->sw_if_index,
1086 ~0, // invalid fib index
1087 1,
1088 NULL,
1089 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001090
1091 fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
1092 ai = fib_entry_get_adj(fei);
1093 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
1094
1095 /*
1096 * +2 adj-fibs, and their non-shared path-lists
1097 */
1098 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001099 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001100 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001101 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001102 fib_entry_pool_size());
1103
1104 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001105 * Add 2 routes via the first ADJ. ensure path-list sharing
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001106 */
1107 fib_prefix_t pfx_1_1_1_1_s_32 = {
1108 .fp_len = 32,
1109 .fp_proto = FIB_PROTOCOL_IP4,
1110 .fp_addr = {
1111 /* 1.1.1.1/32 */
1112 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1113 },
1114 };
1115
1116 fib_table_entry_path_add(fib_index,
1117 &pfx_1_1_1_1_s_32,
1118 FIB_SOURCE_API,
1119 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001120 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001121 &nh_10_10_10_1,
1122 tm->hw[0]->sw_if_index,
1123 ~0, // invalid fib index
1124 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001125 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001126 FIB_ROUTE_PATH_FLAG_NONE);
1127 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
1128 ai = fib_entry_get_adj(fei);
1129 FIB_TEST((ai_01 == ai), "1.1.1.1 resolves via 10.10.10.1");
1130
1131 /*
1132 * +1 entry and a shared path-list
1133 */
1134 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001135 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001136 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001137 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001138 fib_entry_pool_size());
1139
1140 /* 1.1.2.0/24 */
1141 fib_prefix_t pfx_1_1_2_0_s_24 = {
1142 .fp_len = 24,
1143 .fp_proto = FIB_PROTOCOL_IP4,
1144 .fp_addr = {
1145 .ip4.as_u32 = clib_host_to_net_u32(0x01010200),
1146 }
1147 };
1148
1149 fib_table_entry_path_add(fib_index,
1150 &pfx_1_1_2_0_s_24,
1151 FIB_SOURCE_API,
1152 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001153 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001154 &nh_10_10_10_1,
1155 tm->hw[0]->sw_if_index,
1156 ~0, // invalid fib index
1157 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001158 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001159 FIB_ROUTE_PATH_FLAG_NONE);
1160 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1161 ai = fib_entry_get_adj(fei);
1162 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1163
1164 /*
1165 * +1 entry only
1166 */
1167 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001168 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001169 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001170 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001171 fib_entry_pool_size());
1172
1173 /*
1174 * modify 1.1.2.0/24 to use multipath.
1175 */
1176 fib_table_entry_path_add(fib_index,
1177 &pfx_1_1_2_0_s_24,
1178 FIB_SOURCE_API,
1179 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001180 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001181 &nh_10_10_10_2,
1182 tm->hw[0]->sw_if_index,
1183 ~0, // invalid fib index
1184 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001185 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001186 FIB_ROUTE_PATH_FLAG_NONE);
1187 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
1188 dpo = fib_entry_contribute_ip_forwarding(fei);
Neale Ranns3ee44042016-10-03 13:05:48 +01001189 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1190 1, tm->hw[0]->sw_if_index),
1191 "RPF list for 1.1.2.0/24 contains both adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001192
1193 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 0);
1194 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1195 FIB_TEST((ai_01 == dpo1->dpoi_index),
1196 "1.1.2.0/24 bucket 0 resolves via 10.10.10.1 (%d=%d)",
1197 ai_01, dpo1->dpoi_index);
1198
1199 dpo1 = load_balance_get_bucket(dpo->dpoi_index, 1);
1200 FIB_TEST(DPO_ADJACENCY == dpo1->dpoi_type, "type is %d", dpo1->dpoi_type);
1201 FIB_TEST((ai_02 == dpo1->dpoi_index),
1202 "1.1.2.0/24 bucket 1 resolves via 10.10.10.2");
1203
1204 /*
1205 * +1 shared-pathlist
1206 */
1207 FIB_TEST((2 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00001208 FIB_TEST((PNBR+6 == 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 * revert the modify
1215 */
1216 fib_table_entry_path_remove(fib_index,
1217 &pfx_1_1_2_0_s_24,
1218 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001219 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001220 &nh_10_10_10_2,
1221 tm->hw[0]->sw_if_index,
1222 ~0,
1223 1,
1224 FIB_ROUTE_PATH_FLAG_NONE);
1225 fei = fib_table_lookup(fib_index, &pfx_1_1_2_0_s_24);
Neale Ranns3ee44042016-10-03 13:05:48 +01001226 dpo = fib_entry_contribute_ip_forwarding(fei);
1227 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1228 1, tm->hw[0]->sw_if_index),
1229 "RPF list for 1.1.2.0/24 contains one adj");
1230
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001231 ai = fib_entry_get_adj(fei);
1232 FIB_TEST((ai_01 == ai), "1.1.2.0/24 resolves via 10.10.10.1");
1233
1234 /*
1235 * +1 shared-pathlist
1236 */
1237 FIB_TEST((1 == fib_path_list_db_size()), "path list DB is %d",
1238 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001239 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001240 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001241 FIB_TEST((ENBR+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001242 fib_entry_pool_size());
1243
1244 /*
1245 * Add 2 recursive routes:
1246 * 100.100.100.100/32 via 1.1.1.1/32 => the via entry is installed.
1247 * 100.100.100.101/32 via 1.1.1.1/32 => the via entry is installed.
1248 */
1249 fib_prefix_t bgp_100_pfx = {
1250 .fp_len = 32,
1251 .fp_proto = FIB_PROTOCOL_IP4,
1252 .fp_addr = {
1253 /* 100.100.100.100/32 */
1254 .ip4.as_u32 = clib_host_to_net_u32(0x64646464),
1255 },
1256 };
1257 /* via 1.1.1.1 */
1258 ip46_address_t nh_1_1_1_1 = {
1259 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
1260 };
1261
Neale Ranns3ee44042016-10-03 13:05:48 +01001262 fei = fib_table_entry_path_add(fib_index,
1263 &bgp_100_pfx,
1264 FIB_SOURCE_API,
1265 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001266 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001267 &nh_1_1_1_1,
1268 ~0, // no index provided.
1269 fib_index, // nexthop in same fib as route
1270 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001271 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001272 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001273
Neale Ranns3ee44042016-10-03 13:05:48 +01001274 FIB_TEST_REC_FORW(&bgp_100_pfx, &pfx_1_1_1_1_s_32, 0);
1275 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1276 tm->hw[0]->sw_if_index),
1277 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001278
1279 /*
1280 * +1 entry and +1 shared-path-list
1281 */
1282 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1283 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001284 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001285 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001286 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001287 fib_entry_pool_size());
1288
1289 fib_prefix_t bgp_101_pfx = {
1290 .fp_len = 32,
1291 .fp_proto = FIB_PROTOCOL_IP4,
1292 .fp_addr = {
1293 /* 100.100.100.101/32 */
1294 .ip4.as_u32 = clib_host_to_net_u32(0x64646465),
1295 },
1296 };
1297
1298 fib_table_entry_path_add(fib_index,
1299 &bgp_101_pfx,
1300 FIB_SOURCE_API,
1301 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001302 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001303 &nh_1_1_1_1,
1304 ~0, // no index provided.
1305 fib_index, // nexthop in same fib as route
1306 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001307 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001308 FIB_ROUTE_PATH_FLAG_NONE);
1309
Neale Ranns3ee44042016-10-03 13:05:48 +01001310 FIB_TEST_REC_FORW(&bgp_101_pfx, &pfx_1_1_1_1_s_32, 0);
1311 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
1312 tm->hw[0]->sw_if_index),
1313 "RPF list for adj-fib contains adj");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001314
1315 /*
1316 * +1 entry, but the recursive path-list is shared.
1317 */
1318 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
1319 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001320 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001321 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001322 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001323 fib_entry_pool_size());
1324
1325 /*
Neale Rannsa0558302017-04-13 00:44:52 -07001326 * An special route; one where the user (me) provides the
1327 * adjacency through which the route will resovle by setting the flags
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001328 */
1329 fib_prefix_t ex_pfx = {
1330 .fp_len = 32,
1331 .fp_proto = FIB_PROTOCOL_IP4,
1332 .fp_addr = {
1333 /* 4.4.4.4/32 */
1334 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
1335 },
1336 };
1337
1338 fib_table_entry_special_add(fib_index,
1339 &ex_pfx,
1340 FIB_SOURCE_SPECIAL,
Neale Rannsa0558302017-04-13 00:44:52 -07001341 FIB_ENTRY_FLAG_LOCAL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001342 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
Neale Rannsa0558302017-04-13 00:44:52 -07001343 dpo = fib_entry_contribute_ip_forwarding(fei);
1344 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
1345 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
1346 "local interface adj is local");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001347
1348 fib_table_entry_special_remove(fib_index,
1349 &ex_pfx,
1350 FIB_SOURCE_SPECIAL);
1351 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1352 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1353 "Exclusive reoute removed");
1354
1355 /*
1356 * An EXCLUSIVE route; one where the user (me) provides the exclusive
1357 * adjacency through which the route will resovle
1358 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001359 dpo_id_t ex_dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001360
1361 lookup_dpo_add_or_lock_w_fib_index(fib_index,
1362 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001363 LOOKUP_UNICAST,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001364 LOOKUP_INPUT_DST_ADDR,
1365 LOOKUP_TABLE_FROM_CONFIG,
1366 &ex_dpo);
1367
1368 fib_table_entry_special_dpo_add(fib_index,
1369 &ex_pfx,
1370 FIB_SOURCE_SPECIAL,
1371 FIB_ENTRY_FLAG_EXCLUSIVE,
1372 &ex_dpo);
1373 fei = fib_table_lookup_exact_match(fib_index, &ex_pfx);
1374 dpo = fib_entry_contribute_ip_forwarding(fei);
1375 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1376 "exclusive remote uses lookup DPO");
1377
Neale Ranns948e00f2016-10-20 13:39:34 +01001378 /*
1379 * update the exclusive to use a different DPO
1380 */
Neale Ranns450cd302016-11-09 17:49:42 +00001381 ip_null_dpo_add_and_lock(DPO_PROTO_IP4,
Neale Ranns948e00f2016-10-20 13:39:34 +01001382 IP_NULL_ACTION_SEND_ICMP_UNREACH,
1383 &ex_dpo);
1384 fib_table_entry_special_dpo_update(fib_index,
1385 &ex_pfx,
1386 FIB_SOURCE_SPECIAL,
1387 FIB_ENTRY_FLAG_EXCLUSIVE,
1388 &ex_dpo);
1389 dpo = fib_entry_contribute_ip_forwarding(fei);
1390 FIB_TEST(!dpo_cmp(&ex_dpo, load_balance_get_bucket(dpo->dpoi_index, 0)),
1391 "exclusive remote uses now uses NULL DPO");
1392
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001393 fib_table_entry_special_remove(fib_index,
1394 &ex_pfx,
1395 FIB_SOURCE_SPECIAL);
1396 FIB_TEST(FIB_NODE_INDEX_INVALID ==
1397 fib_table_lookup_exact_match(fib_index, &ex_pfx),
1398 "Exclusive reoute removed");
1399 dpo_reset(&ex_dpo);
1400
1401 /*
1402 * Add a recursive route:
1403 * 200.200.200.200/32 via 1.1.1.2/32 => the via entry is NOT installed.
1404 */
1405 fib_prefix_t bgp_200_pfx = {
1406 .fp_len = 32,
1407 .fp_proto = FIB_PROTOCOL_IP4,
1408 .fp_addr = {
1409 /* 200.200.200.200/32 */
1410 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c8),
1411 },
1412 };
1413 /* via 1.1.1.2 */
1414 fib_prefix_t pfx_1_1_1_2_s_32 = {
1415 .fp_len = 32,
1416 .fp_proto = FIB_PROTOCOL_IP4,
1417 .fp_addr = {
1418 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
1419 },
1420 };
1421
Neale Ranns57b58602017-07-15 07:37:25 -07001422 fei = fib_table_entry_path_add(fib_index,
1423 &bgp_200_pfx,
1424 FIB_SOURCE_API,
1425 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001426 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07001427 &pfx_1_1_1_2_s_32.fp_addr,
1428 ~0, // no index provided.
1429 fib_index, // nexthop in same fib as route
1430 1,
1431 NULL,
1432 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001433
Neale Ranns57b58602017-07-15 07:37:25 -07001434 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
1435 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001436
1437 /*
1438 * the adj should be recursive via drop, since the route resolves via
1439 * the default route, which is itself a DROP
1440 */
1441 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
1442 dpo1 = fib_entry_contribute_ip_forwarding(fei);
1443 FIB_TEST(load_balance_is_drop(dpo1), "1.1.1.2/32 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01001444 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
1445 "RPF list for 1.1.1.2/32 contains 0 adjs");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001446
1447 /*
1448 * +2 entry and +1 shared-path-list
1449 */
1450 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
1451 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001452 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001453 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00001454 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001455 fib_entry_pool_size());
1456
1457 /*
1458 * Unequal Cost load-balance. 3:1 ratio. fits in a 4 bucket LB
Neale Ranns3ee44042016-10-03 13:05:48 +01001459 * The paths are sort by NH first. in this case the the path with greater
1460 * weight is first in the set. This ordering is to test the RPF sort|uniq logic
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001461 */
1462 fib_prefix_t pfx_1_2_3_4_s_32 = {
1463 .fp_len = 32,
1464 .fp_proto = FIB_PROTOCOL_IP4,
1465 .fp_addr = {
1466 .ip4.as_u32 = clib_host_to_net_u32(0x01020304),
1467 },
1468 };
1469 fib_table_entry_path_add(fib_index,
1470 &pfx_1_2_3_4_s_32,
1471 FIB_SOURCE_API,
1472 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001473 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001474 &nh_10_10_10_1,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001475 tm->hw[0]->sw_if_index,
1476 ~0,
1477 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001478 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001479 FIB_ROUTE_PATH_FLAG_NONE);
1480 fei = fib_table_entry_path_add(fib_index,
1481 &pfx_1_2_3_4_s_32,
1482 FIB_SOURCE_API,
1483 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001484 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001485 &nh_12_12_12_12,
1486 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001487 ~0,
1488 3,
Neale Rannsad422ed2016-11-02 14:20:04 +00001489 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001490 FIB_ROUTE_PATH_FLAG_NONE);
1491
1492 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.4/32 presnet");
1493 dpo = fib_entry_contribute_ip_forwarding(fei);
1494 lb = load_balance_get(dpo->dpoi_index);
1495 FIB_TEST((lb->lb_n_buckets == 4),
1496 "1.2.3.4/32 LB has %d bucket",
1497 lb->lb_n_buckets);
1498
Neale Ranns3ee44042016-10-03 13:05:48 +01001499 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 0, ai_12_12_12_12);
1500 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 1, ai_12_12_12_12);
1501 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 2, ai_12_12_12_12);
1502 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_4_s_32, 3, ai_01);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001503
Neale Ranns3ee44042016-10-03 13:05:48 +01001504 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1505 tm->hw[0]->sw_if_index,
1506 tm->hw[1]->sw_if_index),
1507 "RPF list for 1.2.3.4/32 contains both adjs");
1508
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001509
1510 /*
1511 * Unequal Cost load-balance. 4:1 ratio.
1512 * fits in a 16 bucket LB with ratio 13:3
1513 */
1514 fib_prefix_t pfx_1_2_3_5_s_32 = {
1515 .fp_len = 32,
1516 .fp_proto = FIB_PROTOCOL_IP4,
1517 .fp_addr = {
1518 .ip4.as_u32 = clib_host_to_net_u32(0x01020305),
1519 },
1520 };
1521 fib_table_entry_path_add(fib_index,
1522 &pfx_1_2_3_5_s_32,
1523 FIB_SOURCE_API,
1524 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001525 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001526 &nh_12_12_12_12,
1527 tm->hw[1]->sw_if_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001528 ~0,
1529 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001530 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001531 FIB_ROUTE_PATH_FLAG_NONE);
1532 fei = fib_table_entry_path_add(fib_index,
1533 &pfx_1_2_3_5_s_32,
1534 FIB_SOURCE_API,
1535 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001536 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001537 &nh_10_10_10_1,
1538 tm->hw[0]->sw_if_index,
1539 ~0,
1540 4,
Neale Rannsad422ed2016-11-02 14:20:04 +00001541 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001542 FIB_ROUTE_PATH_FLAG_NONE);
1543
1544 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.2.3.5/32 presnet");
1545 dpo = fib_entry_contribute_ip_forwarding(fei);
1546 lb = load_balance_get(dpo->dpoi_index);
1547 FIB_TEST((lb->lb_n_buckets == 16),
1548 "1.2.3.5/32 LB has %d bucket",
1549 lb->lb_n_buckets);
1550
1551 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 0, ai_01);
1552 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 1, ai_01);
1553 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 2, ai_01);
1554 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 3, ai_01);
1555 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 4, ai_01);
1556 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 5, ai_01);
1557 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 6, ai_01);
1558 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 7, ai_01);
1559 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 8, ai_01);
1560 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 9, ai_01);
1561 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 10, ai_01);
1562 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 11, ai_01);
1563 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 12, ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01001564 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 13, ai_12_12_12_12);
1565 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 14, ai_12_12_12_12);
1566 FIB_TEST_LB_BUCKET_VIA_ADJ(&pfx_1_2_3_5_s_32, 15, ai_12_12_12_12);
1567
1568 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1569 tm->hw[0]->sw_if_index,
1570 tm->hw[1]->sw_if_index),
1571 "RPF list for 1.2.3.4/32 contains both adjs");
1572
1573 /*
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001574 * Test UCMP with a large weight skew - this produces load-balance objects with large
1575 * numbers of buckets to accommodate the skew. By updating said load-balances we are
1576 * laso testing the LB in placce modify code when number of buckets is large.
1577 */
1578 fib_prefix_t pfx_6_6_6_6_s_32 = {
1579 .fp_len = 32,
1580 .fp_proto = FIB_PROTOCOL_IP4,
1581 .fp_addr = {
1582 /* 1.1.1.1/32 */
1583 .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
1584 },
1585 };
Neale Ranns81424992017-05-18 03:03:22 -07001586 fib_test_lb_bucket_t ip_o_10_10_10_1 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001587 .type = FT_LB_ADJ,
1588 .adj = {
1589 .adj = ai_01,
1590 },
1591 };
Neale Ranns81424992017-05-18 03:03:22 -07001592 fib_test_lb_bucket_t ip_o_10_10_10_2 = {
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001593 .type = FT_LB_ADJ,
1594 .adj = {
1595 .adj = ai_02,
1596 },
1597 };
1598 fib_test_lb_bucket_t ip_6_6_6_6_o_12_12_12_12 = {
1599 .type = FT_LB_ADJ,
1600 .adj = {
1601 .adj = ai_12_12_12_12,
1602 },
1603 };
1604 fib_table_entry_update_one_path(fib_index,
1605 &pfx_6_6_6_6_s_32,
1606 FIB_SOURCE_API,
1607 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001608 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001609 &nh_10_10_10_1,
1610 tm->hw[0]->sw_if_index,
1611 ~0, // invalid fib index
1612 0, // zero weigth
Neale Rannsad422ed2016-11-02 14:20:04 +00001613 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001614 FIB_ROUTE_PATH_FLAG_NONE);
1615
1616 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1617 FIB_TEST(fib_test_validate_entry(fei,
1618 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1619 1,
Neale Ranns81424992017-05-18 03:03:22 -07001620 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001621 "6.6.6.6/32 via 10.10.10.1");
1622
1623 fib_table_entry_path_add(fib_index,
1624 &pfx_6_6_6_6_s_32,
1625 FIB_SOURCE_API,
1626 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001627 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001628 &nh_10_10_10_2,
1629 tm->hw[0]->sw_if_index,
1630 ~0, // invalid fib index
1631 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001632 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001633 FIB_ROUTE_PATH_FLAG_NONE);
1634
1635 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1636 FIB_TEST(fib_test_validate_entry(fei,
1637 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1638 64,
Neale Ranns81424992017-05-18 03:03:22 -07001639 &ip_o_10_10_10_2,
1640 &ip_o_10_10_10_2,
1641 &ip_o_10_10_10_2,
1642 &ip_o_10_10_10_2,
1643 &ip_o_10_10_10_2,
1644 &ip_o_10_10_10_2,
1645 &ip_o_10_10_10_2,
1646 &ip_o_10_10_10_2,
1647 &ip_o_10_10_10_2,
1648 &ip_o_10_10_10_2,
1649 &ip_o_10_10_10_2,
1650 &ip_o_10_10_10_2,
1651 &ip_o_10_10_10_2,
1652 &ip_o_10_10_10_2,
1653 &ip_o_10_10_10_2,
1654 &ip_o_10_10_10_2,
1655 &ip_o_10_10_10_2,
1656 &ip_o_10_10_10_2,
1657 &ip_o_10_10_10_2,
1658 &ip_o_10_10_10_2,
1659 &ip_o_10_10_10_2,
1660 &ip_o_10_10_10_2,
1661 &ip_o_10_10_10_2,
1662 &ip_o_10_10_10_2,
1663 &ip_o_10_10_10_2,
1664 &ip_o_10_10_10_2,
1665 &ip_o_10_10_10_2,
1666 &ip_o_10_10_10_2,
1667 &ip_o_10_10_10_2,
1668 &ip_o_10_10_10_2,
1669 &ip_o_10_10_10_2,
1670 &ip_o_10_10_10_2,
1671 &ip_o_10_10_10_2,
1672 &ip_o_10_10_10_2,
1673 &ip_o_10_10_10_2,
1674 &ip_o_10_10_10_2,
1675 &ip_o_10_10_10_2,
1676 &ip_o_10_10_10_2,
1677 &ip_o_10_10_10_2,
1678 &ip_o_10_10_10_2,
1679 &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_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001703 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1704
1705 fib_table_entry_path_add(fib_index,
1706 &pfx_6_6_6_6_s_32,
1707 FIB_SOURCE_API,
1708 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001709 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001710 &nh_12_12_12_12,
1711 tm->hw[1]->sw_if_index,
1712 ~0, // invalid fib index
1713 100,
Neale Rannsad422ed2016-11-02 14:20:04 +00001714 NULL,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001715 FIB_ROUTE_PATH_FLAG_NONE);
1716
1717 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1718 FIB_TEST(fib_test_validate_entry(fei,
1719 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1720 128,
Neale Ranns81424992017-05-18 03:03:22 -07001721 &ip_o_10_10_10_1,
1722 &ip_o_10_10_10_2,
1723 &ip_o_10_10_10_2,
1724 &ip_o_10_10_10_2,
1725 &ip_o_10_10_10_2,
1726 &ip_o_10_10_10_2,
1727 &ip_o_10_10_10_2,
1728 &ip_o_10_10_10_2,
1729 &ip_o_10_10_10_2,
1730 &ip_o_10_10_10_2,
1731 &ip_o_10_10_10_2,
1732 &ip_o_10_10_10_2,
1733 &ip_o_10_10_10_2,
1734 &ip_o_10_10_10_2,
1735 &ip_o_10_10_10_2,
1736 &ip_o_10_10_10_2,
1737 &ip_o_10_10_10_2,
1738 &ip_o_10_10_10_2,
1739 &ip_o_10_10_10_2,
1740 &ip_o_10_10_10_2,
1741 &ip_o_10_10_10_2,
1742 &ip_o_10_10_10_2,
1743 &ip_o_10_10_10_2,
1744 &ip_o_10_10_10_2,
1745 &ip_o_10_10_10_2,
1746 &ip_o_10_10_10_2,
1747 &ip_o_10_10_10_2,
1748 &ip_o_10_10_10_2,
1749 &ip_o_10_10_10_2,
1750 &ip_o_10_10_10_2,
1751 &ip_o_10_10_10_2,
1752 &ip_o_10_10_10_2,
1753 &ip_o_10_10_10_2,
1754 &ip_o_10_10_10_2,
1755 &ip_o_10_10_10_2,
1756 &ip_o_10_10_10_2,
1757 &ip_o_10_10_10_2,
1758 &ip_o_10_10_10_2,
1759 &ip_o_10_10_10_2,
1760 &ip_o_10_10_10_2,
1761 &ip_o_10_10_10_2,
1762 &ip_o_10_10_10_2,
1763 &ip_o_10_10_10_2,
1764 &ip_o_10_10_10_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,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001786 &ip_6_6_6_6_o_12_12_12_12,
1787 &ip_6_6_6_6_o_12_12_12_12,
1788 &ip_6_6_6_6_o_12_12_12_12,
1789 &ip_6_6_6_6_o_12_12_12_12,
1790 &ip_6_6_6_6_o_12_12_12_12,
1791 &ip_6_6_6_6_o_12_12_12_12,
1792 &ip_6_6_6_6_o_12_12_12_12,
1793 &ip_6_6_6_6_o_12_12_12_12,
1794 &ip_6_6_6_6_o_12_12_12_12,
1795 &ip_6_6_6_6_o_12_12_12_12,
1796 &ip_6_6_6_6_o_12_12_12_12,
1797 &ip_6_6_6_6_o_12_12_12_12,
1798 &ip_6_6_6_6_o_12_12_12_12,
1799 &ip_6_6_6_6_o_12_12_12_12,
1800 &ip_6_6_6_6_o_12_12_12_12,
1801 &ip_6_6_6_6_o_12_12_12_12,
1802 &ip_6_6_6_6_o_12_12_12_12,
1803 &ip_6_6_6_6_o_12_12_12_12,
1804 &ip_6_6_6_6_o_12_12_12_12,
1805 &ip_6_6_6_6_o_12_12_12_12,
1806 &ip_6_6_6_6_o_12_12_12_12,
1807 &ip_6_6_6_6_o_12_12_12_12,
1808 &ip_6_6_6_6_o_12_12_12_12,
1809 &ip_6_6_6_6_o_12_12_12_12,
1810 &ip_6_6_6_6_o_12_12_12_12,
1811 &ip_6_6_6_6_o_12_12_12_12,
1812 &ip_6_6_6_6_o_12_12_12_12,
1813 &ip_6_6_6_6_o_12_12_12_12,
1814 &ip_6_6_6_6_o_12_12_12_12,
1815 &ip_6_6_6_6_o_12_12_12_12,
1816 &ip_6_6_6_6_o_12_12_12_12,
1817 &ip_6_6_6_6_o_12_12_12_12,
1818 &ip_6_6_6_6_o_12_12_12_12,
1819 &ip_6_6_6_6_o_12_12_12_12,
1820 &ip_6_6_6_6_o_12_12_12_12,
1821 &ip_6_6_6_6_o_12_12_12_12,
1822 &ip_6_6_6_6_o_12_12_12_12,
1823 &ip_6_6_6_6_o_12_12_12_12,
1824 &ip_6_6_6_6_o_12_12_12_12,
1825 &ip_6_6_6_6_o_12_12_12_12,
1826 &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 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1850
1851 fib_table_entry_path_remove(fib_index,
1852 &pfx_6_6_6_6_s_32,
1853 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001854 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001855 &nh_12_12_12_12,
1856 tm->hw[1]->sw_if_index,
1857 ~0, // invalid fib index
1858 100,
1859 FIB_ROUTE_PATH_FLAG_NONE);
1860
1861 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1862 FIB_TEST(fib_test_validate_entry(fei,
1863 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1864 64,
Neale Ranns81424992017-05-18 03:03:22 -07001865 &ip_o_10_10_10_2,
1866 &ip_o_10_10_10_2,
1867 &ip_o_10_10_10_2,
1868 &ip_o_10_10_10_2,
1869 &ip_o_10_10_10_2,
1870 &ip_o_10_10_10_2,
1871 &ip_o_10_10_10_2,
1872 &ip_o_10_10_10_2,
1873 &ip_o_10_10_10_2,
1874 &ip_o_10_10_10_2,
1875 &ip_o_10_10_10_2,
1876 &ip_o_10_10_10_2,
1877 &ip_o_10_10_10_2,
1878 &ip_o_10_10_10_2,
1879 &ip_o_10_10_10_2,
1880 &ip_o_10_10_10_2,
1881 &ip_o_10_10_10_2,
1882 &ip_o_10_10_10_2,
1883 &ip_o_10_10_10_2,
1884 &ip_o_10_10_10_2,
1885 &ip_o_10_10_10_2,
1886 &ip_o_10_10_10_2,
1887 &ip_o_10_10_10_2,
1888 &ip_o_10_10_10_2,
1889 &ip_o_10_10_10_2,
1890 &ip_o_10_10_10_2,
1891 &ip_o_10_10_10_2,
1892 &ip_o_10_10_10_2,
1893 &ip_o_10_10_10_2,
1894 &ip_o_10_10_10_2,
1895 &ip_o_10_10_10_2,
1896 &ip_o_10_10_10_2,
1897 &ip_o_10_10_10_2,
1898 &ip_o_10_10_10_2,
1899 &ip_o_10_10_10_2,
1900 &ip_o_10_10_10_2,
1901 &ip_o_10_10_10_2,
1902 &ip_o_10_10_10_2,
1903 &ip_o_10_10_10_2,
1904 &ip_o_10_10_10_2,
1905 &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_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001929 "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
1930
1931 fib_table_entry_path_remove(fib_index,
1932 &pfx_6_6_6_6_s_32,
1933 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07001934 DPO_PROTO_IP4,
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001935 &nh_10_10_10_2,
1936 tm->hw[0]->sw_if_index,
1937 ~0, // invalid fib index
1938 100,
1939 FIB_ROUTE_PATH_FLAG_NONE);
1940
1941 fei = fib_table_lookup(fib_index, &pfx_6_6_6_6_s_32);
1942 FIB_TEST(fib_test_validate_entry(fei,
1943 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
1944 1,
Neale Ranns81424992017-05-18 03:03:22 -07001945 &ip_o_10_10_10_1),
Neale Ranns0bd36ea2016-11-16 11:47:44 +00001946 "6.6.6.6/32 via 10.10.10.1");
1947
1948 fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
1949
1950 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01001951 * A recursive via the two unequal cost entries
1952 */
1953 fib_prefix_t bgp_44_s_32 = {
1954 .fp_len = 32,
1955 .fp_proto = FIB_PROTOCOL_IP4,
1956 .fp_addr = {
1957 /* 200.200.200.201/32 */
1958 .ip4.as_u32 = clib_host_to_net_u32(0x44444444),
1959 },
1960 };
1961 fei = fib_table_entry_path_add(fib_index,
1962 &bgp_44_s_32,
1963 FIB_SOURCE_API,
1964 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001965 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001966 &pfx_1_2_3_4_s_32.fp_addr,
1967 ~0,
1968 fib_index,
1969 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001970 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001971 FIB_ROUTE_PATH_FLAG_NONE);
1972 fei = fib_table_entry_path_add(fib_index,
1973 &bgp_44_s_32,
1974 FIB_SOURCE_API,
1975 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07001976 DPO_PROTO_IP4,
Neale Ranns3ee44042016-10-03 13:05:48 +01001977 &pfx_1_2_3_5_s_32.fp_addr,
1978 ~0,
1979 fib_index,
1980 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00001981 NULL,
Neale Ranns3ee44042016-10-03 13:05:48 +01001982 FIB_ROUTE_PATH_FLAG_NONE);
1983
1984 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_4_s_32, 0);
1985 FIB_TEST_REC_FORW(&bgp_44_s_32, &pfx_1_2_3_5_s_32, 1);
1986 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 2,
1987 tm->hw[0]->sw_if_index,
1988 tm->hw[1]->sw_if_index),
1989 "RPF list for 1.2.3.4/32 contains both adjs");
1990
1991 /*
1992 * test the uRPF check functions
1993 */
Neale Ranns948e00f2016-10-20 13:39:34 +01001994 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01001995 index_t urpfi;
1996
1997 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
1998 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
1999
2000 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
2001 "uRPF check for 68.68.68.68/32 on %d OK",
2002 tm->hw[0]->sw_if_index);
2003 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
2004 "uRPF check for 68.68.68.68/32 on %d OK",
2005 tm->hw[1]->sw_if_index);
2006 FIB_TEST(!fib_urpf_check(urpfi, 99),
2007 "uRPF check for 68.68.68.68/32 on 99 not-OK",
2008 99);
2009 dpo_reset(&dpo_44);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002010
2011 fib_table_entry_delete(fib_index,
Neale Ranns3ee44042016-10-03 13:05:48 +01002012 &bgp_44_s_32,
2013 FIB_SOURCE_API);
2014 fib_table_entry_delete(fib_index,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002015 &pfx_1_2_3_5_s_32,
2016 FIB_SOURCE_API);
Neale Ranns3ee44042016-10-03 13:05:48 +01002017 fib_table_entry_delete(fib_index,
2018 &pfx_1_2_3_4_s_32,
2019 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002020
2021 /*
2022 * Add a recursive route:
2023 * 200.200.200.201/32 via 1.1.1.200/32 => the via entry is NOT installed.
2024 */
2025 fib_prefix_t bgp_201_pfx = {
2026 .fp_len = 32,
2027 .fp_proto = FIB_PROTOCOL_IP4,
2028 .fp_addr = {
2029 /* 200.200.200.201/32 */
2030 .ip4.as_u32 = clib_host_to_net_u32(0xc8c8c8c9),
2031 },
2032 };
2033 /* via 1.1.1.200 */
2034 fib_prefix_t pfx_1_1_1_200_s_32 = {
2035 .fp_len = 32,
2036 .fp_proto = FIB_PROTOCOL_IP4,
2037 .fp_addr = {
2038 .ip4.as_u32 = clib_host_to_net_u32(0x010101c8),
2039 },
2040 };
2041
Neale Ranns57b58602017-07-15 07:37:25 -07002042 fei = fib_table_entry_path_add(fib_index,
2043 &bgp_201_pfx,
2044 FIB_SOURCE_API,
2045 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002046 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002047 &pfx_1_1_1_200_s_32.fp_addr,
2048 ~0, // no index provided.
2049 fib_index, // nexthop in same fib as route
2050 1,
2051 NULL,
2052 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002053
Neale Ranns57b58602017-07-15 07:37:25 -07002054 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2055 "Recursive via unresolved is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002056
2057 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
2058 FIB_TEST((FIB_ENTRY_FLAG_NONE == fib_entry_get_flags(fei)),
2059 "Flags set on RR via non-attached");
Neale Ranns3ee44042016-10-03 13:05:48 +01002060 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
2061 "RPF list for BGP route empty");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002062
2063 /*
2064 * +2 entry (BGP & RR) and +1 shared-path-list
2065 */
2066 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2067 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002068 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002069 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002070 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002071 fib_entry_pool_size());
2072
2073 /*
2074 * insert a route that covers the missing 1.1.1.2/32. we epxect
2075 * 200.200.200.200/32 and 200.200.200.201/32 to resolve through it.
2076 */
2077 fib_prefix_t pfx_1_1_1_0_s_24 = {
2078 .fp_len = 24,
2079 .fp_proto = FIB_PROTOCOL_IP4,
2080 .fp_addr = {
2081 /* 1.1.1.0/24 */
2082 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2083 },
2084 };
2085
2086 fib_table_entry_path_add(fib_index,
2087 &pfx_1_1_1_0_s_24,
2088 FIB_SOURCE_API,
2089 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002090 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002091 &nh_10_10_10_1,
2092 tm->hw[0]->sw_if_index,
2093 ~0, // invalid fib index
2094 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002095 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002096 FIB_ROUTE_PATH_FLAG_NONE);
2097 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24);
2098 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2099 ai = fib_entry_get_adj(fei);
2100 FIB_TEST((ai_01 == ai), "1.1.1.0/24 resolves via 10.10.10.1");
2101 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2102 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2103 ai = fib_entry_get_adj(fei);
2104 FIB_TEST((ai_01 == ai), "1.1.1.2/32 resolves via 10.10.10.1");
2105 fei = fib_table_lookup(fib_index, &pfx_1_1_1_200_s_32);
2106 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2107 ai = fib_entry_get_adj(fei);
2108 FIB_TEST((ai_01 == ai), "1.1.1.200/24 resolves via 10.10.10.1");
2109
2110 /*
2111 * +1 entry. 1.1.1.1/32 already uses 10.10.10.1 so no new pah-list
2112 */
2113 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2114 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002115 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002116 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002117 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002118 fib_entry_pool_size());
2119
2120 /*
2121 * the recursive adj for 200.200.200.200 should be updated.
2122 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002123 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2124 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
2125 fei = fib_table_lookup(fib_index, &bgp_200_pfx);
2126 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1,
2127 tm->hw[0]->sw_if_index),
2128 "RPF list for BGP route has itf index 0");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002129
2130 /*
2131 * insert a more specific route than 1.1.1.0/24 that also covers the
2132 * missing 1.1.1.2/32, but not 1.1.1.200/32. we epxect
2133 * 200.200.200.200 to resolve through it.
2134 */
2135 fib_prefix_t pfx_1_1_1_0_s_28 = {
2136 .fp_len = 28,
2137 .fp_proto = FIB_PROTOCOL_IP4,
2138 .fp_addr = {
2139 /* 1.1.1.0/24 */
2140 .ip4.as_u32 = clib_host_to_net_u32(0x01010100),
2141 },
2142 };
2143
2144 fib_table_entry_path_add(fib_index,
2145 &pfx_1_1_1_0_s_28,
2146 FIB_SOURCE_API,
2147 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002148 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002149 &nh_10_10_10_2,
2150 tm->hw[0]->sw_if_index,
2151 ~0, // invalid fib index
2152 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002153 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002154 FIB_ROUTE_PATH_FLAG_NONE);
2155 fei = fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28);
2156 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2157 ai = fib_entry_get_adj(fei);
2158 FIB_TEST((ai_02 == ai), "1.1.1.0/24 resolves via 10.10.10.2");
2159
2160 /*
2161 * +1 entry. +1 shared path-list
2162 */
2163 FIB_TEST((5 == fib_path_list_db_size()), "path list DB population:%d",
2164 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002165 FIB_TEST((PNBR+9 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002166 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002167 FIB_TEST((ENBR+14 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002168 fib_entry_pool_size());
2169
2170 /*
2171 * the recursive adj for 200.200.200.200 should be updated.
2172 * 200.200.200.201 remains unchanged.
2173 */
Neale Ranns3ee44042016-10-03 13:05:48 +01002174 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2175 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002176
2177 /*
2178 * remove this /28. 200.200.200.200/32 should revert back to via 1.1.1.0/24
2179 */
2180 fib_table_entry_path_remove(fib_index,
2181 &pfx_1_1_1_0_s_28,
2182 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002183 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002184 &nh_10_10_10_2,
2185 tm->hw[0]->sw_if_index,
2186 ~0,
2187 1,
2188 FIB_ROUTE_PATH_FLAG_NONE);
2189 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28) ==
2190 FIB_NODE_INDEX_INVALID),
2191 "1.1.1.0/28 removed");
2192 FIB_TEST((fib_table_lookup(fib_index, &pfx_1_1_1_0_s_28) ==
2193 fib_table_lookup(fib_index, &pfx_1_1_1_0_s_24)),
2194 "1.1.1.0/28 lookup via /24");
Neale Ranns3ee44042016-10-03 13:05:48 +01002195 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_200_s_32, 0);
2196 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002197
2198 /*
2199 * -1 entry. -1 shared path-list
2200 */
2201 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2202 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002203 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002204 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002205 FIB_TEST((ENBR+13 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002206 fib_entry_pool_size());
2207
2208 /*
2209 * remove 1.1.1.0/24. 200.200.200.200/32 should revert back to via 0.0.0.0/0
2210 */
2211 fib_table_entry_path_remove(fib_index,
2212 &pfx_1_1_1_0_s_24,
2213 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002214 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002215 &nh_10_10_10_1,
2216 tm->hw[0]->sw_if_index,
2217 ~0,
2218 1,
2219 FIB_ROUTE_PATH_FLAG_NONE);
2220 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_24) ==
2221 FIB_NODE_INDEX_INVALID),
2222 "1.1.1.0/24 removed");
2223
2224 fei = fib_table_lookup(fib_index, &pfx_1_1_1_2_s_32);
2225 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2226 "1.1.1.2/32 route is DROP");
Neale Ranns57b58602017-07-15 07:37:25 -07002227 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002228 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2229 "1.1.1.200/32 route is DROP");
2230
Neale Ranns57b58602017-07-15 07:37:25 -07002231 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2232 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2233 "201 is drop");
2234 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2235 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2236 "200 is drop");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002237
2238 /*
2239 * -1 entry
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+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002246 fib_entry_pool_size());
2247
2248 /*
2249 * insert the missing 1.1.1.2/32
2250 */
2251 fei = fib_table_entry_path_add(fib_index,
2252 &pfx_1_1_1_2_s_32,
2253 FIB_SOURCE_API,
2254 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002255 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002256 &nh_10_10_10_1,
2257 tm->hw[0]->sw_if_index,
2258 ~0, // invalid fib index
2259 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002260 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002261 FIB_ROUTE_PATH_FLAG_NONE);
2262 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2263 ai = fib_entry_get_adj(fei);
2264 FIB_TEST((ai = ai_01), "1.1.1.2/32 resolves via 10.10.10.1");
2265
Neale Ranns57b58602017-07-15 07:37:25 -07002266 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2267 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2268 "201 is drop");
Neale Ranns3ee44042016-10-03 13:05:48 +01002269 FIB_TEST_REC_FORW(&bgp_200_pfx, &pfx_1_1_1_2_s_32, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002270
2271 /*
2272 * no change. 1.1.1.2/32 was already there RR sourced.
2273 */
2274 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2275 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002276 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002277 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002278 FIB_TEST((ENBR+12 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002279 fib_entry_pool_size());
2280
2281 /*
Neale Ranns57b58602017-07-15 07:37:25 -07002282 * give 201 a resolved path.
2283 * it now has the unresolved 1.1.1.200 and the resolved 1.1.1.2,
2284 * only the latter contributes forwarding.
2285 */
2286 fei = fib_table_entry_path_add(fib_index,
2287 &bgp_201_pfx,
2288 FIB_SOURCE_API,
2289 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002290 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002291 &pfx_1_1_1_2_s_32.fp_addr,
2292 ~0,
2293 fib_index,
2294 1,
2295 NULL,
2296 FIB_ROUTE_PATH_FLAG_NONE);
2297 FIB_TEST_REC_FORW(&bgp_201_pfx, &pfx_1_1_1_2_s_32, 0);
2298 fib_table_entry_path_remove(fib_index,
2299 &bgp_201_pfx,
2300 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002301 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07002302 &pfx_1_1_1_2_s_32.fp_addr,
2303 ~0,
2304 fib_index,
2305 1,
2306 FIB_ROUTE_PATH_FLAG_NONE);
2307
2308 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002309 * remove 200.200.200.201/32 which does not have a valid via FIB
2310 */
2311 fib_table_entry_path_remove(fib_index,
2312 &bgp_201_pfx,
2313 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002314 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002315 &pfx_1_1_1_200_s_32.fp_addr,
2316 ~0, // no index provided.
2317 fib_index,
2318 1,
2319 FIB_ROUTE_PATH_FLAG_NONE);
2320
2321 /*
2322 * -2 entries (BGP and RR). -1 shared path-list;
2323 */
2324 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2325 FIB_NODE_INDEX_INVALID),
2326 "200.200.200.201/32 removed");
2327 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_200_s_32) ==
2328 FIB_NODE_INDEX_INVALID),
2329 "1.1.1.200/32 removed");
2330
2331 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2332 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002333 FIB_TEST((PNBR+7 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002334 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002335 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002336 fib_entry_pool_size());
2337
2338 /*
2339 * remove 200.200.200.200/32 which does have a valid via FIB
2340 */
2341 fib_table_entry_path_remove(fib_index,
2342 &bgp_200_pfx,
2343 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002344 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002345 &pfx_1_1_1_2_s_32.fp_addr,
2346 ~0, // no index provided.
2347 fib_index,
2348 1,
2349 FIB_ROUTE_PATH_FLAG_NONE);
2350
2351 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2352 FIB_NODE_INDEX_INVALID),
2353 "200.200.200.200/32 removed");
2354 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32) !=
2355 FIB_NODE_INDEX_INVALID),
2356 "1.1.1.2/32 still present");
2357
2358 /*
2359 * -1 entry (BGP, the RR source is also API sourced). -1 shared path-list;
2360 */
2361 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2362 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002363 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002364 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002365 FIB_TEST((ENBR+9 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002366 fib_entry_pool_size());
2367
2368 /*
2369 * A recursive prefix that has a 2 path load-balance.
2370 * It also shares a next-hop with other BGP prefixes and hence
2371 * test the ref counting of RR sourced prefixes and 2 level LB.
2372 */
2373 const fib_prefix_t bgp_102 = {
2374 .fp_len = 32,
2375 .fp_proto = FIB_PROTOCOL_IP4,
2376 .fp_addr = {
2377 /* 100.100.100.101/32 */
2378 .ip4.as_u32 = clib_host_to_net_u32(0x64646466),
2379 },
2380 };
2381 fib_table_entry_path_add(fib_index,
2382 &bgp_102,
2383 FIB_SOURCE_API,
2384 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002385 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002386 &pfx_1_1_1_1_s_32.fp_addr,
2387 ~0, // no index provided.
2388 fib_index, // same as route
2389 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002390 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002391 FIB_ROUTE_PATH_FLAG_NONE);
2392 fib_table_entry_path_add(fib_index,
2393 &bgp_102,
2394 FIB_SOURCE_API,
2395 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002396 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002397 &pfx_1_1_1_2_s_32.fp_addr,
2398 ~0, // no index provided.
2399 fib_index, // same as route's FIB
2400 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002401 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002402 FIB_ROUTE_PATH_FLAG_NONE);
2403 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2404 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "100.100.100.102/32 presnet");
2405 dpo = fib_entry_contribute_ip_forwarding(fei);
2406
2407 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2408 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2409 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32);
2410 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2411
2412 lb = load_balance_get(dpo->dpoi_index);
2413 FIB_TEST((lb->lb_n_buckets == 2), "Recursive LB has %d bucket", lb->lb_n_buckets);
2414 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2415 "First via 10.10.10.1");
2416 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 1)),
2417 "Second via 10.10.10.1");
2418
2419 fib_table_entry_path_remove(fib_index,
2420 &bgp_102,
2421 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002422 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002423 &pfx_1_1_1_1_s_32.fp_addr,
2424 ~0, // no index provided.
2425 fib_index, // same as route's FIB
2426 1,
2427 FIB_ROUTE_PATH_FLAG_NONE);
2428 fib_table_entry_path_remove(fib_index,
2429 &bgp_102,
2430 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002431 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002432 &pfx_1_1_1_2_s_32.fp_addr,
2433 ~0, // no index provided.
2434 fib_index, // same as route's FIB
2435 1,
2436 FIB_ROUTE_PATH_FLAG_NONE);
2437 fei = fib_table_lookup_exact_match(fib_index, &bgp_102);
2438 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "100.100.100.102/32 removed");
2439
2440 /*
2441 * remove the remaining recursives
2442 */
2443 fib_table_entry_path_remove(fib_index,
2444 &bgp_100_pfx,
2445 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002446 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002447 &pfx_1_1_1_1_s_32.fp_addr,
2448 ~0, // no index provided.
2449 fib_index, // same as route's FIB
2450 1,
2451 FIB_ROUTE_PATH_FLAG_NONE);
2452 fib_table_entry_path_remove(fib_index,
2453 &bgp_101_pfx,
2454 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002455 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002456 &pfx_1_1_1_1_s_32.fp_addr,
2457 ~0, // no index provided.
2458 fib_index, // same as route's FIB
2459 1,
2460 FIB_ROUTE_PATH_FLAG_NONE);
2461 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_100_pfx) ==
2462 FIB_NODE_INDEX_INVALID),
2463 "100.100.100.100/32 removed");
2464 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_101_pfx) ==
2465 FIB_NODE_INDEX_INVALID),
2466 "100.100.100.101/32 removed");
2467
2468 /*
2469 * -2 entry (2*BGP, the RR source is also API sourced). -1 shared path-list;
2470 */
2471 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2472 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002473 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002474 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002475 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002476 fib_entry_pool_size());
2477
2478 /*
2479 * Add a recursive route via a connected cover, using an adj-fib that does exist
2480 */
2481 fib_table_entry_path_add(fib_index,
2482 &bgp_200_pfx,
2483 FIB_SOURCE_API,
2484 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002485 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002486 &nh_10_10_10_1,
2487 ~0, // no index provided.
2488 fib_index, // Same as route's FIB
2489 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002490 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002491 FIB_ROUTE_PATH_FLAG_NONE);
2492
2493 /*
2494 * +1 entry. +1 shared path-list (recursive via 10.10.10.1)
2495 */
2496 FIB_TEST((2 == fib_path_list_db_size()), "path list DB population:%d",
2497 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002498 FIB_TEST((PNBR+6 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002499 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002500 FIB_TEST((ENBR+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002501 fib_entry_pool_size());
2502
2503 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
2504 dpo = fib_entry_contribute_ip_forwarding(fei);
2505
2506 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
2507 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2508
2509 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2510 "200.200.200.200/32 is recursive via adj for 10.10.10.1");
2511
2512 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED == fib_entry_get_flags(fei)),
2513 "Flags set on RR via existing attached");
2514
2515 /*
2516 * Add a recursive route via a connected cover, using and adj-fib that does
2517 * not exist
2518 */
2519 ip46_address_t nh_10_10_10_3 = {
2520 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
2521 };
2522 fib_prefix_t pfx_10_10_10_3 = {
2523 .fp_len = 32,
2524 .fp_proto = FIB_PROTOCOL_IP4,
2525 .fp_addr = nh_10_10_10_3,
2526 };
2527
2528 fib_table_entry_path_add(fib_index,
2529 &bgp_201_pfx,
2530 FIB_SOURCE_API,
2531 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002532 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002533 &nh_10_10_10_3,
2534 ~0, // no index provided.
2535 fib_index,
2536 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002537 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002538 FIB_ROUTE_PATH_FLAG_NONE);
2539
2540 /*
2541 * +2 entries (BGP and RR). +1 shared path-list (recursive via 10.10.10.3) and
2542 * one unshared non-recursive via 10.10.10.3
2543 */
2544 FIB_TEST((3 == fib_path_list_db_size()), "path list DB population:%d",
2545 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002546 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002547 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002548 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002549 fib_entry_pool_size());
2550
2551 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01002552 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002553 &nh_10_10_10_3,
2554 tm->hw[0]->sw_if_index);
2555
2556 fei = fib_table_lookup_exact_match(fib_index, &bgp_201_pfx);
2557 dpo = fib_entry_contribute_ip_forwarding(fei);
2558 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3);
2559 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2560
2561 ai = fib_entry_get_adj(fei);
2562 FIB_TEST((ai == ai_03), "adj for 10.10.10.3/32 is via adj for 10.10.10.3");
2563 FIB_TEST(((FIB_ENTRY_FLAG_ATTACHED | FIB_ENTRY_FLAG_CONNECTED) ==
2564 fib_entry_get_flags(fei)),
2565 "Flags set on RR via non-existing attached");
2566
2567 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 0)),
2568 "adj for 200.200.200.200/32 is recursive via adj for 10.10.10.3");
2569
2570 adj_unlock(ai_03);
2571
2572 /*
2573 * remove the recursives
2574 */
2575 fib_table_entry_path_remove(fib_index,
2576 &bgp_200_pfx,
2577 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002578 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002579 &nh_10_10_10_1,
2580 ~0, // no index provided.
2581 fib_index, // same as route's FIB
2582 1,
2583 FIB_ROUTE_PATH_FLAG_NONE);
2584 fib_table_entry_path_remove(fib_index,
2585 &bgp_201_pfx,
2586 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002587 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002588 &nh_10_10_10_3,
2589 ~0, // no index provided.
2590 fib_index, // same as route's FIB
2591 1,
2592 FIB_ROUTE_PATH_FLAG_NONE);
2593
2594 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_201_pfx) ==
2595 FIB_NODE_INDEX_INVALID),
2596 "200.200.200.201/32 removed");
2597 FIB_TEST((fib_table_lookup_exact_match(fib_index, &bgp_200_pfx) ==
2598 FIB_NODE_INDEX_INVALID),
2599 "200.200.200.200/32 removed");
2600 FIB_TEST((fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3) ==
2601 FIB_NODE_INDEX_INVALID),
2602 "10.10.10.3/32 removed");
2603
2604 /*
2605 * -3 entries (2*BGP and RR). -2 shared path-list (recursive via 10.10.10.3 &
2606 * 10.10.10.1) and one unshared non-recursive via 10.10.10.3
2607 */
2608 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2609 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002610 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002611 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002612 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002613 fib_entry_pool_size());
2614
2615
2616 /*
2617 * RECURSION LOOPS
2618 * Add 5.5.5.5/32 -> 5.5.5.6/32 -> 5.5.5.7/32 -> 5.5.5.5/32
2619 */
2620 fib_prefix_t pfx_5_5_5_5_s_32 = {
2621 .fp_len = 32,
2622 .fp_proto = FIB_PROTOCOL_IP4,
2623 .fp_addr = {
2624 .ip4.as_u32 = clib_host_to_net_u32(0x05050505),
2625 },
2626 };
2627 fib_prefix_t pfx_5_5_5_6_s_32 = {
2628 .fp_len = 32,
2629 .fp_proto = FIB_PROTOCOL_IP4,
2630 .fp_addr = {
2631 .ip4.as_u32 = clib_host_to_net_u32(0x05050506),
2632 },
2633 };
2634 fib_prefix_t pfx_5_5_5_7_s_32 = {
2635 .fp_len = 32,
2636 .fp_proto = FIB_PROTOCOL_IP4,
2637 .fp_addr = {
2638 .ip4.as_u32 = clib_host_to_net_u32(0x05050507),
2639 },
2640 };
2641
2642 fib_table_entry_path_add(fib_index,
2643 &pfx_5_5_5_5_s_32,
2644 FIB_SOURCE_API,
2645 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002646 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002647 &pfx_5_5_5_6_s_32.fp_addr,
2648 ~0, // no index provided.
2649 fib_index,
2650 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002651 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002652 FIB_ROUTE_PATH_FLAG_NONE);
2653 fib_table_entry_path_add(fib_index,
2654 &pfx_5_5_5_6_s_32,
2655 FIB_SOURCE_API,
2656 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002657 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002658 &pfx_5_5_5_7_s_32.fp_addr,
2659 ~0, // no index provided.
2660 fib_index,
2661 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002662 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002663 FIB_ROUTE_PATH_FLAG_NONE);
2664 fib_table_entry_path_add(fib_index,
2665 &pfx_5_5_5_7_s_32,
2666 FIB_SOURCE_API,
2667 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002668 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002669 &pfx_5_5_5_5_s_32.fp_addr,
2670 ~0, // no index provided.
2671 fib_index,
2672 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002673 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002674 FIB_ROUTE_PATH_FLAG_NONE);
2675 /*
2676 * +3 entries, +3 shared path-list
2677 */
2678 FIB_TEST((4 == fib_path_list_db_size()), "path list DB population:%d",
2679 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002680 FIB_TEST((PNBR+8 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002681 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002682 FIB_TEST((ENBR+10 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002683 fib_entry_pool_size());
2684
2685 /*
2686 * All the entries have only looped paths, so they are all drop
2687 */
2688 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2689 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2690 "LB for 5.5.5.7/32 is via adj for DROP");
2691 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2692 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2693 "LB for 5.5.5.5/32 is via adj for DROP");
2694 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2695 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2696 "LB for 5.5.5.6/32 is via adj for DROP");
2697
2698 /*
2699 * provide 5.5.5.6/32 with alternate path.
2700 * this will allow only 5.5.5.6/32 to forward with this path, the others
2701 * are still drop since the loop is still present.
2702 */
2703 fib_table_entry_path_add(fib_index,
2704 &pfx_5_5_5_6_s_32,
2705 FIB_SOURCE_API,
2706 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002707 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002708 &nh_10_10_10_1,
2709 tm->hw[0]->sw_if_index,
2710 ~0,
2711 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002712 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002713 FIB_ROUTE_PATH_FLAG_NONE);
2714
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002715 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2716 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2717
2718 lb = load_balance_get(dpo1->dpoi_index);
2719 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.6 LB has %d bucket", lb->lb_n_buckets);
2720
2721 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2722 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2723 FIB_TEST((ai_01 == dpo2->dpoi_index),
2724 "5.5.5.6 bucket 0 resolves via 10.10.10.2");
2725
2726 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2727 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2728 "LB for 5.5.5.7/32 is via adj for DROP");
2729 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2730 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2731 "LB for 5.5.5.5/32 is via adj for DROP");
2732
2733 /*
2734 * remove the alternate path for 5.5.5.6/32
2735 * back to all drop
2736 */
2737 fib_table_entry_path_remove(fib_index,
2738 &pfx_5_5_5_6_s_32,
2739 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002740 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002741 &nh_10_10_10_1,
2742 tm->hw[0]->sw_if_index,
2743 ~0,
2744 1,
2745 FIB_ROUTE_PATH_FLAG_NONE);
2746
2747 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2748 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2749 "LB for 5.5.5.7/32 is via adj for DROP");
2750 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2751 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2752 "LB for 5.5.5.5/32 is via adj for DROP");
2753 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2754 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2755 "LB for 5.5.5.6/32 is via adj for DROP");
2756
2757 /*
2758 * break the loop by giving 5.5.5.5/32 a new set of paths
2759 * expect all to forward via this new path.
2760 */
2761 fib_table_entry_update_one_path(fib_index,
2762 &pfx_5_5_5_5_s_32,
2763 FIB_SOURCE_API,
2764 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002765 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002766 &nh_10_10_10_1,
2767 tm->hw[0]->sw_if_index,
2768 ~0, // invalid fib index
2769 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002770 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002771 FIB_ROUTE_PATH_FLAG_NONE);
2772
2773 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2774 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2775 lb = load_balance_get(dpo1->dpoi_index);
2776 FIB_TEST((lb->lb_n_buckets == 1), "5.5.5.5 LB has %d bucket", lb->lb_n_buckets);
2777
2778 dpo2 = load_balance_get_bucket(dpo1->dpoi_index, 0);
2779 FIB_TEST(DPO_ADJACENCY == dpo2->dpoi_type, "type is %d", dpo2->dpoi_type);
2780 FIB_TEST((ai_01 == dpo2->dpoi_index),
2781 "5.5.5.5 bucket 0 resolves via 10.10.10.2");
2782
2783 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_7_s_32);
2784 dpo2 = fib_entry_contribute_ip_forwarding(fei);
2785
2786 lb = load_balance_get(dpo2->dpoi_index);
2787 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2788 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo2->dpoi_index, 0)),
2789 "5.5.5.5.7 via 5.5.5.5");
2790
2791 fei = fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32);
2792 dpo1 = fib_entry_contribute_ip_forwarding(fei);
2793
2794 lb = load_balance_get(dpo1->dpoi_index);
2795 FIB_TEST((lb->lb_n_buckets == 1), "Recursive LB has %d bucket", lb->lb_n_buckets);
2796 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
2797 "5.5.5.5.6 via 5.5.5.7");
2798
2799 /*
2800 * revert back to the loop. so we can remove the prefixes with
2801 * the loop intact
2802 */
2803 fib_table_entry_update_one_path(fib_index,
2804 &pfx_5_5_5_5_s_32,
2805 FIB_SOURCE_API,
2806 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002807 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002808 &pfx_5_5_5_6_s_32.fp_addr,
2809 ~0, // no index provided.
2810 fib_index,
2811 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002812 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002813 FIB_ROUTE_PATH_FLAG_NONE);
2814
2815 fei = fib_table_lookup(fib_index, &pfx_5_5_5_7_s_32);
2816 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2817 "LB for 5.5.5.7/32 is via adj for DROP");
2818 fei = fib_table_lookup(fib_index, &pfx_5_5_5_5_s_32);
2819 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2820 "LB for 5.5.5.5/32 is via adj for DROP");
2821 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2822 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2823 "LB for 5.5.5.6/32 is via adj for DROP");
2824
2825 /*
2826 * remove all the 5.5.5.x/32 prefixes
2827 */
2828 fib_table_entry_path_remove(fib_index,
2829 &pfx_5_5_5_5_s_32,
2830 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002831 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002832 &pfx_5_5_5_6_s_32.fp_addr,
2833 ~0, // no index provided.
2834 fib_index, // same as route's FIB
2835 1,
2836 FIB_ROUTE_PATH_FLAG_NONE);
2837 fib_table_entry_path_remove(fib_index,
2838 &pfx_5_5_5_6_s_32,
2839 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002840 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002841 &pfx_5_5_5_7_s_32.fp_addr,
2842 ~0, // no index provided.
2843 fib_index, // same as route's FIB
2844 1,
2845 FIB_ROUTE_PATH_FLAG_NONE);
2846 fib_table_entry_path_remove(fib_index,
2847 &pfx_5_5_5_7_s_32,
2848 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002849 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002850 &pfx_5_5_5_5_s_32.fp_addr,
2851 ~0, // no index provided.
2852 fib_index, // same as route's FIB
2853 1,
2854 FIB_ROUTE_PATH_FLAG_NONE);
2855 fib_table_entry_path_remove(fib_index,
2856 &pfx_5_5_5_6_s_32,
2857 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002858 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002859 &nh_10_10_10_2,
2860 ~0, // no index provided.
2861 fib_index, // same as route's FIB
2862 1,
2863 FIB_ROUTE_PATH_FLAG_NONE);
2864
2865 /*
2866 * -3 entries, -3 shared path-list
2867 */
2868 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2869 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002870 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002871 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002872 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002873 fib_entry_pool_size());
2874
2875 /*
2876 * Single level loop 5.5.5.5/32 via 5.5.5.5/32
2877 */
2878 fib_table_entry_path_add(fib_index,
2879 &pfx_5_5_5_6_s_32,
2880 FIB_SOURCE_API,
2881 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002882 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002883 &pfx_5_5_5_6_s_32.fp_addr,
2884 ~0, // no index provided.
2885 fib_index,
2886 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002887 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002888 FIB_ROUTE_PATH_FLAG_NONE);
2889 fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
2890 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
2891 "1-level 5.5.5.6/32 loop is via adj for DROP");
2892
2893 fib_table_entry_path_remove(fib_index,
2894 &pfx_5_5_5_6_s_32,
2895 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07002896 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002897 &pfx_5_5_5_6_s_32.fp_addr,
2898 ~0, // no index provided.
2899 fib_index, // same as route's FIB
2900 1,
2901 FIB_ROUTE_PATH_FLAG_NONE);
2902 FIB_TEST(FIB_NODE_INDEX_INVALID ==
2903 fib_table_lookup_exact_match(fib_index, &pfx_5_5_5_6_s_32),
2904 "1-level 5.5.5.6/32 loop is removed");
2905
2906 /*
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002907 * A recursive route whose next-hop is covered by the prefix.
2908 * This would mean the via-fib, which inherits forwarding from its
2909 * cover, thus picks up forwarding from the prfix, which is via the
2910 * via-fib, and we have a loop.
2911 */
2912 fib_prefix_t pfx_23_23_23_0_s_24 = {
2913 .fp_len = 24,
2914 .fp_proto = FIB_PROTOCOL_IP4,
2915 .fp_addr = {
2916 .ip4.as_u32 = clib_host_to_net_u32(0x17171700),
2917 },
2918 };
2919 fib_prefix_t pfx_23_23_23_23_s_32 = {
2920 .fp_len = 32,
2921 .fp_proto = FIB_PROTOCOL_IP4,
2922 .fp_addr = {
2923 .ip4.as_u32 = clib_host_to_net_u32(0x17171717),
2924 },
2925 };
2926 fei = fib_table_entry_path_add(fib_index,
2927 &pfx_23_23_23_0_s_24,
2928 FIB_SOURCE_API,
2929 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002930 DPO_PROTO_IP4,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002931 &pfx_23_23_23_23_s_32.fp_addr,
2932 ~0, // recursive
2933 fib_index,
2934 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002935 NULL,
Neale Ranns3dffb1e2016-11-01 20:38:53 +00002936 FIB_ROUTE_PATH_FLAG_NONE);
2937 dpo = fib_entry_contribute_ip_forwarding(fei);
2938 FIB_TEST(load_balance_is_drop(dpo),
2939 "23.23.23.0/24 via covered is DROP");
2940 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
2941
2942 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002943 * add-remove test. no change.
2944 */
2945 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
2946 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002947 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002948 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00002949 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002950 fib_entry_pool_size());
2951
2952 /*
Neale Ranns08b16482017-05-13 05:52:58 -07002953 * Make the default route recursive via a unknown next-hop. Thus the
2954 * next hop's cover would be the default route
2955 */
2956 fei = fib_table_entry_path_add(fib_index,
2957 &pfx_0_0_0_0_s_0,
2958 FIB_SOURCE_API,
2959 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002960 DPO_PROTO_IP4,
Neale Ranns08b16482017-05-13 05:52:58 -07002961 &pfx_23_23_23_23_s_32.fp_addr,
2962 ~0, // recursive
2963 fib_index,
2964 1,
2965 NULL,
2966 FIB_ROUTE_PATH_FLAG_NONE);
2967 dpo = fib_entry_contribute_ip_forwarding(fei);
2968 FIB_TEST(load_balance_is_drop(dpo),
2969 "0.0.0.0.0/0 via is DROP");
2970 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
2971 "no resolving interface for looped 0.0.0.0/0");
2972
2973 fei = fib_table_lookup_exact_match(fib_index, &pfx_23_23_23_23_s_32);
2974 dpo = fib_entry_contribute_ip_forwarding(fei);
2975 FIB_TEST(load_balance_is_drop(dpo),
2976 "23.23.23.23/32 via is DROP");
2977 FIB_TEST((fib_entry_get_resolving_interface(fei) == ~0),
2978 "no resolving interface for looped 23.23.23.23/32");
2979
2980 fib_table_entry_delete(fib_index, &pfx_0_0_0_0_s_0, FIB_SOURCE_API);
2981
2982 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002983 * A recursive route with recursion constraints.
2984 * 200.200.200.200/32 via 1.1.1.1 is recurse via host constrained
2985 */
2986 fib_table_entry_path_add(fib_index,
2987 &bgp_200_pfx,
2988 FIB_SOURCE_API,
2989 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07002990 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002991 &nh_1_1_1_1,
2992 ~0,
2993 fib_index,
2994 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00002995 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01002996 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
2997
2998 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
2999 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3000
3001 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3002 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3003
3004 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3005 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3006
3007 /*
3008 * save the load-balance. we expect it to be inplace modified
3009 */
3010 lb = load_balance_get(dpo1->dpoi_index);
3011
3012 /*
3013 * add a covering prefix for the via fib that would otherwise serve
3014 * as the resolving route when the host is removed
3015 */
3016 fib_table_entry_path_add(fib_index,
3017 &pfx_1_1_1_0_s_28,
3018 FIB_SOURCE_API,
3019 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003020 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003021 &nh_10_10_10_1,
3022 tm->hw[0]->sw_if_index,
3023 ~0, // invalid fib index
3024 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003025 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003026 FIB_ROUTE_PATH_FLAG_NONE);
3027 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28);
3028 ai = fib_entry_get_adj(fei);
3029 FIB_TEST((ai == ai_01),
3030 "adj for 1.1.1.0/28 is via adj for 1.1.1.1");
3031
3032 /*
3033 * remove the host via FIB - expect the BGP prefix to be drop
3034 */
3035 fib_table_entry_path_remove(fib_index,
3036 &pfx_1_1_1_1_s_32,
3037 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003038 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003039 &nh_10_10_10_1,
3040 tm->hw[0]->sw_if_index,
3041 ~0, // invalid fib index
3042 1,
3043 FIB_ROUTE_PATH_FLAG_NONE);
3044
3045 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3046 "adj for 200.200.200.200/32 is recursive via adj for DROP");
3047
3048 /*
3049 * add the via-entry host reoute back. expect to resolve again
3050 */
3051 fib_table_entry_path_add(fib_index,
3052 &pfx_1_1_1_1_s_32,
3053 FIB_SOURCE_API,
3054 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003055 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003056 &nh_10_10_10_1,
3057 tm->hw[0]->sw_if_index,
3058 ~0, // invalid fib index
3059 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003060 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003061 FIB_ROUTE_PATH_FLAG_NONE);
3062 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo1->dpoi_index, 0)),
3063 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3064
3065 /*
3066 * add another path for the recursive. it will then have 2.
3067 */
3068 fib_prefix_t pfx_1_1_1_3_s_32 = {
3069 .fp_len = 32,
3070 .fp_proto = FIB_PROTOCOL_IP4,
3071 .fp_addr = {
3072 .ip4.as_u32 = clib_host_to_net_u32(0x01010103),
3073 },
3074 };
3075 fib_table_entry_path_add(fib_index,
3076 &pfx_1_1_1_3_s_32,
3077 FIB_SOURCE_API,
3078 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003079 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003080 &nh_10_10_10_2,
3081 tm->hw[0]->sw_if_index,
3082 ~0, // invalid fib index
3083 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003084 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003085 FIB_ROUTE_PATH_FLAG_NONE);
3086
3087 fib_table_entry_path_add(fib_index,
3088 &bgp_200_pfx,
3089 FIB_SOURCE_API,
3090 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003091 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003092 &pfx_1_1_1_3_s_32.fp_addr,
3093 ~0,
3094 fib_index,
3095 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003096 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003097 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3098
Neale Rannsf12a83f2017-04-18 09:09:40 -07003099 /*
3100 * add a bunch load more entries using this path combo so that we get
3101 * an LB-map created.
3102 */
3103#define N_P 128
3104 fib_prefix_t bgp_78s[N_P];
3105 for (ii = 0; ii < N_P; ii++)
3106 {
3107 bgp_78s[ii].fp_len = 32;
3108 bgp_78s[ii].fp_proto = FIB_PROTOCOL_IP4;
3109 bgp_78s[ii].fp_addr.ip4.as_u32 = clib_host_to_net_u32(0x4e000000+ii);
3110
3111
3112 fib_table_entry_path_add(fib_index,
3113 &bgp_78s[ii],
3114 FIB_SOURCE_API,
3115 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003116 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003117 &pfx_1_1_1_3_s_32.fp_addr,
3118 ~0,
3119 fib_index,
3120 1,
3121 NULL,
3122 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3123 fib_table_entry_path_add(fib_index,
3124 &bgp_78s[ii],
3125 FIB_SOURCE_API,
3126 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003127 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003128 &nh_1_1_1_1,
3129 ~0,
3130 fib_index,
3131 1,
3132 NULL,
3133 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3134 }
3135
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003136 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3137 dpo = fib_entry_contribute_ip_forwarding(fei);
3138
3139 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32);
3140 dpo2 = fib_entry_contribute_ip_forwarding(fei);
3141 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket(dpo->dpoi_index, 0)),
3142 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.1");
3143 fei = fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32);
3144 dpo1 = fib_entry_contribute_ip_forwarding(fei);
3145 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket(dpo->dpoi_index, 1)),
3146 "adj for 200.200.200.200/32 is recursive via adj for 1.1.1.3");
3147
3148 /*
3149 * expect the lb-map used by the recursive's load-balance is using both buckets
3150 */
3151 load_balance_map_t *lbm;
3152 index_t lbmi;
3153
3154 lb = load_balance_get(dpo->dpoi_index);
3155 lbmi = lb->lb_map;
3156 load_balance_map_lock(lbmi);
3157 lbm = load_balance_map_get(lbmi);
3158
3159 FIB_TEST(lbm->lbm_buckets[0] == 0,
3160 "LB maps's bucket 0 is %d",
3161 lbm->lbm_buckets[0]);
3162 FIB_TEST(lbm->lbm_buckets[1] == 1,
3163 "LB maps's bucket 1 is %d",
3164 lbm->lbm_buckets[1]);
3165
3166 /*
3167 * withdraw one of the /32 via-entrys.
3168 * that ECMP path will be unresolved and forwarding should continue on the
3169 * other available path. this is an iBGP PIC edge failover.
3170 * Test the forwarding changes without re-fetching the adj from the
3171 * recursive entry. this ensures its the same one that is updated; i.e. an
3172 * inplace-modify.
3173 */
3174 fib_table_entry_path_remove(fib_index,
3175 &pfx_1_1_1_1_s_32,
3176 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003177 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003178 &nh_10_10_10_1,
3179 tm->hw[0]->sw_if_index,
3180 ~0, // invalid fib index
3181 1,
3182 FIB_ROUTE_PATH_FLAG_NONE);
3183
Neale Rannsf12a83f2017-04-18 09:09:40 -07003184 /* suspend so the update walk kicks int */
3185 vlib_process_suspend(vlib_get_main(), 1e-5);
3186
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003187 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3188 FIB_TEST(!dpo_cmp(dpo, fib_entry_contribute_ip_forwarding(fei)),
3189 "post PIC 200.200.200.200/32 was inplace modified");
3190
3191 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 0)),
3192 "post PIC adj for 200.200.200.200/32 is recursive"
3193 " via adj for 1.1.1.3");
3194
3195 /*
3196 * the LB maps that was locked above should have been modified to remove
3197 * the path that was down, and thus its bucket points to a path that is
3198 * still up.
3199 */
3200 FIB_TEST(lbm->lbm_buckets[0] == 1,
3201 "LB maps's bucket 0 is %d",
3202 lbm->lbm_buckets[0]);
3203 FIB_TEST(lbm->lbm_buckets[1] == 1,
3204 "LB maps's bucket 1 is %d",
3205 lbm->lbm_buckets[1]);
3206
Neale Ranns994dab42017-04-18 12:56:45 -07003207 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003208
3209 /*
3210 * add it back. again
3211 */
3212 fib_table_entry_path_add(fib_index,
3213 &pfx_1_1_1_1_s_32,
3214 FIB_SOURCE_API,
3215 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003216 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003217 &nh_10_10_10_1,
3218 tm->hw[0]->sw_if_index,
3219 ~0, // invalid fib index
3220 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003221 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003222 FIB_ROUTE_PATH_FLAG_NONE);
3223
Neale Rannsf12a83f2017-04-18 09:09:40 -07003224 /* suspend so the update walk kicks in */
3225 vlib_process_suspend(vlib_get_main(), 1e-5);
3226
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003227 FIB_TEST(!dpo_cmp(dpo2, load_balance_get_bucket_i(lb, 0)),
3228 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3229 "via adj for 1.1.1.1");
3230 FIB_TEST(!dpo_cmp(dpo1, load_balance_get_bucket_i(lb, 1)),
3231 "post PIC recovery adj for 200.200.200.200/32 is recursive "
3232 "via adj for 1.1.1.3");
3233
3234 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3235 dpo = fib_entry_contribute_ip_forwarding(fei);
3236 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3237 "post PIC 200.200.200.200/32 was inplace modified");
3238
3239 /*
3240 * add a 3rd path. this makes the LB 16 buckets.
3241 */
3242 fib_table_entry_path_add(fib_index,
3243 &bgp_200_pfx,
3244 FIB_SOURCE_API,
3245 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003246 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003247 &pfx_1_1_1_2_s_32.fp_addr,
3248 ~0,
3249 fib_index,
3250 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003251 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003252 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003253 for (ii = 0; ii < N_P; ii++)
3254 {
3255 fib_table_entry_path_add(fib_index,
3256 &bgp_78s[ii],
3257 FIB_SOURCE_API,
3258 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003259 DPO_PROTO_IP4,
Neale Rannsf12a83f2017-04-18 09:09:40 -07003260 &pfx_1_1_1_2_s_32.fp_addr,
3261 ~0,
3262 fib_index,
3263 1,
3264 NULL,
3265 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3266 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003267
3268 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3269 dpo = fib_entry_contribute_ip_forwarding(fei);
3270 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3271 "200.200.200.200/32 was inplace modified for 3rd path");
3272 FIB_TEST(16 == lb->lb_n_buckets,
3273 "200.200.200.200/32 was inplace modified for 3rd path to 16 buckets");
3274
3275 lbmi = lb->lb_map;
3276 load_balance_map_lock(lbmi);
3277 lbm = load_balance_map_get(lbmi);
3278
3279 for (ii = 0; ii < 16; ii++)
3280 {
3281 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3282 "LB Map for 200.200.200.200/32 at %d is %d",
3283 ii, lbm->lbm_buckets[ii]);
3284 }
3285
3286 /*
3287 * trigger PIC by removing the first via-entry
3288 * the first 6 buckets of the map should map to the next 6
3289 */
3290 fib_table_entry_path_remove(fib_index,
3291 &pfx_1_1_1_1_s_32,
3292 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003293 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003294 &nh_10_10_10_1,
3295 tm->hw[0]->sw_if_index,
3296 ~0,
3297 1,
3298 FIB_ROUTE_PATH_FLAG_NONE);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003299 /* suspend so the update walk kicks int */
3300 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003301
3302 fei = fib_table_lookup_exact_match(fib_index, &bgp_200_pfx);
3303 dpo = fib_entry_contribute_ip_forwarding(fei);
3304 FIB_TEST(lb == load_balance_get(dpo->dpoi_index),
3305 "200.200.200.200/32 was inplace modified for 3rd path");
3306 FIB_TEST(2 == lb->lb_n_buckets,
3307 "200.200.200.200/32 was inplace modified for 3rd path remove to 2 buckets");
3308
3309 for (ii = 0; ii < 6; ii++)
3310 {
3311 FIB_TEST(lbm->lbm_buckets[ii] == ii+6,
3312 "LB Map for 200.200.200.200/32 at %d is %d",
3313 ii, lbm->lbm_buckets[ii]);
3314 }
3315 for (ii = 6; ii < 16; ii++)
3316 {
3317 FIB_TEST(lbm->lbm_buckets[ii] == ii,
3318 "LB Map for 200.200.200.200/32 at %d is %d",
3319 ii, lbm->lbm_buckets[ii]);
3320 }
Neale Ranns994dab42017-04-18 12:56:45 -07003321 load_balance_map_unlock(lbmi);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003322
3323 /*
3324 * tidy up
3325 */
3326 fib_table_entry_path_add(fib_index,
3327 &pfx_1_1_1_1_s_32,
3328 FIB_SOURCE_API,
3329 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003330 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003331 &nh_10_10_10_1,
3332 tm->hw[0]->sw_if_index,
3333 ~0,
3334 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003335 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003336 FIB_ROUTE_PATH_FLAG_NONE);
3337
Neale Rannsf12a83f2017-04-18 09:09:40 -07003338 for (ii = 0; ii < N_P; ii++)
3339 {
3340 fib_table_entry_delete(fib_index,
3341 &bgp_78s[ii],
3342 FIB_SOURCE_API);
3343 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3344 fib_table_lookup_exact_match(fib_index, &bgp_78s[ii])),
3345 "%U removed",
3346 format_fib_prefix, &bgp_78s[ii]);
3347 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003348 fib_table_entry_path_remove(fib_index,
3349 &bgp_200_pfx,
3350 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003351 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003352 &pfx_1_1_1_2_s_32.fp_addr,
3353 ~0,
3354 fib_index,
3355 1,
3356 MPLS_LABEL_INVALID);
3357 fib_table_entry_path_remove(fib_index,
3358 &bgp_200_pfx,
3359 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003360 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003361 &nh_1_1_1_1,
3362 ~0,
3363 fib_index,
3364 1,
3365 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3366 fib_table_entry_path_remove(fib_index,
3367 &bgp_200_pfx,
3368 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003369 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003370 &pfx_1_1_1_3_s_32.fp_addr,
3371 ~0,
3372 fib_index,
3373 1,
3374 FIB_ROUTE_PATH_RESOLVE_VIA_HOST);
3375 fib_table_entry_delete(fib_index,
3376 &pfx_1_1_1_3_s_32,
3377 FIB_SOURCE_API);
3378 fib_table_entry_delete(fib_index,
3379 &pfx_1_1_1_0_s_28,
3380 FIB_SOURCE_API);
Neale Rannsf12a83f2017-04-18 09:09:40 -07003381 /* suspend so the update walk kicks int */
3382 vlib_process_suspend(vlib_get_main(), 1e-5);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003383 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3384 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_0_s_28)),
3385 "1.1.1.1/28 removed");
3386 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3387 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_3_s_32)),
3388 "1.1.1.3/32 removed");
3389 FIB_TEST((FIB_NODE_INDEX_INVALID ==
3390 fib_table_lookup_exact_match(fib_index, &bgp_200_pfx)),
3391 "200.200.200.200/32 removed");
3392
3393 /*
3394 * add-remove test. no change.
3395 */
3396 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3397 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003398 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003399 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003400 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003401 fib_entry_pool_size());
3402
3403 /*
3404 * A route whose paths are built up iteratively and then removed
3405 * all at once
3406 */
3407 fib_prefix_t pfx_4_4_4_4_s_32 = {
3408 .fp_len = 32,
3409 .fp_proto = FIB_PROTOCOL_IP4,
3410 .fp_addr = {
3411 /* 4.4.4.4/32 */
3412 .ip4.as_u32 = clib_host_to_net_u32(0x04040404),
3413 },
3414 };
3415
3416 fib_table_entry_path_add(fib_index,
3417 &pfx_4_4_4_4_s_32,
3418 FIB_SOURCE_API,
3419 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003420 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003421 &nh_10_10_10_1,
3422 tm->hw[0]->sw_if_index,
3423 ~0,
3424 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003425 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003426 FIB_ROUTE_PATH_FLAG_NONE);
3427 fib_table_entry_path_add(fib_index,
3428 &pfx_4_4_4_4_s_32,
3429 FIB_SOURCE_API,
3430 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003431 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003432 &nh_10_10_10_2,
3433 tm->hw[0]->sw_if_index,
3434 ~0,
3435 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003436 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003437 FIB_ROUTE_PATH_FLAG_NONE);
3438 fib_table_entry_path_add(fib_index,
3439 &pfx_4_4_4_4_s_32,
3440 FIB_SOURCE_API,
3441 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003442 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003443 &nh_10_10_10_3,
3444 tm->hw[0]->sw_if_index,
3445 ~0,
3446 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003447 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003448 FIB_ROUTE_PATH_FLAG_NONE);
3449 FIB_TEST(FIB_NODE_INDEX_INVALID !=
3450 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3451 "4.4.4.4/32 present");
3452
3453 fib_table_entry_delete(fib_index,
3454 &pfx_4_4_4_4_s_32,
3455 FIB_SOURCE_API);
3456 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3457 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3458 "4.4.4.4/32 removed");
3459
3460 /*
3461 * add-remove test. no change.
3462 */
3463 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3464 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003465 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003466 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003467 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003468 fib_entry_pool_size());
3469
3470 /*
3471 * A route with multiple paths at once
3472 */
3473 fib_route_path_t *r_paths = NULL;
3474
3475 for (ii = 0; ii < 4; ii++)
3476 {
3477 fib_route_path_t r_path = {
Neale Rannsda78f952017-05-24 09:15:43 -07003478 .frp_proto = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003479 .frp_addr = {
3480 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02 + ii),
3481 },
3482 .frp_sw_if_index = tm->hw[0]->sw_if_index,
3483 .frp_weight = 1,
3484 .frp_fib_index = ~0,
3485 };
3486 vec_add1(r_paths, r_path);
3487 }
3488
3489 fib_table_entry_update(fib_index,
3490 &pfx_4_4_4_4_s_32,
3491 FIB_SOURCE_API,
3492 FIB_ENTRY_FLAG_NONE,
3493 r_paths);
3494
3495 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3496 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3497 dpo = fib_entry_contribute_ip_forwarding(fei);
3498
3499 lb = load_balance_get(dpo->dpoi_index);
3500 FIB_TEST((lb->lb_n_buckets == 4), "4.4.4.4/32 lb over %d paths", lb->lb_n_buckets);
3501
3502 fib_table_entry_delete(fib_index,
3503 &pfx_4_4_4_4_s_32,
3504 FIB_SOURCE_API);
3505 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3506 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3507 "4.4.4.4/32 removed");
3508 vec_free(r_paths);
3509
3510 /*
3511 * add-remove test. no change.
3512 */
3513 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3514 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003515 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003516 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003517 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003518 fib_entry_pool_size());
3519
3520 /*
3521 * A route deag route
3522 */
3523 fib_table_entry_path_add(fib_index,
3524 &pfx_4_4_4_4_s_32,
3525 FIB_SOURCE_API,
3526 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003527 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003528 &zero_addr,
3529 ~0,
3530 fib_index,
3531 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003532 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003533 FIB_ROUTE_PATH_FLAG_NONE);
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
3538 dpo = fib_entry_contribute_ip_forwarding(fei);
3539 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3540 lookup_dpo_t *lkd = lookup_dpo_get(dpo->dpoi_index);
3541
3542 FIB_TEST((fib_index == lkd->lkd_fib_index),
3543 "4.4.4.4/32 is deag in %d %U",
3544 lkd->lkd_fib_index,
3545 format_dpo_id, dpo, 0);
Neale Ranns054c03a2017-10-13 05:15:07 -07003546 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
3547 "4.4.4.4/32 is source deag in %d %U",
3548 lkd->lkd_input,
3549 format_dpo_id, dpo, 0);
3550
3551 fib_table_entry_delete(fib_index,
3552 &pfx_4_4_4_4_s_32,
3553 FIB_SOURCE_API);
3554 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3555 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3556 "4.4.4.4/32 removed");
3557 vec_free(r_paths);
3558
3559 /*
3560 * A route deag route in a source lookup table
3561 */
3562 fib_table_entry_path_add(fib_index,
3563 &pfx_4_4_4_4_s_32,
3564 FIB_SOURCE_API,
3565 FIB_ENTRY_FLAG_NONE,
3566 DPO_PROTO_IP4,
3567 &zero_addr,
3568 ~0,
3569 fib_index,
3570 1,
3571 NULL,
3572 FIB_ROUTE_PATH_SOURCE_LOOKUP);
3573
3574 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32);
3575 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.4.4.4/32 present");
3576
3577 dpo = fib_entry_contribute_ip_forwarding(fei);
3578 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
3579 lkd = lookup_dpo_get(dpo->dpoi_index);
3580
3581 FIB_TEST((fib_index == lkd->lkd_fib_index),
3582 "4.4.4.4/32 is deag in %d %U",
3583 lkd->lkd_fib_index,
3584 format_dpo_id, dpo, 0);
3585 FIB_TEST((LOOKUP_INPUT_SRC_ADDR == lkd->lkd_input),
3586 "4.4.4.4/32 is source deag in %d %U",
3587 lkd->lkd_input,
3588 format_dpo_id, dpo, 0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003589
3590 fib_table_entry_delete(fib_index,
3591 &pfx_4_4_4_4_s_32,
3592 FIB_SOURCE_API);
3593 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3594 fib_table_lookup_exact_match(fib_index, &pfx_4_4_4_4_s_32),
3595 "4.4.4.4/32 removed");
3596 vec_free(r_paths);
3597
3598 /*
3599 * add-remove test. no change.
3600 */
3601 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3602 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003603 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003604 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003605 FIB_TEST((ENBR+7 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003606 fib_entry_pool_size());
3607
3608 /*
Neale Rannsbcc889c2016-11-03 14:15:28 -07003609 * Duplicate paths:
3610 * add a recursive with duplicate paths. Expect the duplicate to be ignored.
3611 */
3612 fib_prefix_t pfx_34_1_1_1_s_32 = {
3613 .fp_len = 32,
3614 .fp_proto = FIB_PROTOCOL_IP4,
3615 .fp_addr = {
3616 .ip4.as_u32 = clib_host_to_net_u32(0x22010101),
3617 },
3618 };
3619 fib_prefix_t pfx_34_34_1_1_s_32 = {
3620 .fp_len = 32,
3621 .fp_proto = FIB_PROTOCOL_IP4,
3622 .fp_addr = {
3623 .ip4.as_u32 = clib_host_to_net_u32(0x22220101),
3624 },
3625 };
3626 fei = fib_table_entry_path_add(fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -07003627 &pfx_34_34_1_1_s_32,
3628 FIB_SOURCE_API,
3629 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003630 DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07003631 &nh_10_10_10_1,
3632 tm->hw[0]->sw_if_index,
3633 0,
3634 1,
3635 NULL,
3636 FIB_ROUTE_PATH_FLAG_NONE);
3637 fei = fib_table_entry_path_add(fib_index,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003638 &pfx_34_1_1_1_s_32,
3639 FIB_SOURCE_API,
3640 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003641 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003642 &pfx_34_34_1_1_s_32.fp_addr,
3643 ~0,
3644 fib_index,
3645 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003646 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003647 FIB_ROUTE_PATH_FLAG_NONE);
3648 fei = fib_table_entry_path_add(fib_index,
3649 &pfx_34_1_1_1_s_32,
3650 FIB_SOURCE_API,
3651 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003652 DPO_PROTO_IP4,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003653 &pfx_34_34_1_1_s_32.fp_addr,
3654 ~0,
3655 fib_index,
3656 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003657 NULL,
Neale Rannsbcc889c2016-11-03 14:15:28 -07003658 FIB_ROUTE_PATH_FLAG_NONE);
3659 FIB_TEST_REC_FORW(&pfx_34_1_1_1_s_32, &pfx_34_34_1_1_s_32, 0);
3660 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
Neale Ranns57b58602017-07-15 07:37:25 -07003661 fib_table_entry_delete(fib_index,
3662 &pfx_34_34_1_1_s_32,
3663 FIB_SOURCE_API);
Neale Rannsbcc889c2016-11-03 14:15:28 -07003664
3665 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003666 * CLEANUP
3667 * remove: 1.1.1.2/32, 1.1.2.0/24 and 1.1.1.1/32
3668 * all of which are via 10.10.10.1, Itf1
3669 */
3670 fib_table_entry_path_remove(fib_index,
3671 &pfx_1_1_1_2_s_32,
3672 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003673 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003674 &nh_10_10_10_1,
3675 tm->hw[0]->sw_if_index,
3676 ~0,
3677 1,
3678 FIB_ROUTE_PATH_FLAG_NONE);
3679 fib_table_entry_path_remove(fib_index,
3680 &pfx_1_1_1_1_s_32,
3681 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003682 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003683 &nh_10_10_10_1,
3684 tm->hw[0]->sw_if_index,
3685 ~0,
3686 1,
3687 FIB_ROUTE_PATH_FLAG_NONE);
3688 fib_table_entry_path_remove(fib_index,
3689 &pfx_1_1_2_0_s_24,
3690 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07003691 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003692 &nh_10_10_10_1,
3693 tm->hw[0]->sw_if_index,
3694 ~0,
3695 1,
3696 FIB_ROUTE_PATH_FLAG_NONE);
3697
3698 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3699 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_1_s_32),
3700 "1.1.1.1/32 removed");
3701 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3702 fib_table_lookup_exact_match(fib_index, &pfx_1_1_1_2_s_32),
3703 "1.1.1.2/32 removed");
3704 FIB_TEST(FIB_NODE_INDEX_INVALID ==
3705 fib_table_lookup_exact_match(fib_index, &pfx_1_1_2_0_s_24),
3706 "1.1.2.0/24 removed");
3707
3708 /*
3709 * -3 entries and -1 shared path-list
3710 */
3711 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3712 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003713 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003714 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003715 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003716 fib_entry_pool_size());
3717
3718 /*
3719 * An attached-host route. Expect to link to the incomplete adj
3720 */
3721 fib_prefix_t pfx_4_1_1_1_s_32 = {
3722 .fp_len = 32,
3723 .fp_proto = FIB_PROTOCOL_IP4,
3724 .fp_addr = {
3725 /* 4.1.1.1/32 */
3726 .ip4.as_u32 = clib_host_to_net_u32(0x04010101),
3727 },
3728 };
3729 fib_table_entry_path_add(fib_index,
3730 &pfx_4_1_1_1_s_32,
3731 FIB_SOURCE_API,
3732 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003733 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003734 &zero_addr,
3735 tm->hw[0]->sw_if_index,
3736 fib_index,
3737 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003738 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003739 FIB_ROUTE_PATH_FLAG_NONE);
3740
3741 fei = fib_table_lookup_exact_match(fib_index, &pfx_4_1_1_1_s_32);
3742 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "4.1.1.1/32 present");
3743 ai = fib_entry_get_adj(fei);
3744
3745 ai2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01003746 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003747 &pfx_4_1_1_1_s_32.fp_addr,
3748 tm->hw[0]->sw_if_index);
3749 FIB_TEST((ai == ai2), "Attached-host link to incomplete ADJ");
3750 adj_unlock(ai2);
3751
3752 /*
3753 * +1 entry and +1 shared path-list
3754 */
3755 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
3756 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003757 FIB_TEST((PNBR+5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003758 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003759 FIB_TEST((ENBR+5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003760 fib_entry_pool_size());
3761
3762 fib_table_entry_delete(fib_index,
3763 &pfx_4_1_1_1_s_32,
3764 FIB_SOURCE_API);
3765
3766 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
3767 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003768 FIB_TEST((PNBR+4 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003769 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00003770 FIB_TEST((ENBR+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003771 fib_entry_pool_size());
3772
3773 /*
3774 * add a v6 prefix via v4 next-hops
3775 */
3776 fib_prefix_t pfx_2001_s_64 = {
3777 .fp_len = 64,
3778 .fp_proto = FIB_PROTOCOL_IP6,
3779 .fp_addr = {
3780 .ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
3781 },
3782 };
3783 fei = fib_table_entry_path_add(0, //default v6 table
3784 &pfx_2001_s_64,
3785 FIB_SOURCE_API,
3786 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003787 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003788 &nh_10_10_10_1,
3789 tm->hw[0]->sw_if_index,
3790 fib_index,
3791 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00003792 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003793 FIB_ROUTE_PATH_FLAG_NONE);
3794
3795 fei = fib_table_lookup_exact_match(0, &pfx_2001_s_64);
3796 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "2001::/64 present");
3797 ai = fib_entry_get_adj(fei);
3798 adj = adj_get(ai);
3799 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
3800 "2001::/64 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01003801 FIB_TEST((adj->ia_link == VNET_LINK_IP6),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003802 "2001::/64 is link type v6");
3803 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP4),
3804 "2001::/64 ADJ-adj is NH proto v4");
3805 fib_table_entry_delete(0, &pfx_2001_s_64, FIB_SOURCE_API);
3806
Neale Ranns3ee44042016-10-03 13:05:48 +01003807 /*
3808 * add a uRPF exempt prefix:
3809 * test:
3810 * - it's forwarding is drop
3811 * - it's uRPF list is not empty
3812 * - the uRPF list for the default route (it's cover) is empty
3813 */
3814 fei = fib_table_entry_special_add(fib_index,
3815 &pfx_4_1_1_1_s_32,
3816 FIB_SOURCE_URPF_EXEMPT,
Neale Rannsa0558302017-04-13 00:44:52 -07003817 FIB_ENTRY_FLAG_DROP);
Neale Ranns3ee44042016-10-03 13:05:48 +01003818 dpo = fib_entry_contribute_ip_forwarding(fei);
3819 FIB_TEST(load_balance_is_drop(dpo),
3820 "uRPF exempt 4.1.1.1/32 DROP");
3821 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 1, 0),
3822 "uRPF list for exempt prefix has itf index 0");
3823 fei = fib_table_lookup_exact_match(fib_index, &pfx_0_0_0_0_s_0);
3824 FIB_TEST(fib_test_urpf_is_equal(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, 0),
3825 "uRPF list for 0.0.0.0/0 empty");
3826
3827 fib_table_entry_delete(fib_index, &pfx_4_1_1_1_s_32, FIB_SOURCE_URPF_EXEMPT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01003828
3829 /*
Neale Ranns3983ac22017-03-10 11:53:27 -08003830 * An adj-fib that fails the refinement criteria - no connected cover
3831 */
3832 fib_prefix_t pfx_12_10_10_2_s_32 = {
3833 .fp_len = 32,
3834 .fp_proto = FIB_PROTOCOL_IP4,
3835 .fp_addr = {
3836 /* 12.10.10.2 */
3837 .ip4.as_u32 = clib_host_to_net_u32(0x0c0a0a02),
3838 },
3839 };
3840
Neale Ranns81424992017-05-18 03:03:22 -07003841 fib_table_entry_path_add(fib_index,
3842 &pfx_12_10_10_2_s_32,
3843 FIB_SOURCE_ADJ,
3844 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003845 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003846 &pfx_12_10_10_2_s_32.fp_addr,
3847 tm->hw[0]->sw_if_index,
3848 ~0, // invalid fib index
3849 1,
3850 NULL,
3851 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003852
3853 fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
3854 dpo = fib_entry_contribute_ip_forwarding(fei);
3855 FIB_TEST(!dpo_id_is_valid(dpo),
3856 "no connected cover adj-fib fails refinement");
3857
3858 fib_table_entry_delete(fib_index,
3859 &pfx_12_10_10_2_s_32,
3860 FIB_SOURCE_ADJ);
3861
3862 /*
3863 * An adj-fib that fails the refinement criteria - cover is connected
3864 * but on a different interface
3865 */
3866 fib_prefix_t pfx_10_10_10_127_s_32 = {
3867 .fp_len = 32,
3868 .fp_proto = FIB_PROTOCOL_IP4,
3869 .fp_addr = {
3870 /* 10.10.10.127 */
3871 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a7f),
3872 },
3873 };
3874
Neale Ranns81424992017-05-18 03:03:22 -07003875 fib_table_entry_path_add(fib_index,
3876 &pfx_10_10_10_127_s_32,
3877 FIB_SOURCE_ADJ,
3878 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07003879 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003880 &pfx_10_10_10_127_s_32.fp_addr,
3881 tm->hw[1]->sw_if_index,
3882 ~0, // invalid fib index
3883 1,
3884 NULL,
3885 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns3983ac22017-03-10 11:53:27 -08003886
3887 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
3888 dpo = fib_entry_contribute_ip_forwarding(fei);
3889 FIB_TEST(!dpo_id_is_valid(dpo),
3890 "wrong interface adj-fib fails refinement");
3891
3892 fib_table_entry_delete(fib_index,
3893 &pfx_10_10_10_127_s_32,
3894 FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07003895
3896 /*
3897 * add a second path to an adj-fib
3898 * this is a sumiluation of another ARP entry created
3899 * on an interface on which the connected prefi does not exist.
3900 * The second path fails refinement. Expect to forward through the
3901 * first.
3902 */
3903 fib_prefix_t pfx_10_10_10_3_s_32 = {
3904 .fp_len = 32,
3905 .fp_proto = FIB_PROTOCOL_IP4,
3906 .fp_addr = {
3907 /* 10.10.10.3 */
3908 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
3909 },
3910 };
3911
3912 ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
3913 VNET_LINK_IP4,
3914 &nh_10_10_10_3,
3915 tm->hw[0]->sw_if_index);
3916
3917 fib_test_lb_bucket_t ip_o_10_10_10_3 = {
3918 .type = FT_LB_ADJ,
3919 .adj = {
3920 .adj = ai_03,
3921 },
3922 };
3923 fei = fib_table_entry_path_add(fib_index,
3924 &pfx_10_10_10_3_s_32,
3925 FIB_SOURCE_ADJ,
3926 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003927 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003928 &nh_10_10_10_3,
3929 tm->hw[0]->sw_if_index,
3930 fib_index,
3931 1,
3932 NULL,
3933 FIB_ROUTE_PATH_FLAG_NONE);
3934 fei = fib_table_entry_path_add(fib_index,
3935 &pfx_10_10_10_3_s_32,
3936 FIB_SOURCE_ADJ,
3937 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003938 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003939 &nh_12_12_12_12,
3940 tm->hw[1]->sw_if_index,
3941 fib_index,
3942 1,
3943 NULL,
3944 FIB_ROUTE_PATH_FLAG_NONE);
3945 FIB_TEST(fib_test_validate_entry(fei,
3946 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3947 1,
3948 &ip_o_10_10_10_3),
3949 "10.10.10.3 via 10.10.10.3/Eth0 only");
3950
3951 /*
3952 * remove the path that refines the cover, should go unresolved
3953 */
3954 fib_table_entry_path_remove(fib_index,
3955 &pfx_10_10_10_3_s_32,
3956 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07003957 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003958 &nh_10_10_10_3,
3959 tm->hw[0]->sw_if_index,
3960 fib_index,
3961 1,
3962 FIB_ROUTE_PATH_FLAG_NONE);
3963 dpo = fib_entry_contribute_ip_forwarding(fei);
3964 FIB_TEST(!dpo_id_is_valid(dpo),
3965 "wrong interface adj-fib fails refinement");
3966
3967 /*
3968 * add back the path that refines the cover
3969 */
3970 fei = fib_table_entry_path_add(fib_index,
3971 &pfx_10_10_10_3_s_32,
3972 FIB_SOURCE_ADJ,
3973 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07003974 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003975 &nh_10_10_10_3,
3976 tm->hw[0]->sw_if_index,
3977 fib_index,
3978 1,
3979 NULL,
3980 FIB_ROUTE_PATH_FLAG_NONE);
3981 FIB_TEST(fib_test_validate_entry(fei,
3982 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
3983 1,
3984 &ip_o_10_10_10_3),
3985 "10.10.10.3 via 10.10.10.3/Eth0 only");
3986
3987 /*
3988 * remove the path that does not refine the cover
3989 */
3990 fib_table_entry_path_remove(fib_index,
3991 &pfx_10_10_10_3_s_32,
3992 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07003993 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07003994 &nh_12_12_12_12,
3995 tm->hw[1]->sw_if_index,
3996 fib_index,
3997 1,
3998 FIB_ROUTE_PATH_FLAG_NONE);
3999 FIB_TEST(fib_test_validate_entry(fei,
4000 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4001 1,
4002 &ip_o_10_10_10_3),
4003 "10.10.10.3 via 10.10.10.3/Eth0 only");
4004
4005 /*
4006 * remove the path that does refine, it's the last path, so
4007 * the entry should be gone
4008 */
4009 fib_table_entry_path_remove(fib_index,
4010 &pfx_10_10_10_3_s_32,
4011 FIB_SOURCE_ADJ,
Neale Rannsda78f952017-05-24 09:15:43 -07004012 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07004013 &nh_10_10_10_3,
4014 tm->hw[0]->sw_if_index,
4015 fib_index,
4016 1,
4017 FIB_ROUTE_PATH_FLAG_NONE);
4018 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
4019 FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
4020
4021 adj_unlock(ai_03);
4022
Neale Ranns227038a2017-04-21 01:07:59 -07004023 /*
4024 * change the table's flow-hash config - expect the update to propagete to
4025 * the entries' load-balance objects
4026 */
4027 flow_hash_config_t old_hash_config, new_hash_config;
4028
4029 old_hash_config = fib_table_get_flow_hash_config(fib_index,
4030 FIB_PROTOCOL_IP4);
4031 new_hash_config = (IP_FLOW_HASH_SRC_ADDR |
4032 IP_FLOW_HASH_DST_ADDR);
4033
4034 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
4035 dpo = fib_entry_contribute_ip_forwarding(fei);
4036 lb = load_balance_get(dpo->dpoi_index);
4037 FIB_TEST((lb->lb_hash_config == old_hash_config),
4038 "Table and LB hash config match: %U",
4039 format_ip_flow_hash_config, lb->lb_hash_config);
4040
4041 fib_table_set_flow_hash_config(fib_index, FIB_PROTOCOL_IP4, new_hash_config);
4042
4043 FIB_TEST((lb->lb_hash_config == new_hash_config),
4044 "Table and LB newhash config match: %U",
4045 format_ip_flow_hash_config, lb->lb_hash_config);
Neale Ranns3983ac22017-03-10 11:53:27 -08004046
4047 /*
Neale Ranns6f631152017-10-03 08:20:21 -07004048 * A route via an L2 Bridge
4049 */
4050 fei = fib_table_entry_path_add(fib_index,
4051 &pfx_10_10_10_3_s_32,
4052 FIB_SOURCE_API,
4053 FIB_ENTRY_FLAG_NONE,
4054 DPO_PROTO_ETHERNET,
4055 &zero_addr,
4056 tm->hw[0]->sw_if_index,
4057 ~0,
4058 1,
4059 NULL,
4060 FIB_ROUTE_PATH_FLAG_NONE);
4061 dpo_id_t l2_dpo = DPO_INVALID;
4062 l2_bridge_dpo_add_or_lock(tm->hw[0]->sw_if_index, &l2_dpo);
4063 fib_test_lb_bucket_t ip_o_l2 = {
4064 .type = FT_LB_L2,
4065 .adj = {
4066 .adj = l2_dpo.dpoi_index,
4067 },
4068 };
4069
4070 FIB_TEST(fib_test_validate_entry(fei,
4071 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
4072 1,
4073 &ip_o_l2),
4074 "10.10.10.3 via L2 on Eth0");
4075 fib_table_entry_path_remove(fib_index,
4076 &pfx_10_10_10_3_s_32,
4077 FIB_SOURCE_API,
4078 DPO_PROTO_ETHERNET,
4079 &zero_addr,
4080 tm->hw[0]->sw_if_index,
4081 fib_index,
4082 1,
4083 FIB_ROUTE_PATH_FLAG_NONE);
4084 dpo_reset(&l2_dpo);
4085
4086 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004087 * CLEANUP
4088 * remove adj-fibs:
4089 */
4090 fib_table_entry_delete(fib_index,
4091 &pfx_10_10_10_1_s_32,
4092 FIB_SOURCE_ADJ);
4093 fib_table_entry_delete(fib_index,
4094 &pfx_10_10_10_2_s_32,
4095 FIB_SOURCE_ADJ);
4096 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4097 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32),
4098 "10.10.10.1/32 adj-fib removed");
4099 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4100 fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32),
4101 "10.10.10.2/32 adj-fib removed");
4102
4103 /*
4104 * -2 entries and -2 non-shared path-list
4105 */
4106 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4107 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004108 FIB_TEST((PNBR+2 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004109 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004110 FIB_TEST((ENBR+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004111 fib_entry_pool_size());
4112
4113 /*
Neale Ranns3ee44042016-10-03 13:05:48 +01004114 * unlock the adjacencies for which this test provided a rewrite.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004115 * These are the last locks on these adjs. they should thus go away.
4116 */
4117 adj_unlock(ai_02);
4118 adj_unlock(ai_01);
Neale Ranns3ee44042016-10-03 13:05:48 +01004119 adj_unlock(ai_12_12_12_12);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004120
4121 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4122 adj_nbr_db_size());
Neale Ranns3dffb1e2016-11-01 20:38:53 +00004123
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004124 /*
4125 * CLEANUP
4126 * remove the interface prefixes
4127 */
4128 local_pfx.fp_len = 32;
4129 fib_table_entry_special_remove(fib_index, &local_pfx,
4130 FIB_SOURCE_INTERFACE);
4131 fei = fib_table_lookup(fib_index, &local_pfx);
4132
4133 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4134 fib_table_lookup_exact_match(fib_index, &local_pfx),
4135 "10.10.10.10/32 adj-fib removed");
4136
4137 local_pfx.fp_len = 24;
4138 fib_table_entry_delete(fib_index, &local_pfx,
4139 FIB_SOURCE_INTERFACE);
4140
4141 FIB_TEST(FIB_NODE_INDEX_INVALID ==
4142 fib_table_lookup_exact_match(fib_index, &local_pfx),
4143 "10.10.10.10/24 adj-fib removed");
4144
4145 /*
4146 * -2 entries and -2 non-shared path-list
4147 */
Neale Rannsf12a83f2017-04-18 09:09:40 -07004148 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004149 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004150 FIB_TEST((PNBR == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004151 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004152 FIB_TEST((ENBR == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004153 fib_entry_pool_size());
4154
4155 /*
4156 * Last but not least, remove the VRF
4157 */
4158 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4159 FIB_PROTOCOL_IP4,
4160 FIB_SOURCE_API)),
4161 "NO API Source'd prefixes");
4162 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4163 FIB_PROTOCOL_IP4,
4164 FIB_SOURCE_RR)),
4165 "NO RR Source'd prefixes");
4166 FIB_TEST((0 == fib_table_get_num_entries(fib_index,
4167 FIB_PROTOCOL_IP4,
4168 FIB_SOURCE_INTERFACE)),
4169 "NO INterface Source'd prefixes");
4170
Neale Ranns15002542017-09-10 04:39:11 -07004171 fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004172
4173 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4174 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004175 FIB_TEST((PNBR-5 == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004176 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004177 FIB_TEST((ENBR-5 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004178 fib_entry_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004179 FIB_TEST((ENBR-5 == pool_elts(fib_urpf_list_pool)), "uRPF pool size is %d",
Neale Ranns3ee44042016-10-03 13:05:48 +01004180 pool_elts(fib_urpf_list_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004181 FIB_TEST((0 == pool_elts(load_balance_map_pool)), "LB-map pool size is %d",
Neale Rannsf12a83f2017-04-18 09:09:40 -07004182 pool_elts(load_balance_map_pool));
Neale Ranns994dab42017-04-18 12:56:45 -07004183 FIB_TEST((lb_count == pool_elts(load_balance_pool)), "LB pool size is %d",
4184 pool_elts(load_balance_pool));
Neale Ranns6f631152017-10-03 08:20:21 -07004185 FIB_TEST((0 == pool_elts(l2_bridge_dpo_pool)), "L2 DPO pool size is %d",
4186 pool_elts(l2_bridge_dpo_pool));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004187
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004188 return 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004189}
4190
Neale Ranns0ebe8d72016-12-08 19:48:11 +00004191static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004192fib_test_v6 (void)
4193{
4194 /*
4195 * In the default table check for the presence and correct forwarding
4196 * of the special entries
4197 */
4198 fib_node_index_t dfrt, fei, ai, locked_ai, ai_01, ai_02;
4199 const dpo_id_t *dpo, *dpo_drop;
4200 const ip_adjacency_t *adj;
4201 const receive_dpo_t *rd;
4202 test_main_t *tm;
4203 u32 fib_index;
4204 int ii;
4205
4206 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
4207 adj_nbr_db_size());
4208
4209 /* via 2001:0:0:1::2 */
4210 ip46_address_t nh_2001_2 = {
4211 .ip6 = {
4212 .as_u64 = {
4213 [0] = clib_host_to_net_u64(0x2001000000000001),
4214 [1] = clib_host_to_net_u64(0x0000000000000002),
4215 },
4216 },
4217 };
4218
4219 tm = &test_main;
4220
4221 dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
4222
4223 /* Find or create FIB table 11 */
Neale Ranns15002542017-09-10 04:39:11 -07004224 fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
4225 FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004226
4227 for (ii = 0; ii < 4; ii++)
4228 {
4229 ip6_main.fib_index_by_sw_if_index[tm->hw[ii]->sw_if_index] = fib_index;
4230 }
4231
4232 fib_prefix_t pfx_0_0 = {
4233 .fp_len = 0,
4234 .fp_proto = FIB_PROTOCOL_IP6,
4235 .fp_addr = {
4236 .ip6 = {
4237 {0, 0},
4238 },
4239 },
4240 };
4241
4242 dfrt = fib_table_lookup(fib_index, &pfx_0_0);
4243 FIB_TEST((FIB_NODE_INDEX_INVALID != dfrt), "default route present");
4244 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4245 "Default route is DROP");
4246
4247 dpo = fib_entry_contribute_ip_forwarding(dfrt);
4248 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4249 &ip6_main,
4250 1,
4251 &pfx_0_0.fp_addr.ip6)),
4252 "default-route; fwd and non-fwd tables match");
4253
4254 // FIXME - check specials.
4255
4256 /*
4257 * At this stage there is one v4 FIB with 5 routes and two v6 FIBs
Neale Ranns32e1c012016-11-22 17:07:28 +00004258 * each with 2 entries and a v6 mfib with 4 path-lists.
4259 * All entries are special so no path-list sharing.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004260 */
Neale Ranns32e1c012016-11-22 17:07:28 +00004261#define ENPS (5+4)
4262#define PNPS (5+4+4)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004263 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004264 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004265 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004266 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004267 fib_entry_pool_size());
4268
4269 /*
4270 * add interface routes.
4271 * validate presence of /64 attached and /128 recieve.
4272 * test for the presence of the receive address in the glean and local adj
4273 *
4274 * receive on 2001:0:0:1::1/128
4275 */
4276 fib_prefix_t local_pfx = {
4277 .fp_len = 64,
4278 .fp_proto = FIB_PROTOCOL_IP6,
4279 .fp_addr = {
4280 .ip6 = {
4281 .as_u64 = {
4282 [0] = clib_host_to_net_u64(0x2001000000000001),
4283 [1] = clib_host_to_net_u64(0x0000000000000001),
4284 },
4285 },
4286 }
4287 };
4288
4289 fib_table_entry_update_one_path(fib_index, &local_pfx,
4290 FIB_SOURCE_INTERFACE,
4291 (FIB_ENTRY_FLAG_CONNECTED |
4292 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004293 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004294 NULL,
4295 tm->hw[0]->sw_if_index,
4296 ~0,
4297 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004298 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004299 FIB_ROUTE_PATH_FLAG_NONE);
4300 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4301
4302 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4303
4304 ai = fib_entry_get_adj(fei);
4305 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
4306 adj = adj_get(ai);
4307 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4308 "attached interface adj is glean");
4309 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4310 &adj->sub_type.glean.receive_addr)),
4311 "attached interface adj is receive ok");
4312 dpo = fib_entry_contribute_ip_forwarding(fei);
4313 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4314 &ip6_main,
4315 1,
4316 &local_pfx.fp_addr.ip6)),
4317 "attached-route; fwd and non-fwd tables match");
4318
4319 local_pfx.fp_len = 128;
4320 fib_table_entry_update_one_path(fib_index, &local_pfx,
4321 FIB_SOURCE_INTERFACE,
4322 (FIB_ENTRY_FLAG_CONNECTED |
4323 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004324 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004325 NULL,
4326 tm->hw[0]->sw_if_index,
4327 ~0, // invalid fib index
4328 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004329 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004330 FIB_ROUTE_PATH_FLAG_NONE);
4331 fei = fib_table_lookup(fib_index, &local_pfx);
4332
4333 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4334
4335 dpo = fib_entry_contribute_ip_forwarding(fei);
4336 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4337 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4338 "local interface adj is local");
4339 rd = receive_dpo_get(dpo->dpoi_index);
4340
4341 FIB_TEST((0 == ip46_address_cmp(&local_pfx.fp_addr,
4342 &rd->rd_addr)),
4343 "local interface adj is receive ok");
4344
4345 dpo = fib_entry_contribute_ip_forwarding(fei);
4346 FIB_TEST((dpo->dpoi_index == ip6_fib_table_fwding_lookup(
4347 &ip6_main,
4348 1,
4349 &local_pfx.fp_addr.ip6)),
4350 "local-route; fwd and non-fwd tables match");
4351
4352 /*
4353 * +2 entries. +2 unshared path-lists
4354 */
4355 FIB_TEST((0 == fib_path_list_db_size()), "path list DB is empty");
Neale Ranns32e1c012016-11-22 17:07:28 +00004356 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004357 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004358 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004359 fib_entry_pool_size());
4360
4361 /*
4362 * Modify the default route to be via an adj not yet known.
4363 * this sources the defalut route with the API source, which is
4364 * a higher preference to the DEFAULT_ROUTE source
4365 */
4366 fib_table_entry_path_add(fib_index, &pfx_0_0,
4367 FIB_SOURCE_API,
4368 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004369 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004370 &nh_2001_2,
4371 tm->hw[0]->sw_if_index,
4372 ~0,
4373 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004374 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004375 FIB_ROUTE_PATH_FLAG_NONE);
4376 fei = fib_table_lookup(fib_index, &pfx_0_0);
4377
4378 FIB_TEST((fei == dfrt), "default route same index");
4379 ai = fib_entry_get_adj(fei);
4380 FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "default route adj present");
4381 adj = adj_get(ai);
4382 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4383 "adj is incomplete");
4384 FIB_TEST((0 == ip46_address_cmp(&nh_2001_2, &adj->sub_type.nbr.next_hop)),
4385 "adj nbr next-hop ok");
4386
4387 /*
4388 * find the adj in the shared db
4389 */
4390 locked_ai = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004391 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004392 &nh_2001_2,
4393 tm->hw[0]->sw_if_index);
4394 FIB_TEST((locked_ai == ai), "ADJ NBR DB find");
4395 adj_unlock(locked_ai);
4396
4397 /*
4398 * no more entires. +1 shared path-list
4399 */
4400 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4401 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004402 FIB_TEST((PNPS+3 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004403 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004404 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004405 fib_entry_pool_size());
4406
4407 /*
4408 * remove the API source from the default route. We expected
4409 * the route to remain, sourced by DEFAULT_ROUTE, and hence a DROP
4410 */
4411 fib_table_entry_path_remove(fib_index, &pfx_0_0,
4412 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07004413 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004414 &nh_2001_2,
4415 tm->hw[0]->sw_if_index,
4416 ~0,
4417 1,
4418 FIB_ROUTE_PATH_FLAG_NONE);
4419 fei = fib_table_lookup(fib_index, &pfx_0_0);
4420
4421 FIB_TEST((fei == dfrt), "default route same index");
4422 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(dfrt)),
4423 "Default route is DROP");
4424
4425 /*
4426 * no more entires. -1 shared path-list
4427 */
4428 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4429 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004430 FIB_TEST((PNPS+2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004431 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004432 FIB_TEST((ENPS+2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004433 fib_entry_pool_size());
4434
4435 /*
4436 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
4437 */
4438 fib_prefix_t pfx_2001_1_2_s_128 = {
4439 .fp_len = 128,
4440 .fp_proto = FIB_PROTOCOL_IP6,
4441 .fp_addr = {
4442 .ip6 = {
4443 .as_u64 = {
4444 [0] = clib_host_to_net_u64(0x2001000000000001),
4445 [1] = clib_host_to_net_u64(0x0000000000000002),
4446 },
4447 },
4448 }
4449 };
4450 fib_prefix_t pfx_2001_1_3_s_128 = {
4451 .fp_len = 128,
4452 .fp_proto = FIB_PROTOCOL_IP6,
4453 .fp_addr = {
4454 .ip6 = {
4455 .as_u64 = {
4456 [0] = clib_host_to_net_u64(0x2001000000000001),
4457 [1] = clib_host_to_net_u64(0x0000000000000003),
4458 },
4459 },
4460 }
4461 };
4462 u8 eth_addr[] = {
4463 0xde, 0xde, 0xde, 0xba, 0xba, 0xba,
4464 };
4465
4466 ai_01 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004467 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004468 &pfx_2001_1_2_s_128.fp_addr,
4469 tm->hw[0]->sw_if_index);
4470 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_01), "adj created");
4471 adj = adj_get(ai_01);
4472 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4473 "adj is incomplete");
4474 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4475 &adj->sub_type.nbr.next_hop)),
4476 "adj nbr next-hop ok");
4477
Neale Rannsb80c5362016-10-08 13:03:40 +01004478 adj_nbr_update_rewrite(ai_01, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4479 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004480 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4481 "adj is complete");
4482 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_2_s_128.fp_addr,
4483 &adj->sub_type.nbr.next_hop)),
4484 "adj nbr next-hop ok");
4485
Neale Ranns81424992017-05-18 03:03:22 -07004486 fib_table_entry_path_add(fib_index,
4487 &pfx_2001_1_2_s_128,
4488 FIB_SOURCE_ADJ,
4489 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004490 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004491 &pfx_2001_1_2_s_128.fp_addr,
4492 tm->hw[0]->sw_if_index,
4493 ~0,
4494 1,
4495 NULL,
4496 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004497
4498 fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
4499 ai = fib_entry_get_adj(fei);
4500 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4501
4502 eth_addr[5] = 0xb2;
4503
4504 ai_02 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP6,
Neale Ranns924d03a2016-10-19 08:25:46 +01004505 VNET_LINK_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004506 &pfx_2001_1_3_s_128.fp_addr,
4507 tm->hw[0]->sw_if_index);
4508 FIB_TEST((FIB_NODE_INDEX_INVALID != ai_02), "adj created");
4509 adj = adj_get(ai_02);
4510 FIB_TEST((IP_LOOKUP_NEXT_ARP == adj->lookup_next_index),
4511 "adj is incomplete");
4512 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4513 &adj->sub_type.nbr.next_hop)),
4514 "adj nbr next-hop ok");
4515
Neale Rannsb80c5362016-10-08 13:03:40 +01004516 adj_nbr_update_rewrite(ai_02, ADJ_NBR_REWRITE_FLAG_COMPLETE,
4517 fib_test_build_rewrite(eth_addr));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004518 FIB_TEST((IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index),
4519 "adj is complete");
4520 FIB_TEST((0 == ip46_address_cmp(&pfx_2001_1_3_s_128.fp_addr,
4521 &adj->sub_type.nbr.next_hop)),
4522 "adj nbr next-hop ok");
4523 FIB_TEST((ai_01 != ai_02), "ADJs are different");
4524
Neale Ranns81424992017-05-18 03:03:22 -07004525 fib_table_entry_path_add(fib_index,
4526 &pfx_2001_1_3_s_128,
4527 FIB_SOURCE_ADJ,
4528 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004529 DPO_PROTO_IP6,
Neale Ranns81424992017-05-18 03:03:22 -07004530 &pfx_2001_1_3_s_128.fp_addr,
4531 tm->hw[0]->sw_if_index,
4532 ~0,
4533 1,
4534 NULL,
4535 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004536
4537 fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
4538 ai = fib_entry_get_adj(fei);
4539 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4540
4541 /*
4542 * +2 entries, +2 unshread path-lists.
4543 */
4544 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
4545 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004546 FIB_TEST((PNPS+4 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004547 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004548 FIB_TEST((ENPS+4 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004549 fib_entry_pool_size());
4550
4551 /*
4552 * Add a 2 routes via the first ADJ. ensure path-list sharing
4553 */
4554 fib_prefix_t pfx_2001_a_s_64 = {
4555 .fp_len = 64,
4556 .fp_proto = FIB_PROTOCOL_IP6,
4557 .fp_addr = {
4558 .ip6 = {
4559 .as_u64 = {
4560 [0] = clib_host_to_net_u64(0x200100000000000a),
4561 [1] = clib_host_to_net_u64(0x0000000000000000),
4562 },
4563 },
4564 }
4565 };
4566 fib_prefix_t pfx_2001_b_s_64 = {
4567 .fp_len = 64,
4568 .fp_proto = FIB_PROTOCOL_IP6,
4569 .fp_addr = {
4570 .ip6 = {
4571 .as_u64 = {
4572 [0] = clib_host_to_net_u64(0x200100000000000b),
4573 [1] = clib_host_to_net_u64(0x0000000000000000),
4574 },
4575 },
4576 }
4577 };
4578
4579 fib_table_entry_path_add(fib_index,
4580 &pfx_2001_a_s_64,
4581 FIB_SOURCE_API,
4582 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004583 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004584 &nh_2001_2,
4585 tm->hw[0]->sw_if_index,
4586 ~0,
4587 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004588 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004589 FIB_ROUTE_PATH_FLAG_NONE);
4590 fei = fib_table_lookup(fib_index, &pfx_2001_a_s_64);
4591 ai = fib_entry_get_adj(fei);
4592 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4593 fib_table_entry_path_add(fib_index,
4594 &pfx_2001_b_s_64,
4595 FIB_SOURCE_API,
4596 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004597 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004598 &nh_2001_2,
4599 tm->hw[0]->sw_if_index,
4600 ~0,
4601 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004602 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004603 FIB_ROUTE_PATH_FLAG_NONE);
4604 fei = fib_table_lookup(fib_index, &pfx_2001_b_s_64);
4605 ai = fib_entry_get_adj(fei);
4606 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4607
4608 /*
4609 * +2 entries, +1 shared path-list.
4610 */
4611 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4612 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004613 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004614 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004615 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004616 fib_entry_pool_size());
4617
4618 /*
4619 * add a v4 prefix via a v6 next-hop
4620 */
4621 fib_prefix_t pfx_1_1_1_1_s_32 = {
4622 .fp_len = 32,
4623 .fp_proto = FIB_PROTOCOL_IP4,
4624 .fp_addr = {
4625 .ip4.as_u32 = 0x01010101,
4626 },
4627 };
4628 fei = fib_table_entry_path_add(0, // default table
4629 &pfx_1_1_1_1_s_32,
4630 FIB_SOURCE_API,
4631 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07004632 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004633 &nh_2001_2,
4634 tm->hw[0]->sw_if_index,
4635 ~0,
4636 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004637 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004638 FIB_ROUTE_PATH_FLAG_NONE);
4639 FIB_TEST(fei == fib_table_lookup_exact_match(0, &pfx_1_1_1_1_s_32),
4640 "1.1.1.1/32 o v6 route present");
4641 ai = fib_entry_get_adj(fei);
4642 adj = adj_get(ai);
4643 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP),
4644 "1.1.1.1/32 via ARP-adj");
Neale Ranns924d03a2016-10-19 08:25:46 +01004645 FIB_TEST((adj->ia_link == VNET_LINK_IP4),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004646 "1.1.1.1/32 ADJ-adj is link type v4");
4647 FIB_TEST((adj->ia_nh_proto == FIB_PROTOCOL_IP6),
4648 "1.1.1.1/32 ADJ-adj is NH proto v6");
4649 fib_table_entry_delete(0, &pfx_1_1_1_1_s_32, FIB_SOURCE_API);
4650
4651 /*
4652 * An attached route
4653 */
4654 fib_prefix_t pfx_2001_c_s_64 = {
4655 .fp_len = 64,
4656 .fp_proto = FIB_PROTOCOL_IP6,
4657 .fp_addr = {
4658 .ip6 = {
4659 .as_u64 = {
4660 [0] = clib_host_to_net_u64(0x200100000000000c),
4661 [1] = clib_host_to_net_u64(0x0000000000000000),
4662 },
4663 },
4664 }
4665 };
4666 fib_table_entry_path_add(fib_index,
4667 &pfx_2001_c_s_64,
4668 FIB_SOURCE_CLI,
4669 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07004670 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004671 NULL,
4672 tm->hw[0]->sw_if_index,
4673 ~0,
4674 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004675 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004676 FIB_ROUTE_PATH_FLAG_NONE);
4677 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4678 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached route present");
4679 ai = fib_entry_get_adj(fei);
4680 adj = adj_get(ai);
4681 FIB_TEST((adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN),
4682 "2001:0:0:c/64 attached resolves via glean");
4683
4684 fib_table_entry_path_remove(fib_index,
4685 &pfx_2001_c_s_64,
4686 FIB_SOURCE_CLI,
Neale Rannsda78f952017-05-24 09:15:43 -07004687 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004688 NULL,
4689 tm->hw[0]->sw_if_index,
4690 ~0,
4691 1,
4692 FIB_ROUTE_PATH_FLAG_NONE);
4693 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_c_s_64);
4694 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached route removed");
4695
4696 /*
4697 * Shutdown the interface on which we have a connected and through
4698 * which the routes are reachable.
4699 * This will result in the connected, adj-fibs, and routes linking to drop
4700 * The local/for-us prefix continues to receive.
4701 */
4702 clib_error_t * error;
4703
4704 error = vnet_sw_interface_set_flags(vnet_get_main(),
4705 tm->hw[0]->sw_if_index,
4706 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4707 FIB_TEST((NULL == error), "Interface shutdown OK");
4708
4709 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4710 dpo = fib_entry_contribute_ip_forwarding(fei);
4711 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4712 "2001::b/64 resolves via drop");
4713
4714 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4715 dpo = fib_entry_contribute_ip_forwarding(fei);
4716 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4717 "2001::a/64 resolves via drop");
4718 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4719 dpo = fib_entry_contribute_ip_forwarding(fei);
4720 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4721 "2001:0:0:1::3/64 resolves via drop");
4722 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4723 dpo = fib_entry_contribute_ip_forwarding(fei);
4724 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4725 "2001:0:0:1::2/64 resolves via drop");
4726 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4727 dpo = fib_entry_contribute_ip_forwarding(fei);
4728 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4729 "2001:0:0:1::1/128 not drop");
4730 local_pfx.fp_len = 64;
4731 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4732 dpo = fib_entry_contribute_ip_forwarding(fei);
4733 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4734 "2001:0:0:1/64 resolves via drop");
4735
4736 /*
4737 * no change
4738 */
4739 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4740 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004741 FIB_TEST((PNPS+5 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004742 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004743 FIB_TEST((ENPS+6 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004744 fib_entry_pool_size());
4745
4746 /*
4747 * shutdown one of the other interfaces, then add a connected.
4748 * and swap one of the routes to it.
4749 */
4750 error = vnet_sw_interface_set_flags(vnet_get_main(),
4751 tm->hw[1]->sw_if_index,
4752 ~VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4753 FIB_TEST((NULL == error), "Interface 1 shutdown OK");
4754
4755 fib_prefix_t connected_pfx = {
4756 .fp_len = 64,
4757 .fp_proto = FIB_PROTOCOL_IP6,
4758 .fp_addr = {
4759 .ip6 = {
4760 /* 2001:0:0:2::1/64 */
4761 .as_u64 = {
4762 [0] = clib_host_to_net_u64(0x2001000000000002),
4763 [1] = clib_host_to_net_u64(0x0000000000000001),
4764 },
4765 },
4766 }
4767 };
4768 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4769 FIB_SOURCE_INTERFACE,
4770 (FIB_ENTRY_FLAG_CONNECTED |
4771 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07004772 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004773 NULL,
4774 tm->hw[1]->sw_if_index,
4775 ~0,
4776 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004777 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004778 FIB_ROUTE_PATH_FLAG_NONE);
4779 fei = fib_table_lookup_exact_match(fib_index, &connected_pfx);
4780 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached interface route present");
4781 dpo = fib_entry_contribute_ip_forwarding(fei);
4782 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4783 FIB_TEST(!dpo_cmp(dpo, dpo_drop),
4784 "2001:0:0:2/64 not resolves via drop");
4785
4786 connected_pfx.fp_len = 128;
4787 fib_table_entry_update_one_path(fib_index, &connected_pfx,
4788 FIB_SOURCE_INTERFACE,
4789 (FIB_ENTRY_FLAG_CONNECTED |
4790 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07004791 DPO_PROTO_IP6,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004792 NULL,
4793 tm->hw[0]->sw_if_index,
4794 ~0, // invalid fib index
4795 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00004796 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004797 FIB_ROUTE_PATH_FLAG_NONE);
4798 fei = fib_table_lookup(fib_index, &connected_pfx);
4799
4800 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local interface route present");
4801 dpo = fib_entry_contribute_ip_forwarding(fei);
4802 dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
4803 FIB_TEST((DPO_RECEIVE == dpo->dpoi_type),
4804 "local interface adj is local");
4805 rd = receive_dpo_get(dpo->dpoi_index);
4806 FIB_TEST((0 == ip46_address_cmp(&connected_pfx.fp_addr,
4807 &rd->rd_addr)),
4808 "local interface adj is receive ok");
4809
4810 /*
4811 * +2 entries, +2 unshared path-lists
4812 */
4813 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4814 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004815 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004816 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004817 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004818 fib_entry_pool_size());
4819
4820
4821 /*
4822 * bring the interface back up. we expected the routes to return
4823 * to normal forwarding.
4824 */
4825 error = vnet_sw_interface_set_flags(vnet_get_main(),
4826 tm->hw[0]->sw_if_index,
4827 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
4828 FIB_TEST((NULL == error), "Interface bring-up OK");
4829 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4830 ai = fib_entry_get_adj(fei);
4831 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4832 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4833 ai = fib_entry_get_adj(fei);
4834 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4835 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4836 ai = fib_entry_get_adj(fei);
4837 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4838 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4839 ai = fib_entry_get_adj(fei);
4840 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4841 local_pfx.fp_len = 64;
4842 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4843 ai = fib_entry_get_adj(fei);
4844 adj = adj_get(ai);
4845 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4846 "attached interface adj is glean");
4847
4848 /*
Neale Ranns8b37b872016-11-21 12:25:22 +00004849 * Same test as above, but this time the HW interface goes down
4850 */
4851 error = vnet_hw_interface_set_flags(vnet_get_main(),
4852 tm->hw_if_indicies[0],
4853 ~VNET_HW_INTERFACE_FLAG_LINK_UP);
4854 FIB_TEST((NULL == error), "Interface shutdown OK");
4855
4856 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4857 dpo = fib_entry_contribute_ip_forwarding(fei);
4858 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4859 "2001::b/64 resolves via drop");
4860 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4861 dpo = fib_entry_contribute_ip_forwarding(fei);
4862 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4863 "2001::a/64 resolves via drop");
4864 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4865 dpo = fib_entry_contribute_ip_forwarding(fei);
4866 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4867 "2001:0:0:1::3/128 resolves via drop");
4868 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4869 dpo = fib_entry_contribute_ip_forwarding(fei);
4870 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4871 "2001:0:0:1::2/128 resolves via drop");
4872 local_pfx.fp_len = 128;
4873 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4874 dpo = fib_entry_contribute_ip_forwarding(fei);
4875 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4876 "2001:0:0:1::1/128 not drop");
4877 local_pfx.fp_len = 64;
4878 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4879 dpo = fib_entry_contribute_ip_forwarding(fei);
4880 FIB_TEST(!dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
4881 "2001:0:0:1/64 resolves via drop");
4882
4883 error = vnet_hw_interface_set_flags(vnet_get_main(),
4884 tm->hw_if_indicies[0],
4885 VNET_HW_INTERFACE_FLAG_LINK_UP);
4886 FIB_TEST((NULL == error), "Interface bring-up OK");
4887 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4888 ai = fib_entry_get_adj(fei);
4889 FIB_TEST((ai_01 == ai), "2001::a/64 resolves via 2001:0:0:1::1");
4890 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4891 ai = fib_entry_get_adj(fei);
4892 FIB_TEST((ai_01 == ai), "2001::b/64 resolves via 2001:0:0:1::1");
4893 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4894 ai = fib_entry_get_adj(fei);
4895 FIB_TEST((ai_02 == ai), "ADJ-FIB resolves via adj");
4896 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4897 ai = fib_entry_get_adj(fei);
4898 FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
4899 local_pfx.fp_len = 64;
4900 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4901 ai = fib_entry_get_adj(fei);
4902 adj = adj_get(ai);
4903 FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
4904 "attached interface adj is glean");
4905
4906 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004907 * Delete the interface that the routes reolve through.
4908 * Again no routes are removed. They all point to drop.
4909 *
4910 * This is considered an error case. The control plane should
4911 * not remove interfaces through which routes resolve, but
4912 * such things can happen. ALL affected routes will drop.
4913 */
4914 vnet_delete_hw_interface(vnet_get_main(), tm->hw_if_indicies[0]);
4915
4916 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64);
4917 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4918 "2001::b/64 resolves via drop");
4919 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64);
4920 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4921 "2001::b/64 resolves via drop");
4922 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128);
4923 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4924 "2001:0:0:1::3/64 resolves via drop");
4925 fei = fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128);
4926 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4927 "2001:0:0:1::2/64 resolves via drop");
4928 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4929 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4930 "2001:0:0:1::1/128 is drop");
4931 local_pfx.fp_len = 64;
4932 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
4933 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
4934 "2001:0:0:1/64 resolves via drop");
4935
4936 /*
4937 * no change
4938 */
4939 FIB_TEST((1 == fib_path_list_db_size()), "path list DB population:%d",
4940 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004941 FIB_TEST((PNPS+7 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004942 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00004943 FIB_TEST((ENPS+8 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01004944 fib_entry_pool_size());
4945
4946 /*
4947 * Add the interface back. routes stay unresolved.
4948 */
4949 error = ethernet_register_interface(vnet_get_main(),
4950 test_interface_device_class.index,
4951 0 /* instance */,
4952 hw_address,
4953 &tm->hw_if_indicies[0],
4954 /* flag change */ 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 * CLEANUP ALL the routes
4978 */
4979 fib_table_entry_delete(fib_index,
4980 &pfx_2001_c_s_64,
4981 FIB_SOURCE_API);
4982 fib_table_entry_delete(fib_index,
4983 &pfx_2001_a_s_64,
4984 FIB_SOURCE_API);
4985 fib_table_entry_delete(fib_index,
4986 &pfx_2001_b_s_64,
4987 FIB_SOURCE_API);
4988 fib_table_entry_delete(fib_index,
4989 &pfx_2001_1_3_s_128,
4990 FIB_SOURCE_ADJ);
4991 fib_table_entry_delete(fib_index,
4992 &pfx_2001_1_2_s_128,
4993 FIB_SOURCE_ADJ);
4994 local_pfx.fp_len = 64;
4995 fib_table_entry_delete(fib_index, &local_pfx,
4996 FIB_SOURCE_INTERFACE);
4997 local_pfx.fp_len = 128;
4998 fib_table_entry_special_remove(fib_index, &local_pfx,
4999 FIB_SOURCE_INTERFACE);
5000 connected_pfx.fp_len = 64;
5001 fib_table_entry_delete(fib_index, &connected_pfx,
5002 FIB_SOURCE_INTERFACE);
5003 connected_pfx.fp_len = 128;
5004 fib_table_entry_special_remove(fib_index, &connected_pfx,
5005 FIB_SOURCE_INTERFACE);
5006
5007 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5008 fib_table_lookup_exact_match(fib_index, &pfx_2001_a_s_64)),
5009 "2001::a/64 removed");
5010 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5011 fib_table_lookup_exact_match(fib_index, &pfx_2001_b_s_64)),
5012 "2001::b/64 removed");
5013 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5014 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_3_s_128)),
5015 "2001:0:0:1::3/128 removed");
5016 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5017 fib_table_lookup_exact_match(fib_index, &pfx_2001_1_2_s_128)),
5018 "2001:0:0:1::3/128 removed");
5019 local_pfx.fp_len = 64;
5020 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5021 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5022 "2001:0:0:1/64 removed");
5023 local_pfx.fp_len = 128;
5024 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5025 fib_table_lookup_exact_match(fib_index, &local_pfx)),
5026 "2001:0:0:1::1/128 removed");
5027 connected_pfx.fp_len = 64;
5028 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5029 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5030 "2001:0:0:2/64 removed");
5031 connected_pfx.fp_len = 128;
5032 FIB_TEST((FIB_NODE_INDEX_INVALID ==
5033 fib_table_lookup_exact_match(fib_index, &connected_pfx)),
5034 "2001:0:0:2::1/128 removed");
5035
5036 /*
5037 * -8 entries. -7 path-lists (1 was shared).
5038 */
5039 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5040 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005041 FIB_TEST((PNPS == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005042 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005043 FIB_TEST((ENPS == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005044 fib_entry_pool_size());
5045
5046 /*
5047 * now remove the VRF
5048 */
Neale Ranns15002542017-09-10 04:39:11 -07005049 fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005050
5051 FIB_TEST((0 == fib_path_list_db_size()), "path list DB population:%d",
5052 fib_path_list_db_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005053 FIB_TEST((PNPS-2 == fib_path_list_pool_size()), "path list pool size is%d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005054 fib_path_list_pool_size());
Neale Ranns32e1c012016-11-22 17:07:28 +00005055 FIB_TEST((ENPS-2 == fib_entry_pool_size()), "entry pool size is %d",
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005056 fib_entry_pool_size());
5057
5058 adj_unlock(ai_02);
5059 adj_unlock(ai_01);
5060
5061 /*
5062 * return the interfaces to up state
5063 */
5064 error = vnet_sw_interface_set_flags(vnet_get_main(),
5065 tm->hw[0]->sw_if_index,
5066 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5067 error = vnet_sw_interface_set_flags(vnet_get_main(),
5068 tm->hw[1]->sw_if_index,
5069 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5070
5071 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5072 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005073
5074 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005075}
5076
5077/*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005078 * Test Attached Exports
5079 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005080static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005081fib_test_ae (void)
5082{
5083 const dpo_id_t *dpo, *dpo_drop;
5084 const u32 fib_index = 0;
5085 fib_node_index_t fei;
5086 test_main_t *tm;
5087 ip4_main_t *im;
5088
5089 tm = &test_main;
5090 im = &ip4_main;
5091
5092 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5093 adj_nbr_db_size());
5094
5095 /*
5096 * add interface routes. We'll assume this works. It's more rigorously
5097 * tested elsewhere.
5098 */
5099 fib_prefix_t local_pfx = {
5100 .fp_len = 24,
5101 .fp_proto = FIB_PROTOCOL_IP4,
5102 .fp_addr = {
5103 .ip4 = {
5104 /* 10.10.10.10 */
5105 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
5106 },
5107 },
5108 };
5109
5110 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
5111 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
5112
5113 dpo_drop = drop_dpo_get(DPO_PROTO_IP4);
5114
5115 fib_table_entry_update_one_path(fib_index, &local_pfx,
5116 FIB_SOURCE_INTERFACE,
5117 (FIB_ENTRY_FLAG_CONNECTED |
5118 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005119 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005120 NULL,
5121 tm->hw[0]->sw_if_index,
5122 ~0,
5123 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005124 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005125 FIB_ROUTE_PATH_FLAG_NONE);
5126 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5127 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5128 "attached interface route present");
5129
5130 local_pfx.fp_len = 32;
5131 fib_table_entry_update_one_path(fib_index, &local_pfx,
5132 FIB_SOURCE_INTERFACE,
5133 (FIB_ENTRY_FLAG_CONNECTED |
5134 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07005135 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005136 NULL,
5137 tm->hw[0]->sw_if_index,
5138 ~0, // invalid fib index
5139 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005140 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005141 FIB_ROUTE_PATH_FLAG_NONE);
5142 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5143
5144 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
5145 "local interface route present");
5146
5147 /*
5148 * Add an 2 ARP entry => a complete ADJ plus adj-fib.
5149 */
5150 fib_prefix_t pfx_10_10_10_1_s_32 = {
5151 .fp_len = 32,
5152 .fp_proto = FIB_PROTOCOL_IP4,
5153 .fp_addr = {
5154 /* 10.10.10.1 */
5155 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5156 },
5157 };
5158 fib_node_index_t ai;
5159
Neale Ranns81424992017-05-18 03:03:22 -07005160 fib_table_entry_path_add(fib_index,
5161 &pfx_10_10_10_1_s_32,
5162 FIB_SOURCE_ADJ,
5163 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005164 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005165 &pfx_10_10_10_1_s_32.fp_addr,
5166 tm->hw[0]->sw_if_index,
5167 ~0, // invalid fib index
5168 1,
5169 NULL,
5170 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005171
5172 fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
5173 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
5174 ai = fib_entry_get_adj(fei);
5175
5176 /*
5177 * create another FIB table into which routes will be imported
5178 */
5179 u32 import_fib_index1;
5180
Neale Ranns15002542017-09-10 04:39:11 -07005181 import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
5182 11,
5183 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005184
5185 /*
5186 * Add an attached route in the import FIB
5187 */
5188 local_pfx.fp_len = 24;
5189 fib_table_entry_update_one_path(import_fib_index1,
5190 &local_pfx,
5191 FIB_SOURCE_API,
5192 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005193 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005194 NULL,
5195 tm->hw[0]->sw_if_index,
5196 ~0, // invalid fib index
5197 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005198 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005199 FIB_ROUTE_PATH_FLAG_NONE);
5200 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5201 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5202
5203 /*
5204 * check for the presence of the adj-fibs in the import table
5205 */
5206 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5207 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5208 FIB_TEST((ai == fib_entry_get_adj(fei)),
5209 "adj-fib1 Import uses same adj as export");
5210
5211 /*
5212 * check for the presence of the local in the import table
5213 */
5214 local_pfx.fp_len = 32;
5215 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5216 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5217
5218 /*
5219 * Add another adj-fin in the export table. Expect this
5220 * to get magically exported;
5221 */
5222 fib_prefix_t pfx_10_10_10_2_s_32 = {
5223 .fp_len = 32,
5224 .fp_proto = FIB_PROTOCOL_IP4,
5225 .fp_addr = {
5226 /* 10.10.10.2 */
5227 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5228 },
5229 };
5230
Neale Ranns81424992017-05-18 03:03:22 -07005231 fib_table_entry_path_add(fib_index,
5232 &pfx_10_10_10_2_s_32,
5233 FIB_SOURCE_ADJ,
5234 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005235 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005236 &pfx_10_10_10_2_s_32.fp_addr,
5237 tm->hw[0]->sw_if_index,
5238 ~0, // invalid fib index
5239 1,
5240 NULL,
5241 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005242 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5243 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
5244 ai = fib_entry_get_adj(fei);
5245
5246 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5247 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5248 FIB_TEST((ai == fib_entry_get_adj(fei)),
5249 "Import uses same adj as export");
Neale Rannsfa0fb582016-12-10 21:59:14 +00005250 FIB_TEST((FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(fei)),
5251 "ADJ-fib2 imported flags %d",
5252 fib_entry_get_flags(fei));
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005253
5254 /*
5255 * create a 2nd FIB table into which routes will be imported
5256 */
5257 u32 import_fib_index2;
5258
Neale Ranns15002542017-09-10 04:39:11 -07005259 import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
5260 FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005261
5262 /*
5263 * Add an attached route in the import FIB
5264 */
5265 local_pfx.fp_len = 24;
5266 fib_table_entry_update_one_path(import_fib_index2,
5267 &local_pfx,
5268 FIB_SOURCE_API,
5269 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005270 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005271 NULL,
5272 tm->hw[0]->sw_if_index,
5273 ~0, // invalid fib index
5274 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005275 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005276 FIB_ROUTE_PATH_FLAG_NONE);
5277 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5278 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached export created");
5279
5280 /*
5281 * check for the presence of all the adj-fibs and local in the import table
5282 */
5283 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5284 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5285 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5286 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5287 local_pfx.fp_len = 32;
5288 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5289 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5290
5291 /*
5292 * add a 3rd adj-fib. expect it to be exported to both tables.
5293 */
5294 fib_prefix_t pfx_10_10_10_3_s_32 = {
5295 .fp_len = 32,
5296 .fp_proto = FIB_PROTOCOL_IP4,
5297 .fp_addr = {
5298 /* 10.10.10.3 */
5299 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
5300 },
5301 };
5302
Neale Ranns81424992017-05-18 03:03:22 -07005303 fib_table_entry_path_add(fib_index,
5304 &pfx_10_10_10_3_s_32,
5305 FIB_SOURCE_ADJ,
5306 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07005307 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07005308 &pfx_10_10_10_3_s_32.fp_addr,
5309 tm->hw[0]->sw_if_index,
5310 ~0, // invalid fib index
5311 1,
5312 NULL,
5313 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005314 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5315 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
5316 ai = fib_entry_get_adj(fei);
5317
5318 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5319 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB1");
5320 FIB_TEST((ai == fib_entry_get_adj(fei)),
5321 "Import uses same adj as export");
5322 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5323 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 imported to FIB2");
5324 FIB_TEST((ai == fib_entry_get_adj(fei)),
5325 "Import uses same adj as export");
5326
5327 /*
5328 * remove the 3rd adj fib. we expect it to be removed from both FIBs
5329 */
5330 fib_table_entry_delete(fib_index,
5331 &pfx_10_10_10_3_s_32,
5332 FIB_SOURCE_ADJ);
5333
5334 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
5335 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 remved");
5336
5337 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_3_s_32);
5338 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB1");
5339
5340 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_3_s_32);
5341 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib3 removed from FIB2");
5342
5343 /*
5344 * remove the attached route from the 2nd FIB. expect the imported
5345 * entires to be removed
5346 */
5347 local_pfx.fp_len = 24;
5348 fib_table_entry_delete(import_fib_index2,
5349 &local_pfx,
5350 FIB_SOURCE_API);
5351 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5352 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "attached export removed");
5353
5354 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_1_s_32);
5355 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB2");
5356 fei = fib_table_lookup_exact_match(import_fib_index2, &pfx_10_10_10_2_s_32);
5357 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB2");
5358 local_pfx.fp_len = 32;
5359 fei = fib_table_lookup_exact_match(import_fib_index2, &local_pfx);
5360 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB2");
5361
5362 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5363 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 still in FIB1");
5364 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5365 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 still in FIB1");
5366 local_pfx.fp_len = 32;
5367 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5368 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local still in FIB1");
5369
5370 /*
5371 * modify the route in FIB1 so it is no longer attached. expect the imported
5372 * entires to be removed
5373 */
5374 local_pfx.fp_len = 24;
5375 fib_table_entry_update_one_path(import_fib_index1,
5376 &local_pfx,
5377 FIB_SOURCE_API,
5378 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005379 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005380 &pfx_10_10_10_2_s_32.fp_addr,
5381 tm->hw[0]->sw_if_index,
5382 ~0, // invalid fib index
5383 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005384 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005385 FIB_ROUTE_PATH_FLAG_NONE);
5386 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5387 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5388 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5389 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5390 local_pfx.fp_len = 32;
5391 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5392 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5393
5394 /*
5395 * modify it back to attached. expect the adj-fibs back
5396 */
5397 local_pfx.fp_len = 24;
5398 fib_table_entry_update_one_path(import_fib_index1,
5399 &local_pfx,
5400 FIB_SOURCE_API,
5401 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005402 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005403 NULL,
5404 tm->hw[0]->sw_if_index,
5405 ~0, // invalid fib index
5406 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005407 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005408 FIB_ROUTE_PATH_FLAG_NONE);
5409 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5410 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported in FIB1");
5411 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5412 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported in FIB1");
5413 local_pfx.fp_len = 32;
5414 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5415 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported in FIB1");
5416
5417 /*
5418 * add a covering attached next-hop for the interface address, so we have
5419 * a valid adj to find when we check the forwarding tables
5420 */
5421 fib_prefix_t pfx_10_0_0_0_s_8 = {
5422 .fp_len = 8,
5423 .fp_proto = FIB_PROTOCOL_IP4,
5424 .fp_addr = {
5425 /* 10.0.0.0 */
5426 .ip4.as_u32 = clib_host_to_net_u32(0x0a000000),
5427 },
5428 };
5429
5430 fei = fib_table_entry_update_one_path(fib_index,
5431 &pfx_10_0_0_0_s_8,
5432 FIB_SOURCE_API,
5433 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005434 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005435 &pfx_10_10_10_3_s_32.fp_addr,
5436 tm->hw[0]->sw_if_index,
5437 ~0, // invalid fib index
5438 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005439 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005440 FIB_ROUTE_PATH_FLAG_NONE);
5441 dpo = fib_entry_contribute_ip_forwarding(fei);
5442
5443 /*
5444 * remove the route in the export fib. expect the adj-fibs to be removed
5445 */
5446 local_pfx.fp_len = 24;
5447 fib_table_entry_delete(fib_index,
5448 &local_pfx,
5449 FIB_SOURCE_INTERFACE);
5450
5451 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5452 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "Delete export: ADJ-fib1 removed from FIB1");
5453 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5454 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5455 local_pfx.fp_len = 32;
5456 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5457 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5458
5459 /*
5460 * the adj-fibs in the export VRF are present in the FIB table,
5461 * but not installed in forwarding, since they have no attached cover.
5462 * Consequently a lookup in the MTRIE gives the adj for the covering
5463 * route 10.0.0.0/8.
5464 */
5465 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5466 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5467
5468 index_t lbi;
5469 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5470 FIB_TEST(lbi == dpo->dpoi_index,
5471 "10.10.10.1 forwards on \n%U not \n%U",
5472 format_load_balance, lbi, 0,
5473 format_dpo_id, dpo, 0);
5474 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5475 FIB_TEST(lbi == dpo->dpoi_index,
5476 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5477 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_3_s_32.fp_addr.ip4);
5478 FIB_TEST(lbi == dpo->dpoi_index,
5479 "10.10.10.3 forwards on %U", format_dpo_id, dpo, 0);
5480
5481 /*
5482 * add the export prefix back, but not as attached.
5483 * No adj-fibs in export nor import tables
5484 */
5485 local_pfx.fp_len = 24;
5486 fei = fib_table_entry_update_one_path(fib_index,
5487 &local_pfx,
5488 FIB_SOURCE_API,
5489 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005490 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005491 &pfx_10_10_10_1_s_32.fp_addr,
5492 tm->hw[0]->sw_if_index,
5493 ~0, // invalid fib index
5494 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005495 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005496 FIB_ROUTE_PATH_FLAG_NONE);
5497 dpo = fib_entry_contribute_ip_forwarding(fei);
5498
5499 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5500 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "non-attached in export: ADJ-fib1 in export");
5501 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_1_s_32.fp_addr.ip4);
5502 FIB_TEST(lbi == dpo->dpoi_index,
5503 "10.10.10.1 forwards on %U", format_dpo_id, dpo, 0);
5504 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5505 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 in export");
5506 lbi = ip4_fib_forwarding_lookup(fib_index, &pfx_10_10_10_2_s_32.fp_addr.ip4);
5507 FIB_TEST(lbi == dpo->dpoi_index,
5508 "10.10.10.2 forwards on %U", format_dpo_id, dpo, 0);
5509
5510 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5511 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib1 removed from FIB1");
5512 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5513 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "ADJ-fib2 removed from FIB1");
5514 local_pfx.fp_len = 32;
5515 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5516 FIB_TEST((FIB_NODE_INDEX_INVALID == fei), "local removed from FIB1");
5517
5518 /*
5519 * modify the export prefix so it is attached. expect all covereds to return
5520 */
5521 local_pfx.fp_len = 24;
5522 fib_table_entry_update_one_path(fib_index,
5523 &local_pfx,
5524 FIB_SOURCE_API,
5525 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07005526 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005527 NULL,
5528 tm->hw[0]->sw_if_index,
5529 ~0, // invalid fib index
5530 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005531 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005532 FIB_ROUTE_PATH_FLAG_NONE);
5533
5534 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5535 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5536 dpo = fib_entry_contribute_ip_forwarding(fei);
5537 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5538 "Adj-fib1 is not drop in export");
5539 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5540 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5541 local_pfx.fp_len = 32;
5542 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5543 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5544 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5545 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5546 dpo = fib_entry_contribute_ip_forwarding(fei);
5547 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5548 "Adj-fib1 is not drop in export");
5549 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5550 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 imported");
5551 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5552 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5553 local_pfx.fp_len = 32;
5554 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5555 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5556
5557 /*
5558 * modify the export prefix so connected. no change.
5559 */
5560 local_pfx.fp_len = 24;
5561 fib_table_entry_update_one_path(fib_index, &local_pfx,
5562 FIB_SOURCE_INTERFACE,
5563 (FIB_ENTRY_FLAG_CONNECTED |
5564 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07005565 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005566 NULL,
5567 tm->hw[0]->sw_if_index,
5568 ~0,
5569 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00005570 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005571 FIB_ROUTE_PATH_FLAG_NONE);
5572
5573 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_1_s_32);
5574 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 reinstalled in export");
5575 dpo = fib_entry_contribute_ip_forwarding(fei);
5576 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5577 "Adj-fib1 is not drop in export");
5578 fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
5579 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 reinstalled in export");
5580 local_pfx.fp_len = 32;
5581 fei = fib_table_lookup_exact_match(fib_index, &local_pfx);
5582 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local reinstalled in export");
5583 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_1_s_32);
5584 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "attached in export: ADJ-fib1 imported");
5585 dpo = fib_entry_contribute_ip_forwarding(fei);
5586 FIB_TEST(dpo_cmp(dpo_drop, load_balance_get_bucket(dpo->dpoi_index, 0)),
5587 "Adj-fib1 is not drop in export");
5588 fei = fib_table_lookup_exact_match(import_fib_index1, &pfx_10_10_10_2_s_32);
5589 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 imported");
5590 local_pfx.fp_len = 32;
5591 fei = fib_table_lookup_exact_match(import_fib_index1, &local_pfx);
5592 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "local imported");
5593
5594 /*
5595 * CLEANUP
5596 */
5597 fib_table_entry_delete(fib_index,
5598 &pfx_10_0_0_0_s_8,
5599 FIB_SOURCE_API);
5600 fib_table_entry_delete(fib_index,
5601 &pfx_10_10_10_1_s_32,
5602 FIB_SOURCE_ADJ);
5603 fib_table_entry_delete(fib_index,
5604 &pfx_10_10_10_2_s_32,
5605 FIB_SOURCE_ADJ);
5606 local_pfx.fp_len = 32;
5607 fib_table_entry_delete(fib_index,
5608 &local_pfx,
5609 FIB_SOURCE_INTERFACE);
5610 local_pfx.fp_len = 24;
5611 fib_table_entry_delete(fib_index,
5612 &local_pfx,
5613 FIB_SOURCE_API);
5614 fib_table_entry_delete(fib_index,
5615 &local_pfx,
5616 FIB_SOURCE_INTERFACE);
5617 local_pfx.fp_len = 24;
5618 fib_table_entry_delete(import_fib_index1,
5619 &local_pfx,
5620 FIB_SOURCE_API);
5621
Neale Ranns15002542017-09-10 04:39:11 -07005622 fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
5623 fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005624
5625 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
5626 adj_nbr_db_size());
Neale Ranns0ebe8d72016-12-08 19:48:11 +00005627
5628 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01005629}
5630
Neale Ranns57b58602017-07-15 07:37:25 -07005631/*
5632 * Test Path Preference
5633 */
5634static int
5635fib_test_pref (void)
5636{
5637 test_main_t *tm = &test_main;
5638
5639 const fib_prefix_t pfx_1_1_1_1_s_32 = {
5640 .fp_len = 32,
5641 .fp_proto = FIB_PROTOCOL_IP4,
5642 .fp_addr = {
5643 .ip4 = {
5644 .as_u32 = clib_host_to_net_u32(0x01010101),
5645 },
5646 },
5647 };
5648
5649 /*
5650 * 2 high, 2 medium and 2 low preference non-recursive paths
5651 */
5652 fib_route_path_t nr_path_hi_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005653 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005654 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5655 .frp_fib_index = ~0,
5656 .frp_weight = 1,
5657 .frp_preference = 0,
5658 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5659 .frp_addr = {
5660 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
5661 },
5662 };
5663 fib_route_path_t nr_path_hi_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005664 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005665 .frp_sw_if_index = tm->hw[0]->sw_if_index,
5666 .frp_fib_index = ~0,
5667 .frp_weight = 1,
5668 .frp_preference = 0,
5669 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5670 .frp_addr = {
5671 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
5672 },
5673 };
5674 fib_route_path_t nr_path_med_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005675 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005676 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5677 .frp_fib_index = ~0,
5678 .frp_weight = 1,
5679 .frp_preference = 1,
5680 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5681 .frp_addr = {
5682 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5683 },
5684 };
5685 fib_route_path_t nr_path_med_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005686 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005687 .frp_sw_if_index = tm->hw[1]->sw_if_index,
5688 .frp_fib_index = ~0,
5689 .frp_weight = 1,
5690 .frp_preference = 1,
5691 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5692 .frp_addr = {
5693 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0c01),
5694 },
5695 };
5696 fib_route_path_t nr_path_low_1 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005697 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005698 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5699 .frp_fib_index = ~0,
5700 .frp_weight = 1,
5701 .frp_preference = 2,
5702 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5703 .frp_addr = {
5704 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b01),
5705 },
5706 };
5707 fib_route_path_t nr_path_low_2 = {
Neale Rannsda78f952017-05-24 09:15:43 -07005708 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005709 .frp_sw_if_index = tm->hw[2]->sw_if_index,
5710 .frp_fib_index = ~0,
5711 .frp_weight = 1,
5712 .frp_preference = 2,
5713 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5714 .frp_addr = {
5715 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0b02),
5716 },
5717 };
5718 fib_route_path_t *nr_paths = NULL;
5719
5720 vec_add1(nr_paths, nr_path_hi_1);
5721 vec_add1(nr_paths, nr_path_hi_2);
5722 vec_add1(nr_paths, nr_path_med_1);
5723 vec_add1(nr_paths, nr_path_med_2);
5724 vec_add1(nr_paths, nr_path_low_1);
5725 vec_add1(nr_paths, nr_path_low_2);
5726
5727 adj_index_t ai_hi_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5728 VNET_LINK_IP4,
5729 &nr_path_hi_1.frp_addr,
5730 nr_path_hi_1.frp_sw_if_index);
5731 adj_index_t ai_hi_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5732 VNET_LINK_IP4,
5733 &nr_path_hi_2.frp_addr,
5734 nr_path_hi_2.frp_sw_if_index);
5735 adj_index_t ai_med_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5736 VNET_LINK_IP4,
5737 &nr_path_med_1.frp_addr,
5738 nr_path_med_1.frp_sw_if_index);
5739 adj_index_t ai_med_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5740 VNET_LINK_IP4,
5741 &nr_path_med_2.frp_addr,
5742 nr_path_med_2.frp_sw_if_index);
5743 adj_index_t ai_low_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5744 VNET_LINK_IP4,
5745 &nr_path_low_1.frp_addr,
5746 nr_path_low_1.frp_sw_if_index);
5747 adj_index_t ai_low_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
5748 VNET_LINK_IP4,
5749 &nr_path_low_2.frp_addr,
5750 nr_path_low_2.frp_sw_if_index);
5751
5752 fib_test_lb_bucket_t ip_hi_1 = {
5753 .type = FT_LB_ADJ,
5754 .adj = {
5755 .adj = ai_hi_1,
5756 },
5757 };
5758 fib_test_lb_bucket_t ip_hi_2 = {
5759 .type = FT_LB_ADJ,
5760 .adj = {
5761 .adj = ai_hi_2,
5762 },
5763 };
5764 fib_test_lb_bucket_t ip_med_1 = {
5765 .type = FT_LB_ADJ,
5766 .adj = {
5767 .adj = ai_med_1,
5768 },
5769 };
5770 fib_test_lb_bucket_t ip_med_2 = {
5771 .type = FT_LB_ADJ,
5772 .adj = {
5773 .adj = ai_med_2,
5774 },
5775 };
5776 fib_test_lb_bucket_t ip_low_1 = {
5777 .type = FT_LB_ADJ,
5778 .adj = {
5779 .adj = ai_low_1,
5780 },
5781 };
5782 fib_test_lb_bucket_t ip_low_2 = {
5783 .type = FT_LB_ADJ,
5784 .adj = {
5785 .adj = ai_low_2,
5786 },
5787 };
5788
5789 fib_node_index_t fei;
5790
5791 fei = fib_table_entry_path_add2(0,
5792 &pfx_1_1_1_1_s_32,
5793 FIB_SOURCE_API,
5794 FIB_ENTRY_FLAG_NONE,
5795 nr_paths);
5796
5797 FIB_TEST(fib_test_validate_entry(fei,
5798 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5799 2,
5800 &ip_hi_1,
5801 &ip_hi_2),
5802 "1.1.1.1/32 via high preference paths");
5803
5804 /*
5805 * bring down the interface on which the high preference path lie
5806 */
5807 vnet_sw_interface_set_flags(vnet_get_main(),
5808 tm->hw[0]->sw_if_index,
5809 0);
5810
5811 FIB_TEST(fib_test_validate_entry(fei,
5812 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5813 2,
5814 &ip_med_1,
5815 &ip_med_2),
5816 "1.1.1.1/32 via medium preference paths");
5817
5818 /*
5819 * bring down the interface on which the medium preference path lie
5820 */
5821 vnet_sw_interface_set_flags(vnet_get_main(),
5822 tm->hw[1]->sw_if_index,
5823 0);
5824
5825 FIB_TEST(fib_test_validate_entry(fei,
5826 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5827 2,
5828 &ip_low_1,
5829 &ip_low_2),
5830 "1.1.1.1/32 via low preference paths");
5831
5832 /*
5833 * bring up the interface on which the high preference path lie
5834 */
5835 vnet_sw_interface_set_flags(vnet_get_main(),
5836 tm->hw[0]->sw_if_index,
5837 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5838
5839 FIB_TEST(fib_test_validate_entry(fei,
5840 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5841 2,
5842 &ip_hi_1,
5843 &ip_hi_2),
5844 "1.1.1.1/32 via high preference paths");
5845
5846 /*
5847 * bring up the interface on which the medium preference path lie
5848 */
5849 vnet_sw_interface_set_flags(vnet_get_main(),
5850 tm->hw[1]->sw_if_index,
5851 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
5852
5853 FIB_TEST(fib_test_validate_entry(fei,
5854 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5855 2,
5856 &ip_hi_1,
5857 &ip_hi_2),
5858 "1.1.1.1/32 via high preference paths");
5859
5860 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
5861 fib_entry_contribute_forwarding(fei,
5862 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5863 &ip_1_1_1_1);
5864
5865 /*
5866 * 3 recursive paths of different preference
5867 */
5868 const fib_prefix_t pfx_1_1_1_2_s_32 = {
5869 .fp_len = 32,
5870 .fp_proto = FIB_PROTOCOL_IP4,
5871 .fp_addr = {
5872 .ip4 = {
5873 .as_u32 = clib_host_to_net_u32(0x01010102),
5874 },
5875 },
5876 };
5877 const fib_prefix_t pfx_1_1_1_3_s_32 = {
5878 .fp_len = 32,
5879 .fp_proto = FIB_PROTOCOL_IP4,
5880 .fp_addr = {
5881 .ip4 = {
5882 .as_u32 = clib_host_to_net_u32(0x01010103),
5883 },
5884 },
5885 };
5886 fei = fib_table_entry_path_add2(0,
5887 &pfx_1_1_1_2_s_32,
5888 FIB_SOURCE_API,
5889 FIB_ENTRY_FLAG_NONE,
5890 nr_paths);
5891 dpo_id_t ip_1_1_1_2 = DPO_INVALID;
5892 fib_entry_contribute_forwarding(fei,
5893 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5894 &ip_1_1_1_2);
5895 fei = fib_table_entry_path_add2(0,
5896 &pfx_1_1_1_3_s_32,
5897 FIB_SOURCE_API,
5898 FIB_ENTRY_FLAG_NONE,
5899 nr_paths);
5900 dpo_id_t ip_1_1_1_3 = DPO_INVALID;
5901 fib_entry_contribute_forwarding(fei,
5902 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5903 &ip_1_1_1_3);
5904
5905 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
5906 .type = FT_LB_O_LB,
5907 .lb = {
5908 .lb = ip_1_1_1_1.dpoi_index,
5909 },
5910 };
5911 fib_test_lb_bucket_t ip_o_1_1_1_2 = {
5912 .type = FT_LB_O_LB,
5913 .lb = {
5914 .lb = ip_1_1_1_2.dpoi_index,
5915 },
5916 };
5917 fib_test_lb_bucket_t ip_o_1_1_1_3 = {
5918 .type = FT_LB_O_LB,
5919 .lb = {
5920 .lb = ip_1_1_1_3.dpoi_index,
5921 },
5922 };
5923 fib_route_path_t r_path_hi = {
Neale Rannsda78f952017-05-24 09:15:43 -07005924 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005925 .frp_sw_if_index = ~0,
5926 .frp_fib_index = 0,
5927 .frp_weight = 1,
5928 .frp_preference = 0,
5929 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5930 .frp_addr = pfx_1_1_1_1_s_32.fp_addr,
5931 };
5932 fib_route_path_t r_path_med = {
Neale Rannsda78f952017-05-24 09:15:43 -07005933 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005934 .frp_sw_if_index = ~0,
5935 .frp_fib_index = 0,
5936 .frp_weight = 1,
5937 .frp_preference = 10,
5938 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
5939 .frp_addr = pfx_1_1_1_2_s_32.fp_addr,
5940 };
5941 fib_route_path_t r_path_low = {
Neale Rannsda78f952017-05-24 09:15:43 -07005942 .frp_proto = DPO_PROTO_IP4,
Neale Ranns57b58602017-07-15 07:37:25 -07005943 .frp_sw_if_index = ~0,
5944 .frp_fib_index = 0,
5945 .frp_weight = 1,
Neale Rannsa0a908f2017-08-01 11:40:03 -07005946 .frp_preference = 255,
Neale Ranns57b58602017-07-15 07:37:25 -07005947 .frp_flags = FIB_ROUTE_PATH_RESOLVE_VIA_HOST,
5948 .frp_addr = pfx_1_1_1_3_s_32.fp_addr,
5949 };
5950 fib_route_path_t *r_paths = NULL;
5951
5952 vec_add1(r_paths, r_path_hi);
5953 vec_add1(r_paths, r_path_low);
5954 vec_add1(r_paths, r_path_med);
5955
5956 /*
5957 * add many recursive so we get the LB MAp created
5958 */
5959 #define N_PFXS 64
5960 fib_prefix_t pfx_r[N_PFXS];
Marek Gradzkiaf095512017-08-15 07:38:26 +02005961 unsigned int n_pfxs;
Neale Ranns57b58602017-07-15 07:37:25 -07005962 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
5963 {
5964 pfx_r[n_pfxs].fp_len = 32;
5965 pfx_r[n_pfxs].fp_proto = FIB_PROTOCOL_IP4;
5966 pfx_r[n_pfxs].fp_addr.ip4.as_u32 =
5967 clib_host_to_net_u32(0x02000000 + n_pfxs);
5968
5969 fei = fib_table_entry_path_add2(0,
5970 &pfx_r[n_pfxs],
5971 FIB_SOURCE_API,
5972 FIB_ENTRY_FLAG_NONE,
5973 r_paths);
5974
5975 FIB_TEST(fib_test_validate_entry(fei,
5976 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5977 1,
5978 &ip_o_1_1_1_1),
5979 "recursive via high preference paths");
5980
5981 /*
5982 * withdraw hig pref resolving entry
5983 */
5984 fib_table_entry_delete(0,
5985 &pfx_1_1_1_1_s_32,
5986 FIB_SOURCE_API);
5987
5988 /* suspend so the update walk kicks int */
5989 vlib_process_suspend(vlib_get_main(), 1e-5);
5990
5991 FIB_TEST(fib_test_validate_entry(fei,
5992 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
5993 1,
5994 &ip_o_1_1_1_2),
5995 "recursive via medium preference paths");
5996
5997 /*
5998 * withdraw medium pref resolving entry
5999 */
6000 fib_table_entry_delete(0,
6001 &pfx_1_1_1_2_s_32,
6002 FIB_SOURCE_API);
6003
6004 /* suspend so the update walk kicks int */
6005 vlib_process_suspend(vlib_get_main(), 1e-5);
6006
6007 FIB_TEST(fib_test_validate_entry(fei,
6008 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6009 1,
6010 &ip_o_1_1_1_3),
6011 "recursive via low preference paths");
6012
6013 /*
6014 * add back paths for next iteration
6015 */
6016 fei = fib_table_entry_update(0,
6017 &pfx_1_1_1_2_s_32,
6018 FIB_SOURCE_API,
6019 FIB_ENTRY_FLAG_NONE,
6020 nr_paths);
6021 fei = fib_table_entry_update(0,
6022 &pfx_1_1_1_1_s_32,
6023 FIB_SOURCE_API,
6024 FIB_ENTRY_FLAG_NONE,
6025 nr_paths);
6026
6027 /* suspend so the update walk kicks int */
6028 vlib_process_suspend(vlib_get_main(), 1e-5);
6029
6030 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6031 FIB_TEST(fib_test_validate_entry(fei,
6032 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6033 1,
6034 &ip_o_1_1_1_1),
6035 "recursive via high preference paths");
6036 }
6037
6038
6039 fib_table_entry_delete(0,
6040 &pfx_1_1_1_1_s_32,
6041 FIB_SOURCE_API);
6042
6043 /* suspend so the update walk kicks int */
6044 vlib_process_suspend(vlib_get_main(), 1e-5);
6045
6046 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6047 {
6048 fei = fib_table_lookup_exact_match(0, &pfx_r[n_pfxs]);
6049
6050 FIB_TEST(fib_test_validate_entry(fei,
6051 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6052 1,
6053 &ip_o_1_1_1_2),
6054 "recursive via medium preference paths");
6055 }
6056 for (n_pfxs = 0; n_pfxs < N_PFXS; n_pfxs++)
6057 {
6058 fib_table_entry_delete(0,
6059 &pfx_r[n_pfxs],
6060 FIB_SOURCE_API);
6061 }
6062
6063 /*
6064 * Cleanup
6065 */
6066 fib_table_entry_delete(0,
6067 &pfx_1_1_1_2_s_32,
6068 FIB_SOURCE_API);
6069 fib_table_entry_delete(0,
6070 &pfx_1_1_1_3_s_32,
6071 FIB_SOURCE_API);
6072
6073 dpo_reset(&ip_1_1_1_1);
6074 dpo_reset(&ip_1_1_1_2);
6075 dpo_reset(&ip_1_1_1_3);
6076 adj_unlock(ai_low_2);
6077 adj_unlock(ai_low_1);
6078 adj_unlock(ai_med_2);
6079 adj_unlock(ai_med_1);
6080 adj_unlock(ai_hi_2);
6081 adj_unlock(ai_hi_1);
6082 return (0);
6083}
Neale Rannsad422ed2016-11-02 14:20:04 +00006084
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006085/*
6086 * Test the recursive route route handling for GRE tunnels
6087 */
Neale Ranns0ebe8d72016-12-08 19:48:11 +00006088static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006089fib_test_label (void)
6090{
6091 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;
6092 const u32 fib_index = 0;
6093 test_main_t *tm;
6094 ip4_main_t *im;
Neale Rannsad422ed2016-11-02 14:20:04 +00006095 int lb_count, ii;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006096
6097 lb_count = pool_elts(load_balance_pool);
6098 tm = &test_main;
6099 im = &ip4_main;
6100
6101 /*
6102 * add interface routes. We'll assume this works. It's more rigorously
6103 * tested elsewhere.
6104 */
6105 fib_prefix_t local0_pfx = {
6106 .fp_len = 24,
6107 .fp_proto = FIB_PROTOCOL_IP4,
6108 .fp_addr = {
6109 .ip4 = {
6110 /* 10.10.10.10 */
6111 .as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
6112 },
6113 },
6114 };
6115
6116 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
6117 adj_nbr_db_size());
6118
6119 vec_validate(im->fib_index_by_sw_if_index, tm->hw[0]->sw_if_index);
6120 im->fib_index_by_sw_if_index[tm->hw[0]->sw_if_index] = fib_index;
6121
6122 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6123 FIB_SOURCE_INTERFACE,
6124 (FIB_ENTRY_FLAG_CONNECTED |
6125 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006126 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006127 NULL,
6128 tm->hw[0]->sw_if_index,
6129 ~0,
6130 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006131 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006132 FIB_ROUTE_PATH_FLAG_NONE);
6133 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6134 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6135 "attached interface route present");
6136
6137 local0_pfx.fp_len = 32;
6138 fib_table_entry_update_one_path(fib_index, &local0_pfx,
6139 FIB_SOURCE_INTERFACE,
6140 (FIB_ENTRY_FLAG_CONNECTED |
6141 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006142 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006143 NULL,
6144 tm->hw[0]->sw_if_index,
6145 ~0, // invalid fib index
6146 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006147 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006148 FIB_ROUTE_PATH_FLAG_NONE);
6149 fei = fib_table_lookup_exact_match(fib_index, &local0_pfx);
6150
6151 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6152 "local interface route present");
6153
6154 fib_prefix_t local1_pfx = {
6155 .fp_len = 24,
6156 .fp_proto = FIB_PROTOCOL_IP4,
6157 .fp_addr = {
6158 .ip4 = {
6159 /* 10.10.11.10 */
6160 .as_u32 = clib_host_to_net_u32(0x0a0a0b0a),
6161 },
6162 },
6163 };
6164
6165 vec_validate(im->fib_index_by_sw_if_index, tm->hw[1]->sw_if_index);
6166 im->fib_index_by_sw_if_index[tm->hw[1]->sw_if_index] = fib_index;
6167
6168 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6169 FIB_SOURCE_INTERFACE,
6170 (FIB_ENTRY_FLAG_CONNECTED |
6171 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07006172 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006173 NULL,
6174 tm->hw[1]->sw_if_index,
6175 ~0,
6176 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006177 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006178 FIB_ROUTE_PATH_FLAG_NONE);
6179 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6180 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6181 "attached interface route present");
6182
6183 local1_pfx.fp_len = 32;
6184 fib_table_entry_update_one_path(fib_index, &local1_pfx,
6185 FIB_SOURCE_INTERFACE,
6186 (FIB_ENTRY_FLAG_CONNECTED |
6187 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07006188 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006189 NULL,
6190 tm->hw[1]->sw_if_index,
6191 ~0, // invalid fib index
6192 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006193 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006194 FIB_ROUTE_PATH_FLAG_NONE);
6195 fei = fib_table_lookup_exact_match(fib_index, &local1_pfx);
6196
6197 FIB_TEST((FIB_NODE_INDEX_INVALID != fei),
6198 "local interface route present");
6199
6200 ip46_address_t nh_10_10_10_1 = {
6201 .ip4 = {
6202 .as_u32 = clib_host_to_net_u32(0x0a0a0a01),
6203 },
6204 };
6205 ip46_address_t nh_10_10_11_1 = {
6206 .ip4 = {
6207 .as_u32 = clib_host_to_net_u32(0x0a0a0b01),
6208 },
6209 };
6210 ip46_address_t nh_10_10_11_2 = {
6211 .ip4 = {
6212 .as_u32 = clib_host_to_net_u32(0x0a0a0b02),
6213 },
6214 };
6215
6216 ai_v4_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006217 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006218 &nh_10_10_11_1,
6219 tm->hw[1]->sw_if_index);
6220 ai_v4_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006221 VNET_LINK_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006222 &nh_10_10_11_2,
6223 tm->hw[1]->sw_if_index);
6224 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006225 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006226 &nh_10_10_10_1,
6227 tm->hw[0]->sw_if_index);
6228 ai_mpls_10_10_11_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006229 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006230 &nh_10_10_11_2,
6231 tm->hw[1]->sw_if_index);
6232 ai_mpls_10_10_11_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
Neale Ranns924d03a2016-10-19 08:25:46 +01006233 VNET_LINK_MPLS,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006234 &nh_10_10_11_1,
6235 tm->hw[1]->sw_if_index);
6236
6237 /*
6238 * Add an etry with one path with a real out-going label
6239 */
6240 fib_prefix_t pfx_1_1_1_1_s_32 = {
6241 .fp_len = 32,
6242 .fp_proto = FIB_PROTOCOL_IP4,
6243 .fp_addr = {
6244 .ip4.as_u32 = clib_host_to_net_u32(0x01010101),
6245 },
6246 };
6247 fib_test_lb_bucket_t l99_eos_o_10_10_10_1 = {
6248 .type = FT_LB_LABEL_O_ADJ,
6249 .label_o_adj = {
6250 .adj = ai_mpls_10_10_10_1,
6251 .label = 99,
6252 .eos = MPLS_EOS,
6253 },
6254 };
6255 fib_test_lb_bucket_t l99_neos_o_10_10_10_1 = {
6256 .type = FT_LB_LABEL_O_ADJ,
6257 .label_o_adj = {
6258 .adj = ai_mpls_10_10_10_1,
6259 .label = 99,
6260 .eos = MPLS_NON_EOS,
6261 },
6262 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006263 mpls_label_t *l99 = NULL;
6264 vec_add1(l99, 99);
6265
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006266 fib_table_entry_update_one_path(fib_index,
6267 &pfx_1_1_1_1_s_32,
6268 FIB_SOURCE_API,
6269 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006270 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006271 &nh_10_10_10_1,
6272 tm->hw[0]->sw_if_index,
6273 ~0, // invalid fib index
6274 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006275 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006276 FIB_ROUTE_PATH_FLAG_NONE);
6277
6278 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6279 FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "1.1.1.1/32 created");
6280
6281 FIB_TEST(fib_test_validate_entry(fei,
6282 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6283 1,
6284 &l99_eos_o_10_10_10_1),
6285 "1.1.1.1/32 LB 1 bucket via label 99 over 10.10.10.1");
6286
6287 /*
6288 * add a path with an implicit NULL label
6289 */
6290 fib_test_lb_bucket_t a_o_10_10_11_1 = {
6291 .type = FT_LB_ADJ,
6292 .adj = {
6293 .adj = ai_v4_10_10_11_1,
6294 },
6295 };
6296 fib_test_lb_bucket_t a_mpls_o_10_10_11_1 = {
6297 .type = FT_LB_ADJ,
6298 .adj = {
6299 .adj = ai_mpls_10_10_11_1,
6300 },
6301 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006302 mpls_label_t *l_imp_null = NULL;
6303 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006304
6305 fei = fib_table_entry_path_add(fib_index,
6306 &pfx_1_1_1_1_s_32,
6307 FIB_SOURCE_API,
6308 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006309 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006310 &nh_10_10_11_1,
6311 tm->hw[1]->sw_if_index,
6312 ~0, // invalid fib index
6313 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006314 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006315 FIB_ROUTE_PATH_FLAG_NONE);
6316
6317 FIB_TEST(fib_test_validate_entry(fei,
6318 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6319 2,
6320 &l99_eos_o_10_10_10_1,
6321 &a_o_10_10_11_1),
6322 "1.1.1.1/32 LB 2 buckets via: "
6323 "label 99 over 10.10.10.1, "
6324 "adj over 10.10.11.1");
6325
6326 /*
6327 * assign the route a local label
6328 */
6329 fib_table_entry_local_label_add(fib_index,
6330 &pfx_1_1_1_1_s_32,
6331 24001);
6332
6333 fib_prefix_t pfx_24001_eos = {
6334 .fp_proto = FIB_PROTOCOL_MPLS,
6335 .fp_label = 24001,
6336 .fp_eos = MPLS_EOS,
6337 };
6338 fib_prefix_t pfx_24001_neos = {
6339 .fp_proto = FIB_PROTOCOL_MPLS,
6340 .fp_label = 24001,
6341 .fp_eos = MPLS_NON_EOS,
6342 };
6343
6344 /*
6345 * The EOS entry should link to both the paths,
6346 * and use an ip adj for the imp-null
6347 * The NON-EOS entry should link to both the paths,
6348 * and use an mpls adj for the imp-null
6349 */
6350 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6351 &pfx_24001_eos);
6352 FIB_TEST(fib_test_validate_entry(fei,
6353 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6354 2,
6355 &l99_eos_o_10_10_10_1,
6356 &a_o_10_10_11_1),
6357 "24001/eos LB 2 buckets via: "
6358 "label 99 over 10.10.10.1, "
6359 "adj over 10.10.11.1");
6360
6361
6362 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6363 &pfx_24001_neos);
6364 FIB_TEST(fib_test_validate_entry(fei,
6365 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6366 2,
6367 &l99_neos_o_10_10_10_1,
6368 &a_mpls_o_10_10_11_1),
6369 "24001/neos LB 1 bucket via: "
6370 "label 99 over 10.10.10.1 ",
6371 "mpls-adj via 10.10.11.1");
6372
6373 /*
6374 * add an unlabelled path, this is excluded from the neos chains,
6375 */
6376 fib_test_lb_bucket_t adj_o_10_10_11_2 = {
6377 .type = FT_LB_ADJ,
6378 .adj = {
6379 .adj = ai_v4_10_10_11_2,
6380 },
6381 };
6382
6383 fei = fib_table_entry_path_add(fib_index,
6384 &pfx_1_1_1_1_s_32,
6385 FIB_SOURCE_API,
6386 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006387 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006388 &nh_10_10_11_2,
6389 tm->hw[1]->sw_if_index,
6390 ~0, // invalid fib index
6391 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006392 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006393 FIB_ROUTE_PATH_FLAG_NONE);
6394
6395 FIB_TEST(fib_test_validate_entry(fei,
6396 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6397 16, // 3 choices spread over 16 buckets
6398 &l99_eos_o_10_10_10_1,
6399 &l99_eos_o_10_10_10_1,
6400 &l99_eos_o_10_10_10_1,
6401 &l99_eos_o_10_10_10_1,
6402 &l99_eos_o_10_10_10_1,
6403 &l99_eos_o_10_10_10_1,
6404 &a_o_10_10_11_1,
6405 &a_o_10_10_11_1,
6406 &a_o_10_10_11_1,
6407 &a_o_10_10_11_1,
6408 &a_o_10_10_11_1,
6409 &adj_o_10_10_11_2,
6410 &adj_o_10_10_11_2,
6411 &adj_o_10_10_11_2,
6412 &adj_o_10_10_11_2,
6413 &adj_o_10_10_11_2),
6414 "1.1.1.1/32 LB 16 buckets via: "
6415 "label 99 over 10.10.10.1, "
6416 "adj over 10.10.11.1",
6417 "adj over 10.10.11.2");
6418
6419 /*
6420 * get and lock a reference to the non-eos of the via entry 1.1.1.1/32
6421 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006422 dpo_id_t non_eos_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006423 fib_entry_contribute_forwarding(fei,
6424 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6425 &non_eos_1_1_1_1);
6426
6427 /*
6428 * n-eos has only the 2 labelled paths
6429 */
6430 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6431 &pfx_24001_neos);
6432
6433 FIB_TEST(fib_test_validate_entry(fei,
6434 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6435 2,
6436 &l99_neos_o_10_10_10_1,
6437 &a_mpls_o_10_10_11_1),
6438 "24001/neos LB 2 buckets via: "
6439 "label 99 over 10.10.10.1, "
6440 "adj-mpls over 10.10.11.2");
6441
6442 /*
6443 * A labelled recursive
6444 */
6445 fib_prefix_t pfx_2_2_2_2_s_32 = {
6446 .fp_len = 32,
6447 .fp_proto = FIB_PROTOCOL_IP4,
6448 .fp_addr = {
6449 .ip4.as_u32 = clib_host_to_net_u32(0x02020202),
6450 },
6451 };
6452 fib_test_lb_bucket_t l1600_eos_o_1_1_1_1 = {
6453 .type = FT_LB_LABEL_O_LB,
6454 .label_o_lb = {
6455 .lb = non_eos_1_1_1_1.dpoi_index,
6456 .label = 1600,
6457 .eos = MPLS_EOS,
6458 },
6459 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006460 mpls_label_t *l1600 = NULL;
6461 vec_add1(l1600, 1600);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006462
6463 fib_table_entry_update_one_path(fib_index,
6464 &pfx_2_2_2_2_s_32,
6465 FIB_SOURCE_API,
6466 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006467 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006468 &pfx_1_1_1_1_s_32.fp_addr,
6469 ~0,
6470 fib_index,
6471 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006472 l1600,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006473 FIB_ROUTE_PATH_FLAG_NONE);
6474
6475 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6476 FIB_TEST(fib_test_validate_entry(fei,
6477 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6478 1,
6479 &l1600_eos_o_1_1_1_1),
6480 "2.2.2.2.2/32 LB 1 buckets via: "
6481 "label 1600 over 1.1.1.1");
6482
Neale Ranns948e00f2016-10-20 13:39:34 +01006483 dpo_id_t dpo_44 = DPO_INVALID;
Neale Ranns3ee44042016-10-03 13:05:48 +01006484 index_t urpfi;
6485
6486 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_UNICAST_IP4, &dpo_44);
6487 urpfi = load_balance_get_urpf(dpo_44.dpoi_index);
6488
6489 FIB_TEST(fib_urpf_check(urpfi, tm->hw[0]->sw_if_index),
6490 "uRPF check for 2.2.2.2/32 on %d OK",
6491 tm->hw[0]->sw_if_index);
6492 FIB_TEST(fib_urpf_check(urpfi, tm->hw[1]->sw_if_index),
6493 "uRPF check for 2.2.2.2/32 on %d OK",
6494 tm->hw[1]->sw_if_index);
6495 FIB_TEST(!fib_urpf_check(urpfi, 99),
6496 "uRPF check for 2.2.2.2/32 on 99 not-OK",
6497 99);
6498
6499 fib_entry_contribute_forwarding(fei, FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS, &dpo_44);
6500 FIB_TEST(urpfi == load_balance_get_urpf(dpo_44.dpoi_index),
6501 "Shared uRPF on IP and non-EOS chain");
6502
6503 dpo_reset(&dpo_44);
6504
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006505 /*
6506 * we are holding a lock on the non-eos LB of the via-entry.
6507 * do a PIC-core failover by shutting the link of the via-entry.
6508 *
6509 * shut down the link with the valid label
6510 */
6511 vnet_sw_interface_set_flags(vnet_get_main(),
6512 tm->hw[0]->sw_if_index,
6513 0);
6514
6515 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6516 FIB_TEST(fib_test_validate_entry(fei,
6517 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6518 2,
6519 &a_o_10_10_11_1,
6520 &adj_o_10_10_11_2),
6521 "1.1.1.1/32 LB 2 buckets via: "
6522 "adj over 10.10.11.1, ",
6523 "adj-v4 over 10.10.11.2");
6524
6525 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6526 &pfx_24001_eos);
6527 FIB_TEST(fib_test_validate_entry(fei,
6528 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6529 2,
6530 &a_o_10_10_11_1,
6531 &adj_o_10_10_11_2),
6532 "24001/eos LB 2 buckets via: "
6533 "adj over 10.10.11.1, ",
6534 "adj-v4 over 10.10.11.2");
6535
6536 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6537 &pfx_24001_neos);
6538 FIB_TEST(fib_test_validate_entry(fei,
6539 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6540 1,
6541 &a_mpls_o_10_10_11_1),
6542 "24001/neos LB 1 buckets via: "
6543 "adj-mpls over 10.10.11.2");
6544
6545 /*
6546 * test that the pre-failover load-balance has been in-place
6547 * modified
6548 */
Neale Ranns948e00f2016-10-20 13:39:34 +01006549 dpo_id_t current = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006550 fib_entry_contribute_forwarding(fei,
6551 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6552 &current);
6553
6554 FIB_TEST(!dpo_cmp(&non_eos_1_1_1_1,
6555 &current),
6556 "PIC-core LB inplace modified %U %U",
6557 format_dpo_id, &non_eos_1_1_1_1, 0,
6558 format_dpo_id, &current, 0);
6559
6560 dpo_reset(&non_eos_1_1_1_1);
6561 dpo_reset(&current);
6562
6563 /*
6564 * no-shut the link with the valid label
6565 */
6566 vnet_sw_interface_set_flags(vnet_get_main(),
6567 tm->hw[0]->sw_if_index,
6568 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
6569
6570 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6571 FIB_TEST(fib_test_validate_entry(fei,
6572 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6573 16, // 3 choices spread over 16 buckets
6574 &l99_eos_o_10_10_10_1,
6575 &l99_eos_o_10_10_10_1,
6576 &l99_eos_o_10_10_10_1,
6577 &l99_eos_o_10_10_10_1,
6578 &l99_eos_o_10_10_10_1,
6579 &l99_eos_o_10_10_10_1,
6580 &a_o_10_10_11_1,
6581 &a_o_10_10_11_1,
6582 &a_o_10_10_11_1,
6583 &a_o_10_10_11_1,
6584 &a_o_10_10_11_1,
6585 &adj_o_10_10_11_2,
6586 &adj_o_10_10_11_2,
6587 &adj_o_10_10_11_2,
6588 &adj_o_10_10_11_2,
6589 &adj_o_10_10_11_2),
6590 "1.1.1.1/32 LB 16 buckets via: "
6591 "label 99 over 10.10.10.1, "
6592 "adj over 10.10.11.1",
6593 "adj-v4 over 10.10.11.2");
6594
6595
6596 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6597 &pfx_24001_eos);
6598 FIB_TEST(fib_test_validate_entry(fei,
6599 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6600 16, // 3 choices spread over 16 buckets
6601 &l99_eos_o_10_10_10_1,
6602 &l99_eos_o_10_10_10_1,
6603 &l99_eos_o_10_10_10_1,
6604 &l99_eos_o_10_10_10_1,
6605 &l99_eos_o_10_10_10_1,
6606 &l99_eos_o_10_10_10_1,
6607 &a_o_10_10_11_1,
6608 &a_o_10_10_11_1,
6609 &a_o_10_10_11_1,
6610 &a_o_10_10_11_1,
6611 &a_o_10_10_11_1,
6612 &adj_o_10_10_11_2,
6613 &adj_o_10_10_11_2,
6614 &adj_o_10_10_11_2,
6615 &adj_o_10_10_11_2,
6616 &adj_o_10_10_11_2),
6617 "24001/eos LB 16 buckets via: "
6618 "label 99 over 10.10.10.1, "
6619 "adj over 10.10.11.1",
6620 "adj-v4 over 10.10.11.2");
6621
6622 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6623 &pfx_24001_neos);
6624 FIB_TEST(fib_test_validate_entry(fei,
6625 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6626 2,
6627 &l99_neos_o_10_10_10_1,
6628 &a_mpls_o_10_10_11_1),
6629 "24001/neos LB 2 buckets via: "
6630 "label 99 over 10.10.10.1, "
6631 "adj-mpls over 10.10.11.2");
6632
6633 /*
6634 * remove the first path with the valid label
6635 */
6636 fib_table_entry_path_remove(fib_index,
6637 &pfx_1_1_1_1_s_32,
6638 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006639 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006640 &nh_10_10_10_1,
6641 tm->hw[0]->sw_if_index,
6642 ~0, // invalid fib index
6643 1,
6644 FIB_ROUTE_PATH_FLAG_NONE);
6645
6646 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6647 FIB_TEST(fib_test_validate_entry(fei,
6648 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6649 2,
6650 &a_o_10_10_11_1,
6651 &adj_o_10_10_11_2),
6652 "1.1.1.1/32 LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006653 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006654 "adj-v4 over 10.10.11.2");
6655
6656 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6657 &pfx_24001_eos);
6658 FIB_TEST(fib_test_validate_entry(fei,
6659 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6660 2,
6661 &a_o_10_10_11_1,
6662 &adj_o_10_10_11_2),
6663 "24001/eos LB 2 buckets via: "
Neale Rannsa3af3372017-03-28 03:49:52 -07006664 "adj over 10.10.11.1, "
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006665 "adj-v4 over 10.10.11.2");
6666
6667 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6668 &pfx_24001_neos);
6669
6670 FIB_TEST(fib_test_validate_entry(fei,
6671 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6672 1,
6673 &a_mpls_o_10_10_11_1),
6674 "24001/neos LB 1 buckets via: "
6675 "adj-mpls over 10.10.11.2");
6676
6677 /*
6678 * remove the other path with a valid label
6679 */
6680 fib_test_lb_bucket_t bucket_drop = {
6681 .type = FT_LB_SPECIAL,
6682 .special = {
Neale Ranns8fe8cc22016-11-01 10:05:08 +00006683 .adj = DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006684 },
6685 };
Neale Rannsf12a83f2017-04-18 09:09:40 -07006686 fib_test_lb_bucket_t mpls_bucket_drop = {
6687 .type = FT_LB_SPECIAL,
6688 .special = {
6689 .adj = DPO_PROTO_MPLS,
6690 },
6691 };
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006692
6693 fib_table_entry_path_remove(fib_index,
6694 &pfx_1_1_1_1_s_32,
6695 FIB_SOURCE_API,
Neale Rannsda78f952017-05-24 09:15:43 -07006696 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006697 &nh_10_10_11_1,
6698 tm->hw[1]->sw_if_index,
6699 ~0, // invalid fib index
6700 1,
6701 FIB_ROUTE_PATH_FLAG_NONE);
6702
6703 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6704 FIB_TEST(fib_test_validate_entry(fei,
6705 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6706 1,
6707 &adj_o_10_10_11_2),
6708 "1.1.1.1/32 LB 1 buckets via: "
6709 "adj over 10.10.11.2");
6710
6711 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6712 &pfx_24001_eos);
6713 FIB_TEST(fib_test_validate_entry(fei,
6714 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6715 1,
6716 &adj_o_10_10_11_2),
6717 "24001/eos LB 1 buckets via: "
6718 "adj over 10.10.11.2");
6719
6720 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6721 &pfx_24001_neos);
6722 FIB_TEST(fib_test_validate_entry(fei,
6723 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
Neale Rannsf12a83f2017-04-18 09:09:40 -07006724 1,
6725 &mpls_bucket_drop),
6726 "24001/neos LB 1 buckets via: DROP");
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006727
6728 /*
6729 * add back the path with the valid label
6730 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006731 l99 = NULL;
6732 vec_add1(l99, 99);
6733
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006734 fib_table_entry_path_add(fib_index,
6735 &pfx_1_1_1_1_s_32,
6736 FIB_SOURCE_API,
6737 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006738 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006739 &nh_10_10_10_1,
6740 tm->hw[0]->sw_if_index,
6741 ~0, // invalid fib index
6742 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006743 l99,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006744 FIB_ROUTE_PATH_FLAG_NONE);
6745
6746 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6747 FIB_TEST(fib_test_validate_entry(fei,
6748 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6749 2,
6750 &l99_eos_o_10_10_10_1,
6751 &adj_o_10_10_11_2),
6752 "1.1.1.1/32 LB 2 buckets via: "
6753 "label 99 over 10.10.10.1, "
6754 "adj over 10.10.11.2");
6755
6756 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6757 &pfx_24001_eos);
6758 FIB_TEST(fib_test_validate_entry(fei,
6759 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6760 2,
6761 &l99_eos_o_10_10_10_1,
6762 &adj_o_10_10_11_2),
6763 "24001/eos LB 2 buckets via: "
6764 "label 99 over 10.10.10.1, "
6765 "adj over 10.10.11.2");
6766
6767 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6768 &pfx_24001_neos);
6769 FIB_TEST(fib_test_validate_entry(fei,
6770 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6771 1,
6772 &l99_neos_o_10_10_10_1),
6773 "24001/neos LB 1 buckets via: "
6774 "label 99 over 10.10.10.1");
6775
6776 /*
Neale Ranns1357f3b2016-10-16 12:01:42 -07006777 * change the local label
6778 */
6779 fib_table_entry_local_label_add(fib_index,
6780 &pfx_1_1_1_1_s_32,
6781 25005);
6782
6783 fib_prefix_t pfx_25005_eos = {
6784 .fp_proto = FIB_PROTOCOL_MPLS,
6785 .fp_label = 25005,
6786 .fp_eos = MPLS_EOS,
6787 };
6788 fib_prefix_t pfx_25005_neos = {
6789 .fp_proto = FIB_PROTOCOL_MPLS,
6790 .fp_label = 25005,
6791 .fp_eos = MPLS_NON_EOS,
6792 };
6793
6794 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6795 fib_table_lookup(fib_index, &pfx_24001_eos)),
6796 "24001/eos removed after label change");
6797 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6798 fib_table_lookup(fib_index, &pfx_24001_neos)),
6799 "24001/eos removed after label change");
6800
6801 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6802 &pfx_25005_eos);
6803 FIB_TEST(fib_test_validate_entry(fei,
6804 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
6805 2,
6806 &l99_eos_o_10_10_10_1,
6807 &adj_o_10_10_11_2),
6808 "25005/eos LB 2 buckets via: "
6809 "label 99 over 10.10.10.1, "
6810 "adj over 10.10.11.2");
6811
6812 fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
6813 &pfx_25005_neos);
6814 FIB_TEST(fib_test_validate_entry(fei,
6815 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6816 1,
6817 &l99_neos_o_10_10_10_1),
6818 "25005/neos LB 1 buckets via: "
6819 "label 99 over 10.10.10.1");
6820
6821 /*
6822 * remove the local label.
6823 * the check that the MPLS entries are gone is done by the fact the
6824 * MPLS table is no longer present.
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006825 */
6826 fib_table_entry_local_label_remove(fib_index,
6827 &pfx_1_1_1_1_s_32,
Neale Ranns1357f3b2016-10-16 12:01:42 -07006828 25005);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006829
6830 fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
6831 FIB_TEST(fib_test_validate_entry(fei,
6832 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6833 2,
6834 &l99_eos_o_10_10_10_1,
6835 &adj_o_10_10_11_2),
6836 "24001/eos LB 2 buckets via: "
6837 "label 99 over 10.10.10.1, "
6838 "adj over 10.10.11.2");
6839
6840 FIB_TEST((FIB_NODE_INDEX_INVALID ==
6841 mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID)),
6842 "No more MPLS FIB entries => table removed");
6843
6844 /*
6845 * add another via-entry for the recursive
6846 */
6847 fib_prefix_t pfx_1_1_1_2_s_32 = {
6848 .fp_len = 32,
6849 .fp_proto = FIB_PROTOCOL_IP4,
6850 .fp_addr = {
6851 .ip4.as_u32 = clib_host_to_net_u32(0x01010102),
6852 },
6853 };
6854 fib_test_lb_bucket_t l101_eos_o_10_10_10_1 = {
6855 .type = FT_LB_LABEL_O_ADJ,
6856 .label_o_adj = {
6857 .adj = ai_mpls_10_10_10_1,
6858 .label = 101,
6859 .eos = MPLS_EOS,
6860 },
6861 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006862 mpls_label_t *l101 = NULL;
6863 vec_add1(l101, 101);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006864
6865 fei = fib_table_entry_update_one_path(fib_index,
6866 &pfx_1_1_1_2_s_32,
6867 FIB_SOURCE_API,
6868 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006869 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006870 &nh_10_10_10_1,
6871 tm->hw[0]->sw_if_index,
6872 ~0, // invalid fib index
6873 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006874 l101,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006875 FIB_ROUTE_PATH_FLAG_NONE);
6876
6877 FIB_TEST(fib_test_validate_entry(fei,
6878 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6879 1,
6880 &l101_eos_o_10_10_10_1),
6881 "1.1.1.2/32 LB 1 buckets via: "
6882 "label 101 over 10.10.10.1");
6883
Neale Ranns948e00f2016-10-20 13:39:34 +01006884 dpo_id_t non_eos_1_1_1_2 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006885 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6886 &pfx_1_1_1_1_s_32),
6887 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6888 &non_eos_1_1_1_1);
6889 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
6890 &pfx_1_1_1_2_s_32),
6891 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
6892 &non_eos_1_1_1_2);
6893
6894 fib_test_lb_bucket_t l1601_eos_o_1_1_1_2 = {
6895 .type = FT_LB_LABEL_O_LB,
6896 .label_o_lb = {
6897 .lb = non_eos_1_1_1_2.dpoi_index,
6898 .label = 1601,
6899 .eos = MPLS_EOS,
6900 },
6901 };
Neale Rannsad422ed2016-11-02 14:20:04 +00006902 mpls_label_t *l1601 = NULL;
6903 vec_add1(l1601, 1601);
6904
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006905 l1600_eos_o_1_1_1_1.label_o_lb.lb = non_eos_1_1_1_1.dpoi_index;
6906
6907 fei = fib_table_entry_path_add(fib_index,
6908 &pfx_2_2_2_2_s_32,
6909 FIB_SOURCE_API,
6910 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006911 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006912 &pfx_1_1_1_2_s_32.fp_addr,
6913 ~0,
6914 fib_index,
6915 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006916 l1601,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006917 FIB_ROUTE_PATH_FLAG_NONE);
6918
6919 FIB_TEST(fib_test_validate_entry(fei,
6920 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6921 2,
6922 &l1600_eos_o_1_1_1_1,
6923 &l1601_eos_o_1_1_1_2),
6924 "2.2.2.2/32 LB 2 buckets via: "
6925 "label 1600 via 1.1,1.1, "
6926 "label 16001 via 1.1.1.2");
6927
6928 /*
6929 * update the via-entry so it no longer has an imp-null path.
6930 * the LB for the recursive can use an imp-null
6931 */
Neale Rannsad422ed2016-11-02 14:20:04 +00006932 l_imp_null = NULL;
6933 vec_add1(l_imp_null, MPLS_IETF_IMPLICIT_NULL_LABEL);
6934
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006935 fei = fib_table_entry_update_one_path(fib_index,
6936 &pfx_1_1_1_2_s_32,
6937 FIB_SOURCE_API,
6938 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006939 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006940 &nh_10_10_11_1,
6941 tm->hw[1]->sw_if_index,
6942 ~0, // invalid fib index
6943 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006944 l_imp_null,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006945 FIB_ROUTE_PATH_FLAG_NONE);
6946
6947 FIB_TEST(fib_test_validate_entry(fei,
6948 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6949 1,
6950 &a_o_10_10_11_1),
6951 "1.1.1.2/32 LB 1 buckets via: "
6952 "adj 10.10.11.1");
6953
6954 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6955 FIB_TEST(fib_test_validate_entry(fei,
6956 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6957 2,
6958 &l1600_eos_o_1_1_1_1,
6959 &l1601_eos_o_1_1_1_2),
6960 "2.2.2.2/32 LB 2 buckets via: "
6961 "label 1600 via 1.1,1.1, "
6962 "label 16001 via 1.1.1.2");
6963
6964 /*
6965 * update the via-entry so it no longer has labelled paths.
6966 * the LB for the recursive should exclue this via form its LB
6967 */
6968 fei = fib_table_entry_update_one_path(fib_index,
6969 &pfx_1_1_1_2_s_32,
6970 FIB_SOURCE_API,
6971 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07006972 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006973 &nh_10_10_11_1,
6974 tm->hw[1]->sw_if_index,
6975 ~0, // invalid fib index
6976 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00006977 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01006978 FIB_ROUTE_PATH_FLAG_NONE);
6979
6980 FIB_TEST(fib_test_validate_entry(fei,
6981 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6982 1,
6983 &a_o_10_10_11_1),
6984 "1.1.1.2/32 LB 1 buckets via: "
6985 "adj 10.10.11.1");
6986
6987 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
6988 FIB_TEST(fib_test_validate_entry(fei,
6989 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
6990 1,
6991 &l1600_eos_o_1_1_1_1),
6992 "2.2.2.2/32 LB 1 buckets via: "
6993 "label 1600 via 1.1,1.1");
6994
6995 dpo_reset(&non_eos_1_1_1_1);
6996 dpo_reset(&non_eos_1_1_1_2);
6997
6998 /*
6999 * Add a recursive with no out-labels. We expect to use the IP of the via
7000 */
7001 fib_prefix_t pfx_2_2_2_3_s_32 = {
7002 .fp_len = 32,
7003 .fp_proto = FIB_PROTOCOL_IP4,
7004 .fp_addr = {
7005 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
7006 },
7007 };
Neale Ranns948e00f2016-10-20 13:39:34 +01007008 dpo_id_t ip_1_1_1_1 = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007009
7010 fib_table_entry_update_one_path(fib_index,
7011 &pfx_2_2_2_3_s_32,
7012 FIB_SOURCE_API,
7013 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007014 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007015 &pfx_1_1_1_1_s_32.fp_addr,
7016 ~0,
7017 fib_index,
7018 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007019 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007020 FIB_ROUTE_PATH_FLAG_NONE);
7021
7022 fib_entry_contribute_forwarding(fib_table_lookup(fib_index,
7023 &pfx_1_1_1_1_s_32),
7024 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7025 &ip_1_1_1_1);
7026
7027 fib_test_lb_bucket_t ip_o_1_1_1_1 = {
7028 .type = FT_LB_O_LB,
7029 .lb = {
7030 .lb = ip_1_1_1_1.dpoi_index,
7031 },
7032 };
7033
7034 fei = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
7035 FIB_TEST(fib_test_validate_entry(fei,
7036 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7037 1,
7038 &ip_o_1_1_1_1),
7039 "2.2.2.2.3/32 LB 1 buckets via: "
7040 "ip 1.1.1.1");
7041
7042 /*
7043 * Add a recursive with an imp-null out-label.
7044 * We expect to use the IP of the via
7045 */
7046 fib_prefix_t pfx_2_2_2_4_s_32 = {
7047 .fp_len = 32,
7048 .fp_proto = FIB_PROTOCOL_IP4,
7049 .fp_addr = {
7050 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
7051 },
7052 };
7053
7054 fib_table_entry_update_one_path(fib_index,
7055 &pfx_2_2_2_4_s_32,
7056 FIB_SOURCE_API,
7057 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007058 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007059 &pfx_1_1_1_1_s_32.fp_addr,
7060 ~0,
7061 fib_index,
7062 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00007063 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007064 FIB_ROUTE_PATH_FLAG_NONE);
7065
7066 fei = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
7067 FIB_TEST(fib_test_validate_entry(fei,
7068 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7069 1,
7070 &ip_o_1_1_1_1),
7071 "2.2.2.2.4/32 LB 1 buckets via: "
7072 "ip 1.1.1.1");
7073
7074 dpo_reset(&ip_1_1_1_1);
7075
7076 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00007077 * Create an entry with a deep label stack
7078 */
7079 fib_prefix_t pfx_2_2_5_5_s_32 = {
7080 .fp_len = 32,
7081 .fp_proto = FIB_PROTOCOL_IP4,
7082 .fp_addr = {
7083 .ip4.as_u32 = clib_host_to_net_u32(0x02020505),
7084 },
7085 };
7086 fib_test_lb_bucket_t ls_eos_o_10_10_10_1 = {
7087 .type = FT_LB_LABEL_STACK_O_ADJ,
7088 .label_stack_o_adj = {
7089 .adj = ai_mpls_10_10_11_1,
7090 .label_stack_size = 8,
7091 .label_stack = {
7092 200, 201, 202, 203, 204, 205, 206, 207
7093 },
7094 .eos = MPLS_EOS,
7095 },
7096 };
7097 mpls_label_t *label_stack = NULL;
7098 vec_validate(label_stack, 7);
7099 for (ii = 0; ii < 8; ii++)
7100 {
7101 label_stack[ii] = ii + 200;
7102 }
7103
7104 fei = fib_table_entry_update_one_path(fib_index,
7105 &pfx_2_2_5_5_s_32,
7106 FIB_SOURCE_API,
7107 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007108 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00007109 &nh_10_10_11_1,
7110 tm->hw[1]->sw_if_index,
7111 ~0, // invalid fib index
7112 1,
7113 label_stack,
7114 FIB_ROUTE_PATH_FLAG_NONE);
7115
7116 FIB_TEST(fib_test_validate_entry(fei,
7117 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7118 1,
7119 &ls_eos_o_10_10_10_1),
7120 "2.2.5.5/32 LB 1 buckets via: "
7121 "adj 10.10.11.1");
7122 fib_table_entry_delete_index(fei, FIB_SOURCE_API);
7123
7124 /*
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007125 * cleanup
7126 */
7127 fib_table_entry_delete(fib_index,
7128 &pfx_1_1_1_2_s_32,
7129 FIB_SOURCE_API);
7130
7131 fei = fib_table_lookup(fib_index, &pfx_2_2_2_2_s_32);
7132 FIB_TEST(fib_test_validate_entry(fei,
7133 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7134 1,
7135 &l1600_eos_o_1_1_1_1),
7136 "2.2.2.2/32 LB 1 buckets via: "
7137 "label 1600 via 1.1,1.1");
7138
7139 fib_table_entry_delete(fib_index,
7140 &pfx_1_1_1_1_s_32,
7141 FIB_SOURCE_API);
7142
7143 FIB_TEST(fib_test_validate_entry(fei,
7144 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7145 1,
7146 &bucket_drop),
7147 "2.2.2.2/32 LB 1 buckets via: DROP");
7148
7149 fib_table_entry_delete(fib_index,
7150 &pfx_2_2_2_2_s_32,
7151 FIB_SOURCE_API);
7152 fib_table_entry_delete(fib_index,
7153 &pfx_2_2_2_3_s_32,
7154 FIB_SOURCE_API);
7155 fib_table_entry_delete(fib_index,
7156 &pfx_2_2_2_4_s_32,
7157 FIB_SOURCE_API);
7158
7159 adj_unlock(ai_mpls_10_10_10_1);
7160 adj_unlock(ai_mpls_10_10_11_2);
7161 adj_unlock(ai_v4_10_10_11_1);
7162 adj_unlock(ai_v4_10_10_11_2);
7163 adj_unlock(ai_mpls_10_10_11_1);
7164
7165 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
7166 adj_nbr_db_size());
7167
7168 local0_pfx.fp_len = 32;
7169 fib_table_entry_delete(fib_index,
7170 &local0_pfx,
7171 FIB_SOURCE_INTERFACE);
7172 local0_pfx.fp_len = 24;
7173 fib_table_entry_delete(fib_index,
7174 &local0_pfx,
7175 FIB_SOURCE_INTERFACE);
7176 local1_pfx.fp_len = 32;
7177 fib_table_entry_delete(fib_index,
7178 &local1_pfx,
7179 FIB_SOURCE_INTERFACE);
7180 local1_pfx.fp_len = 24;
7181 fib_table_entry_delete(fib_index,
7182 &local1_pfx,
7183 FIB_SOURCE_INTERFACE);
7184
7185 /*
7186 * +1 for the drop LB in the MPLS tables.
7187 */
7188 FIB_TEST(lb_count+1 == pool_elts(load_balance_pool),
7189 "Load-balance resources freed %d of %d",
7190 lb_count+1, pool_elts(load_balance_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007191
7192 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007193}
7194
7195#define N_TEST_CHILDREN 4
7196#define PARENT_INDEX 0
7197
7198typedef struct fib_node_test_t_
7199{
7200 fib_node_t node;
7201 u32 sibling;
7202 u32 index;
7203 fib_node_back_walk_ctx_t *ctxs;
7204 u32 destroyed;
7205} fib_node_test_t;
7206
7207static fib_node_test_t fib_test_nodes[N_TEST_CHILDREN+1];
7208
7209#define PARENT() (&fib_test_nodes[PARENT_INDEX].node)
7210
7211#define FOR_EACH_TEST_CHILD(_tc) \
7212 for (ii = 1, (_tc) = &fib_test_nodes[1]; \
7213 ii < N_TEST_CHILDREN+1; \
7214 ii++, (_tc) = &fib_test_nodes[ii])
7215
7216static fib_node_t *
7217fib_test_child_get_node (fib_node_index_t index)
7218{
7219 return (&fib_test_nodes[index].node);
7220}
7221
7222static int fib_test_walk_spawns_walks;
7223
7224static fib_node_back_walk_rc_t
7225fib_test_child_back_walk_notify (fib_node_t *node,
7226 fib_node_back_walk_ctx_t *ctx)
7227{
7228 fib_node_test_t *tc = (fib_node_test_t*) node;
7229
7230 vec_add1(tc->ctxs, *ctx);
7231
7232 if (1 == fib_test_walk_spawns_walks)
7233 fib_walk_sync(FIB_NODE_TYPE_TEST, tc->index, ctx);
7234 if (2 == fib_test_walk_spawns_walks)
7235 fib_walk_async(FIB_NODE_TYPE_TEST, tc->index,
7236 FIB_WALK_PRIORITY_HIGH, ctx);
7237
7238 return (FIB_NODE_BACK_WALK_CONTINUE);
7239}
7240
7241static void
7242fib_test_child_last_lock_gone (fib_node_t *node)
7243{
7244 fib_node_test_t *tc = (fib_node_test_t *)node;
7245
7246 tc->destroyed = 1;
7247}
7248
7249/**
7250 * The FIB walk's graph node virtual function table
7251 */
7252static const fib_node_vft_t fib_test_child_vft = {
7253 .fnv_get = fib_test_child_get_node,
7254 .fnv_last_lock = fib_test_child_last_lock_gone,
7255 .fnv_back_walk = fib_test_child_back_walk_notify,
7256};
7257
7258/*
7259 * the function (that should have been static but isn't so I can do this)
7260 * that processes the walk from the async queue,
7261 */
7262f64 fib_walk_process_queues(vlib_main_t * vm,
7263 const f64 quota);
7264u32 fib_walk_queue_get_size(fib_walk_priority_t prio);
7265
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007266static int
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007267fib_test_walk (void)
7268{
7269 fib_node_back_walk_ctx_t high_ctx = {}, low_ctx = {};
7270 fib_node_test_t *tc;
7271 vlib_main_t *vm;
7272 u32 ii;
7273
7274 vm = vlib_get_main();
7275 fib_node_register_type(FIB_NODE_TYPE_TEST, &fib_test_child_vft);
7276
7277 /*
7278 * init a fake node on which we will add children
7279 */
7280 fib_node_init(&fib_test_nodes[PARENT_INDEX].node,
7281 FIB_NODE_TYPE_TEST);
7282
7283 FOR_EACH_TEST_CHILD(tc)
7284 {
7285 fib_node_init(&tc->node, FIB_NODE_TYPE_TEST);
7286 fib_node_lock(&tc->node);
7287 tc->ctxs = NULL;
7288 tc->index = ii;
7289 tc->sibling = fib_node_child_add(FIB_NODE_TYPE_TEST,
7290 PARENT_INDEX,
7291 FIB_NODE_TYPE_TEST, ii);
7292 }
7293
7294 /*
7295 * enqueue a walk across the parents children.
7296 */
Neale Ranns450cd302016-11-09 17:49:42 +00007297 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007298
7299 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7300 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7301 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7302 "Parent has %d children pre-walk",
7303 fib_node_list_get_size(PARENT()->fn_children));
7304
7305 /*
7306 * give the walk a large amount of time so it gets to the end
7307 */
7308 fib_walk_process_queues(vm, 1);
7309
7310 FOR_EACH_TEST_CHILD(tc)
7311 {
7312 FIB_TEST(1 == vec_len(tc->ctxs),
7313 "%d child visitsed %d times",
7314 ii, vec_len(tc->ctxs));
7315 vec_free(tc->ctxs);
7316 }
7317 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7318 "Queue is empty post walk");
7319 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7320 "Parent has %d children post walk",
7321 fib_node_list_get_size(PARENT()->fn_children));
7322
7323 /*
7324 * walk again. should be no increase in the number of visits, since
7325 * the walk will have terminated.
7326 */
7327 fib_walk_process_queues(vm, 1);
7328
7329 FOR_EACH_TEST_CHILD(tc)
7330 {
7331 FIB_TEST(0 == vec_len(tc->ctxs),
7332 "%d child visitsed %d times",
7333 ii, vec_len(tc->ctxs));
7334 }
7335
7336 /*
7337 * schedule a low and hig priority walk. expect the high to be performed
7338 * before the low.
7339 * schedule the high prio walk first so that it is further from the head
7340 * of the dependency list. that way it won't merge with the low one.
7341 */
7342 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7343 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7344
7345 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7346 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7347 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7348 FIB_WALK_PRIORITY_LOW, &low_ctx);
7349
7350 fib_walk_process_queues(vm, 1);
7351
7352 FOR_EACH_TEST_CHILD(tc)
7353 {
7354 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7355 "%d child visitsed by high prio walk", ii);
7356 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7357 "%d child visitsed by low prio walk", ii);
7358 vec_free(tc->ctxs);
7359 }
7360 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7361 "Queue is empty post prio walk");
7362 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7363 "Parent has %d children post prio walk",
7364 fib_node_list_get_size(PARENT()->fn_children));
7365
7366 /*
7367 * schedule 2 walks of the same priority that can be megred.
7368 * expect that each child is thus visited only once.
7369 */
7370 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7371 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7372
7373 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7374 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7375 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7376 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7377
7378 fib_walk_process_queues(vm, 1);
7379
7380 FOR_EACH_TEST_CHILD(tc)
7381 {
7382 FIB_TEST(1 == vec_len(tc->ctxs),
7383 "%d child visitsed %d times during merge walk",
7384 ii, vec_len(tc->ctxs));
7385 vec_free(tc->ctxs);
7386 }
7387 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7388 "Queue is empty post merge walk");
7389 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7390 "Parent has %d children post merge walk",
7391 fib_node_list_get_size(PARENT()->fn_children));
7392
7393 /*
7394 * schedule 2 walks of the same priority that cannot be megred.
7395 * expect that each child is thus visited twice and in the order
7396 * in which the walks were scheduled.
7397 */
7398 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
7399 low_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE;
7400
7401 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7402 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7403 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7404 FIB_WALK_PRIORITY_HIGH, &low_ctx);
7405
7406 fib_walk_process_queues(vm, 1);
7407
7408 FOR_EACH_TEST_CHILD(tc)
7409 {
7410 FIB_TEST(high_ctx.fnbw_reason == tc->ctxs[0].fnbw_reason,
7411 "%d child visitsed by high prio walk", ii);
7412 FIB_TEST(low_ctx.fnbw_reason == tc->ctxs[1].fnbw_reason,
7413 "%d child visitsed by low prio walk", ii);
7414 vec_free(tc->ctxs);
7415 }
7416 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7417 "Queue is empty post no-merge walk");
7418 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7419 "Parent has %d children post no-merge walk",
7420 fib_node_list_get_size(PARENT()->fn_children));
7421
7422 /*
7423 * schedule a walk that makes one one child progress.
7424 * we do this by giving the queue draining process zero
7425 * time quanta. it's a do..while loop, so it does something.
7426 */
Neale Ranns450cd302016-11-09 17:49:42 +00007427 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007428
7429 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7430 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7431 fib_walk_process_queues(vm, 0);
7432
7433 FOR_EACH_TEST_CHILD(tc)
7434 {
7435 if (ii == N_TEST_CHILDREN)
7436 {
7437 FIB_TEST(1 == vec_len(tc->ctxs),
7438 "%d child visitsed %d times in zero quanta walk",
7439 ii, vec_len(tc->ctxs));
7440 }
7441 else
7442 {
7443 FIB_TEST(0 == vec_len(tc->ctxs),
7444 "%d child visitsed %d times in 0 quanta walk",
7445 ii, vec_len(tc->ctxs));
7446 }
7447 }
7448 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7449 "Queue is not empty post zero quanta walk");
7450 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7451 "Parent has %d children post zero qunta walk",
7452 fib_node_list_get_size(PARENT()->fn_children));
7453
7454 /*
7455 * another one step
7456 */
7457 fib_walk_process_queues(vm, 0);
7458
7459 FOR_EACH_TEST_CHILD(tc)
7460 {
7461 if (ii >= N_TEST_CHILDREN-1)
7462 {
7463 FIB_TEST(1 == vec_len(tc->ctxs),
7464 "%d child visitsed %d times in 2nd zero quanta walk",
7465 ii, vec_len(tc->ctxs));
7466 }
7467 else
7468 {
7469 FIB_TEST(0 == vec_len(tc->ctxs),
7470 "%d child visitsed %d times in 2nd 0 quanta walk",
7471 ii, vec_len(tc->ctxs));
7472 }
7473 }
7474 FIB_TEST(1 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7475 "Queue is not empty post zero quanta walk");
7476 FIB_TEST(N_TEST_CHILDREN+1 == fib_node_list_get_size(PARENT()->fn_children),
7477 "Parent has %d children post zero qunta walk",
7478 fib_node_list_get_size(PARENT()->fn_children));
7479
7480 /*
7481 * schedule another walk that will catch-up and merge.
7482 */
7483 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7484 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7485 fib_walk_process_queues(vm, 1);
7486
7487 FOR_EACH_TEST_CHILD(tc)
7488 {
7489 if (ii >= N_TEST_CHILDREN-1)
7490 {
7491 FIB_TEST(2 == vec_len(tc->ctxs),
7492 "%d child visitsed %d times in 2nd zero quanta merge walk",
7493 ii, vec_len(tc->ctxs));
7494 vec_free(tc->ctxs);
7495 }
7496 else
7497 {
7498 FIB_TEST(1 == vec_len(tc->ctxs),
7499 "%d child visitsed %d times in 2nd 0 quanta merge walk",
7500 ii, vec_len(tc->ctxs));
7501 vec_free(tc->ctxs);
7502 }
7503 }
7504 FIB_TEST(0 == fib_walk_queue_get_size(FIB_WALK_PRIORITY_HIGH),
7505 "Queue is not empty post 2nd zero quanta merge walk");
7506 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7507 "Parent has %d children post 2nd zero qunta merge walk",
7508 fib_node_list_get_size(PARENT()->fn_children));
7509
7510 /*
7511 * park a async walk in the middle of the list, then have an sync walk catch
7512 * it. same expectations as async catches async.
7513 */
Neale Ranns450cd302016-11-09 17:49:42 +00007514 high_ctx.fnbw_reason = FIB_NODE_BW_REASON_FLAG_RESOLVE;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007515
7516 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7517 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7518
7519 fib_walk_process_queues(vm, 0);
7520 fib_walk_process_queues(vm, 0);
7521
7522 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
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 sync catches async 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 sync catches async 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 * make the parent a child of one of its children, thus inducing a routing loop.
7549 */
7550 fib_test_nodes[PARENT_INDEX].sibling =
7551 fib_node_child_add(FIB_NODE_TYPE_TEST,
7552 1, // the first child
7553 FIB_NODE_TYPE_TEST,
7554 PARENT_INDEX);
7555
7556 /*
7557 * execute a sync walk from the parent. each child visited spawns more sync
7558 * walks. we expect the walk to terminate.
7559 */
7560 fib_test_walk_spawns_walks = 1;
7561
7562 fib_walk_sync(FIB_NODE_TYPE_TEST, PARENT_INDEX, &high_ctx);
7563
7564 FOR_EACH_TEST_CHILD(tc)
7565 {
7566 /*
7567 * child 1 - which is last in the list - has the loop.
7568 * the other children a re thus visitsed first. the we meet
7569 * child 1. we go round the loop again, visting the other children.
7570 * then we meet the walk in the dep list and bail. child 1 is not visitsed
7571 * again.
7572 */
7573 if (1 == ii)
7574 {
7575 FIB_TEST(1 == vec_len(tc->ctxs),
7576 "child %d visitsed %d times during looped sync walk",
7577 ii, vec_len(tc->ctxs));
7578 }
7579 else
7580 {
7581 FIB_TEST(2 == vec_len(tc->ctxs),
7582 "child %d visitsed %d times during looped sync walk",
7583 ii, vec_len(tc->ctxs));
7584 }
7585 vec_free(tc->ctxs);
7586 }
7587 FIB_TEST(N_TEST_CHILDREN == fib_node_list_get_size(PARENT()->fn_children),
7588 "Parent has %d children post sync loop walk",
7589 fib_node_list_get_size(PARENT()->fn_children));
7590
7591 /*
7592 * the walk doesn't reach the max depth because the infra knows that sync
7593 * meets sync implies a loop and bails early.
7594 */
7595 FIB_TEST(high_ctx.fnbw_depth == 9,
7596 "Walk context depth %d post sync loop walk",
7597 high_ctx.fnbw_depth);
7598
7599 /*
7600 * execute an async walk of the graph loop, with each child spawns sync walks
7601 */
7602 high_ctx.fnbw_depth = 0;
7603 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7604 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7605
7606 fib_walk_process_queues(vm, 1);
7607
7608 FOR_EACH_TEST_CHILD(tc)
7609 {
7610 /*
7611 * we don't really care how many times the children are visisted, as long as
7612 * it is more than once.
7613 */
7614 FIB_TEST(1 <= vec_len(tc->ctxs),
7615 "child %d visitsed %d times during looped aync spawns sync walk",
7616 ii, vec_len(tc->ctxs));
7617 vec_free(tc->ctxs);
7618 }
7619
7620 /*
7621 * execute an async walk of the graph loop, with each child spawns async walks
7622 */
7623 fib_test_walk_spawns_walks = 2;
7624 high_ctx.fnbw_depth = 0;
7625 fib_walk_async(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7626 FIB_WALK_PRIORITY_HIGH, &high_ctx);
7627
7628 fib_walk_process_queues(vm, 1);
7629
7630 FOR_EACH_TEST_CHILD(tc)
7631 {
7632 /*
7633 * we don't really care how many times the children are visisted, as long as
7634 * it is more than once.
7635 */
7636 FIB_TEST(1 <= vec_len(tc->ctxs),
7637 "child %d visitsed %d times during looped async spawns async walk",
7638 ii, vec_len(tc->ctxs));
7639 vec_free(tc->ctxs);
7640 }
7641
7642
7643 fib_node_child_remove(FIB_NODE_TYPE_TEST,
7644 1, // the first child
7645 fib_test_nodes[PARENT_INDEX].sibling);
7646
7647 /*
7648 * cleanup
7649 */
7650 FOR_EACH_TEST_CHILD(tc)
7651 {
7652 fib_node_child_remove(FIB_NODE_TYPE_TEST, PARENT_INDEX,
7653 tc->sibling);
7654 fib_node_deinit(&tc->node);
7655 fib_node_unlock(&tc->node);
7656 }
7657 fib_node_deinit(PARENT());
7658
7659 /*
7660 * The parent will be destroyed when the last lock on it goes.
7661 * this test ensures all the walk objects are unlocking it.
7662 */
7663 FIB_TEST((1 == fib_test_nodes[PARENT_INDEX].destroyed),
7664 "Parent was destroyed");
Neale Ranns0ebe8d72016-12-08 19:48:11 +00007665
7666 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01007667}
7668
Neale Ranns88fc83e2017-04-05 08:11:14 -07007669/*
7670 * declaration of the otherwise static callback functions
7671 */
7672void fib_bfd_notify (bfd_listen_event_e event,
7673 const bfd_session_t *session);
7674void adj_bfd_notify (bfd_listen_event_e event,
7675 const bfd_session_t *session);
7676
7677/**
7678 * Test BFD session interaction with FIB
7679 */
7680static int
7681fib_test_bfd (void)
7682{
7683 fib_node_index_t fei;
7684 test_main_t *tm;
7685 int n_feis;
7686
7687 /* via 10.10.10.1 */
7688 ip46_address_t nh_10_10_10_1 = {
7689 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
7690 };
7691 /* via 10.10.10.2 */
7692 ip46_address_t nh_10_10_10_2 = {
7693 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a02),
7694 };
7695 /* via 10.10.10.10 */
7696 ip46_address_t nh_10_10_10_10 = {
7697 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
7698 };
7699 n_feis = fib_entry_pool_size();
7700
7701 tm = &test_main;
7702
7703 /*
7704 * add interface routes. we'll assume this works. it's tested elsewhere
7705 */
7706 fib_prefix_t pfx_10_10_10_10_s_24 = {
7707 .fp_len = 24,
7708 .fp_proto = FIB_PROTOCOL_IP4,
7709 .fp_addr = nh_10_10_10_10,
7710 };
7711
7712 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_24,
7713 FIB_SOURCE_INTERFACE,
7714 (FIB_ENTRY_FLAG_CONNECTED |
7715 FIB_ENTRY_FLAG_ATTACHED),
Neale Rannsda78f952017-05-24 09:15:43 -07007716 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007717 NULL,
7718 tm->hw[0]->sw_if_index,
7719 ~0, // invalid fib index
7720 1, // weight
7721 NULL,
7722 FIB_ROUTE_PATH_FLAG_NONE);
7723
7724 fib_prefix_t pfx_10_10_10_10_s_32 = {
7725 .fp_len = 32,
7726 .fp_proto = FIB_PROTOCOL_IP4,
7727 .fp_addr = nh_10_10_10_10,
7728 };
7729 fib_table_entry_update_one_path(0, &pfx_10_10_10_10_s_32,
7730 FIB_SOURCE_INTERFACE,
7731 (FIB_ENTRY_FLAG_CONNECTED |
7732 FIB_ENTRY_FLAG_LOCAL),
Neale Rannsda78f952017-05-24 09:15:43 -07007733 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007734 NULL,
7735 tm->hw[0]->sw_if_index,
7736 ~0, // invalid fib index
7737 1, // weight
7738 NULL,
7739 FIB_ROUTE_PATH_FLAG_NONE);
7740
7741 /*
7742 * A BFD session via a neighbour we do not yet know
7743 */
7744 bfd_session_t bfd_10_10_10_1 = {
7745 .udp = {
7746 .key = {
7747 .fib_index = 0,
7748 .peer_addr = nh_10_10_10_1,
7749 },
7750 },
7751 .hop_type = BFD_HOP_TYPE_MULTI,
7752 .local_state = BFD_STATE_init,
7753 };
7754
7755 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7756
7757 /*
7758 * A new entry will be created that forwards via the adj
7759 */
7760 adj_index_t ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
7761 VNET_LINK_IP4,
7762 &nh_10_10_10_1,
7763 tm->hw[0]->sw_if_index);
7764 fib_prefix_t pfx_10_10_10_1_s_32 = {
7765 .fp_addr = nh_10_10_10_1,
7766 .fp_len = 32,
7767 .fp_proto = FIB_PROTOCOL_IP4,
7768 };
7769 fib_test_lb_bucket_t adj_o_10_10_10_1 = {
7770 .type = FT_LB_ADJ,
7771 .adj = {
7772 .adj = ai_10_10_10_1,
7773 },
7774 };
7775
7776 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7777 FIB_TEST(fib_test_validate_entry(fei,
7778 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7779 1,
7780 &adj_o_10_10_10_1),
7781 "BFD sourced %U via %U",
7782 format_fib_prefix, &pfx_10_10_10_1_s_32,
7783 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7784
7785 /*
7786 * Delete the BFD session. Expect the fib_entry to be removed
7787 */
7788 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7789
7790 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7791 FIB_TEST(FIB_NODE_INDEX_INVALID == fei,
7792 "BFD sourced %U removed",
7793 format_fib_prefix, &pfx_10_10_10_1_s_32);
7794
7795 /*
7796 * Add the BFD source back
7797 */
7798 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7799
7800 /*
7801 * source the entry via the ADJ fib
7802 */
Neale Ranns81424992017-05-18 03:03:22 -07007803 fei = fib_table_entry_path_add(0,
7804 &pfx_10_10_10_1_s_32,
7805 FIB_SOURCE_ADJ,
7806 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007807 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007808 &nh_10_10_10_1,
7809 tm->hw[0]->sw_if_index,
7810 ~0, // invalid fib index
7811 1,
7812 NULL,
7813 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007814
7815 /*
7816 * Delete the BFD session. Expect the fib_entry to remain
7817 */
7818 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
7819
7820 fei = fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32);
7821 FIB_TEST(fib_test_validate_entry(fei,
7822 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7823 1,
7824 &adj_o_10_10_10_1),
7825 "BFD sourced %U remains via %U",
7826 format_fib_prefix, &pfx_10_10_10_1_s_32,
7827 format_ip_adjacency, ai_10_10_10_1, FORMAT_IP_ADJACENCY_NONE);
7828
7829 /*
7830 * Add the BFD source back
7831 */
7832 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
7833
7834 /*
7835 * Create another ADJ FIB
7836 */
7837 fib_prefix_t pfx_10_10_10_2_s_32 = {
7838 .fp_addr = nh_10_10_10_2,
7839 .fp_len = 32,
7840 .fp_proto = FIB_PROTOCOL_IP4,
7841 };
Neale Ranns81424992017-05-18 03:03:22 -07007842 fib_table_entry_path_add(0,
7843 &pfx_10_10_10_2_s_32,
7844 FIB_SOURCE_ADJ,
7845 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007846 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007847 &nh_10_10_10_2,
7848 tm->hw[0]->sw_if_index,
7849 ~0, // invalid fib index
7850 1,
7851 NULL,
7852 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007853 /*
7854 * A BFD session for the new ADJ FIB
7855 */
7856 bfd_session_t bfd_10_10_10_2 = {
7857 .udp = {
7858 .key = {
7859 .fib_index = 0,
7860 .peer_addr = nh_10_10_10_2,
7861 },
7862 },
7863 .hop_type = BFD_HOP_TYPE_MULTI,
7864 .local_state = BFD_STATE_init,
7865 };
7866
7867 fib_bfd_notify (BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_2);
7868
7869 /*
7870 * remove the adj-fib source whilst the session is present
7871 * then add it back
7872 */
7873 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
Neale Ranns81424992017-05-18 03:03:22 -07007874 fib_table_entry_path_add(0,
7875 &pfx_10_10_10_2_s_32,
7876 FIB_SOURCE_ADJ,
7877 FIB_ENTRY_FLAG_ATTACHED,
Neale Rannsda78f952017-05-24 09:15:43 -07007878 DPO_PROTO_IP4,
Neale Ranns81424992017-05-18 03:03:22 -07007879 &nh_10_10_10_2,
7880 tm->hw[0]->sw_if_index,
7881 ~0, // invalid fib index
7882 1,
7883 NULL,
7884 FIB_ROUTE_PATH_FLAG_NONE);
Neale Ranns88fc83e2017-04-05 08:11:14 -07007885
7886 /*
7887 * Before adding a recursive via the BFD tracked ADJ-FIBs,
7888 * bring one of the sessions UP, leave the other down
7889 */
7890 bfd_10_10_10_1.local_state = BFD_STATE_up;
7891 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
7892 bfd_10_10_10_2.local_state = BFD_STATE_down;
7893 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7894
7895 /*
7896 * A recursive prefix via both of the ADJ FIBs
7897 */
7898 fib_prefix_t pfx_200_0_0_0_s_24 = {
7899 .fp_proto = FIB_PROTOCOL_IP4,
7900 .fp_len = 32,
7901 .fp_addr = {
7902 .ip4.as_u32 = clib_host_to_net_u32(0xc8000000),
7903 },
7904 };
7905 const dpo_id_t *dpo_10_10_10_1, *dpo_10_10_10_2;
7906
7907 dpo_10_10_10_1 =
7908 fib_entry_contribute_ip_forwarding(
7909 fib_table_lookup_exact_match(0, &pfx_10_10_10_1_s_32));
7910 dpo_10_10_10_2 =
7911 fib_entry_contribute_ip_forwarding(
7912 fib_table_lookup_exact_match(0, &pfx_10_10_10_2_s_32));
7913
7914 fib_test_lb_bucket_t lb_o_10_10_10_1 = {
7915 .type = FT_LB_O_LB,
7916 .lb = {
7917 .lb = dpo_10_10_10_1->dpoi_index,
7918 },
7919 };
7920 fib_test_lb_bucket_t lb_o_10_10_10_2 = {
7921 .type = FT_LB_O_LB,
7922 .lb = {
7923 .lb = dpo_10_10_10_2->dpoi_index,
7924 },
7925 };
7926
7927 /*
7928 * A prefix via the adj-fib that is BFD down => DROP
7929 */
7930 fei = fib_table_entry_path_add(0,
7931 &pfx_200_0_0_0_s_24,
7932 FIB_SOURCE_API,
7933 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007934 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007935 &nh_10_10_10_2,
7936 ~0, // recursive
7937 0, // default fib index
7938 1,
7939 NULL,
7940 FIB_ROUTE_PATH_FLAG_NONE);
7941 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
7942 "%U resolves via drop",
7943 format_fib_prefix, &pfx_200_0_0_0_s_24);
7944
7945 /*
7946 * add a path via the UP BFD adj-fib.
7947 * we expect that the DOWN BFD ADJ FIB is not used.
7948 */
7949 fei = fib_table_entry_path_add(0,
7950 &pfx_200_0_0_0_s_24,
7951 FIB_SOURCE_API,
7952 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07007953 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07007954 &nh_10_10_10_1,
7955 ~0, // recursive
7956 0, // default fib index
7957 1,
7958 NULL,
7959 FIB_ROUTE_PATH_FLAG_NONE);
7960
7961 FIB_TEST(fib_test_validate_entry(fei,
7962 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7963 1,
7964 &lb_o_10_10_10_1),
7965 "Recursive %U only UP BFD adj-fibs",
7966 format_fib_prefix, &pfx_200_0_0_0_s_24);
7967
7968 /*
7969 * Send a BFD state change to UP - both sessions are now up
7970 * the recursive prefix should LB over both
7971 */
7972 bfd_10_10_10_2.local_state = BFD_STATE_up;
7973 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7974
7975
7976 FIB_TEST(fib_test_validate_entry(fei,
7977 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7978 2,
7979 &lb_o_10_10_10_1,
7980 &lb_o_10_10_10_2),
7981 "Recursive %U via both UP BFD adj-fibs",
7982 format_fib_prefix, &pfx_200_0_0_0_s_24);
7983
7984 /*
7985 * Send a BFD state change to DOWN
7986 * the recursive prefix should exclude the down
7987 */
7988 bfd_10_10_10_2.local_state = BFD_STATE_down;
7989 fib_bfd_notify (BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_2);
7990
7991
7992 FIB_TEST(fib_test_validate_entry(fei,
7993 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
7994 1,
7995 &lb_o_10_10_10_1),
7996 "Recursive %U via only UP",
7997 format_fib_prefix, &pfx_200_0_0_0_s_24);
7998
7999 /*
8000 * Delete the BFD session while it is in the DOWN state.
8001 * FIB should consider the entry's state as back up
8002 */
8003 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_2);
8004
8005 FIB_TEST(fib_test_validate_entry(fei,
8006 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8007 2,
8008 &lb_o_10_10_10_1,
8009 &lb_o_10_10_10_2),
8010 "Recursive %U via both UP BFD adj-fibs post down session delete",
8011 format_fib_prefix, &pfx_200_0_0_0_s_24);
8012
8013 /*
8014 * Delete the BFD other session while it is in the UP state.
8015 */
8016 fib_bfd_notify (BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8017
8018 FIB_TEST(fib_test_validate_entry(fei,
8019 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8020 2,
8021 &lb_o_10_10_10_1,
8022 &lb_o_10_10_10_2),
8023 "Recursive %U via both UP BFD adj-fibs post up session delete",
8024 format_fib_prefix, &pfx_200_0_0_0_s_24);
8025
8026 /*
8027 * cleaup
8028 */
8029 fib_table_entry_delete(0, &pfx_200_0_0_0_s_24, FIB_SOURCE_API);
8030 fib_table_entry_delete(0, &pfx_10_10_10_1_s_32, FIB_SOURCE_ADJ);
8031 fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
8032
8033 fib_table_entry_delete(0, &pfx_10_10_10_10_s_32, FIB_SOURCE_INTERFACE);
8034 fib_table_entry_delete(0, &pfx_10_10_10_10_s_24, FIB_SOURCE_INTERFACE);
8035
8036 adj_unlock(ai_10_10_10_1);
8037 /*
8038 * test no-one left behind
8039 */
8040 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8041 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8042
8043 /*
8044 * Single-hop BFD tests
8045 */
8046 bfd_10_10_10_1.hop_type = BFD_HOP_TYPE_SINGLE;
8047 bfd_10_10_10_1.udp.key.sw_if_index = tm->hw[0]->sw_if_index;
8048
8049 adj_bfd_notify(BFD_LISTEN_EVENT_CREATE, &bfd_10_10_10_1);
8050
8051 ai_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8052 VNET_LINK_IP4,
8053 &nh_10_10_10_1,
8054 tm->hw[0]->sw_if_index);
8055 /*
8056 * whilst the BFD session is not signalled, the adj is up
8057 */
8058 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on uninit session");
8059
8060 /*
8061 * bring the BFD session up
8062 */
8063 bfd_10_10_10_1.local_state = BFD_STATE_up;
8064 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8065 FIB_TEST(adj_is_up(ai_10_10_10_1), "Adj state up on UP session");
8066
8067 /*
8068 * bring the BFD session down
8069 */
8070 bfd_10_10_10_1.local_state = BFD_STATE_down;
8071 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8072 FIB_TEST(!adj_is_up(ai_10_10_10_1), "Adj state down on DOWN session");
8073
8074
8075 /*
8076 * add an attached next hop FIB entry via the down adj
8077 */
8078 fib_prefix_t pfx_5_5_5_5_s_32 = {
8079 .fp_addr = {
8080 .ip4 = {
8081 .as_u32 = clib_host_to_net_u32(0x05050505),
8082 },
8083 },
8084 .fp_len = 32,
8085 .fp_proto = FIB_PROTOCOL_IP4,
8086 };
8087
8088 fei = fib_table_entry_path_add(0,
8089 &pfx_5_5_5_5_s_32,
8090 FIB_SOURCE_CLI,
8091 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008092 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008093 &nh_10_10_10_1,
8094 tm->hw[0]->sw_if_index,
8095 ~0, // invalid fib index
8096 1,
8097 NULL,
8098 FIB_ROUTE_PATH_FLAG_NONE);
8099 FIB_TEST(load_balance_is_drop(fib_entry_contribute_ip_forwarding(fei)),
8100 "%U resolves via drop",
8101 format_fib_prefix, &pfx_5_5_5_5_s_32);
8102
8103 /*
8104 * Add a path via an ADJ that is up
8105 */
8106 adj_index_t ai_10_10_10_2 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8107 VNET_LINK_IP4,
8108 &nh_10_10_10_2,
8109 tm->hw[0]->sw_if_index);
8110
8111 fib_test_lb_bucket_t adj_o_10_10_10_2 = {
8112 .type = FT_LB_ADJ,
8113 .adj = {
8114 .adj = ai_10_10_10_2,
8115 },
8116 };
8117 adj_o_10_10_10_1.adj.adj = ai_10_10_10_1;
8118
8119 fei = fib_table_entry_path_add(0,
8120 &pfx_5_5_5_5_s_32,
8121 FIB_SOURCE_CLI,
8122 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008123 DPO_PROTO_IP4,
Neale Ranns88fc83e2017-04-05 08:11:14 -07008124 &nh_10_10_10_2,
8125 tm->hw[0]->sw_if_index,
8126 ~0, // invalid fib index
8127 1,
8128 NULL,
8129 FIB_ROUTE_PATH_FLAG_NONE);
8130
8131 FIB_TEST(fib_test_validate_entry(fei,
8132 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8133 1,
8134 &adj_o_10_10_10_2),
8135 "BFD sourced %U via %U",
8136 format_fib_prefix, &pfx_5_5_5_5_s_32,
8137 format_ip_adjacency, ai_10_10_10_2, FORMAT_IP_ADJACENCY_NONE);
8138
8139 /*
8140 * Bring up the down session - should now LB
8141 */
8142 bfd_10_10_10_1.local_state = BFD_STATE_up;
8143 adj_bfd_notify(BFD_LISTEN_EVENT_UPDATE, &bfd_10_10_10_1);
8144 FIB_TEST(fib_test_validate_entry(fei,
8145 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8146 2,
8147 &adj_o_10_10_10_1,
8148 &adj_o_10_10_10_2),
8149 "BFD sourced %U via noth adjs",
8150 format_fib_prefix, &pfx_5_5_5_5_s_32);
8151
8152 /*
8153 * remove the BFD session state from the adj
8154 */
8155 adj_bfd_notify(BFD_LISTEN_EVENT_DELETE, &bfd_10_10_10_1);
8156
8157 /*
8158 * clean-up
8159 */
8160 fib_table_entry_delete(0, &pfx_5_5_5_5_s_32, FIB_SOURCE_CLI);
8161 adj_unlock(ai_10_10_10_1);
8162 adj_unlock(ai_10_10_10_2);
8163
8164 /*
8165 * test no-one left behind
8166 */
8167 FIB_TEST((n_feis == fib_entry_pool_size()), "Entries gone");
8168 FIB_TEST(0 == adj_nbr_db_size(), "All adjacencies removed");
8169 return (0);
8170}
8171
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008172static int
8173lfib_test (void)
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008174{
8175 const mpls_label_t deag_label = 50;
8176 const u32 lfib_index = 0;
8177 const u32 fib_index = 0;
Neale Ranns948e00f2016-10-20 13:39:34 +01008178 dpo_id_t dpo = DPO_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008179 const dpo_id_t *dpo1;
8180 fib_node_index_t lfe;
8181 lookup_dpo_t *lkd;
8182 test_main_t *tm;
8183 int lb_count;
Neale Rannsad422ed2016-11-02 14:20:04 +00008184 adj_index_t ai_mpls_10_10_10_1;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008185
8186 tm = &test_main;
8187 lb_count = pool_elts(load_balance_pool);
8188
8189 FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
8190 adj_nbr_db_size());
8191
8192 /*
8193 * MPLS enable an interface so we get the MPLS table created
8194 */
Neale Ranns2297af02017-09-12 09:45:04 -07008195 mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API, NULL);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008196 mpls_sw_interface_enable_disable(&mpls_main,
8197 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008198 1, 1);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008199
Neale Rannsad422ed2016-11-02 14:20:04 +00008200 ip46_address_t nh_10_10_10_1 = {
8201 .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
8202 };
8203 ai_mpls_10_10_10_1 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
8204 VNET_LINK_MPLS,
8205 &nh_10_10_10_1,
8206 tm->hw[0]->sw_if_index);
8207
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008208 /*
8209 * Test the specials stack properly.
8210 */
8211 fib_prefix_t exp_null_v6_pfx = {
8212 .fp_proto = FIB_PROTOCOL_MPLS,
8213 .fp_eos = MPLS_EOS,
8214 .fp_label = MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8215 .fp_payload_proto = DPO_PROTO_IP6,
8216 };
8217 lfe = fib_table_lookup(lfib_index, &exp_null_v6_pfx);
8218 FIB_TEST((FIB_NODE_INDEX_INVALID != lfe),
8219 "%U/%U present",
8220 format_mpls_unicast_label, MPLS_IETF_IPV6_EXPLICIT_NULL_LABEL,
8221 format_mpls_eos_bit, MPLS_EOS);
8222 fib_entry_contribute_forwarding(lfe,
8223 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8224 &dpo);
8225 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8226 lkd = lookup_dpo_get(dpo1->dpoi_index);
8227
8228 FIB_TEST((fib_index == lkd->lkd_fib_index),
8229 "%U/%U is deag in %d %U",
8230 format_mpls_unicast_label, deag_label,
8231 format_mpls_eos_bit, MPLS_EOS,
8232 lkd->lkd_fib_index,
8233 format_dpo_id, &dpo, 0);
8234 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8235 "%U/%U is dst deag",
8236 format_mpls_unicast_label, deag_label,
8237 format_mpls_eos_bit, MPLS_EOS);
8238 FIB_TEST((LOOKUP_TABLE_FROM_INPUT_INTERFACE == lkd->lkd_table),
8239 "%U/%U is lookup in interface's table",
8240 format_mpls_unicast_label, deag_label,
8241 format_mpls_eos_bit, MPLS_EOS);
8242 FIB_TEST((DPO_PROTO_IP6 == lkd->lkd_proto),
8243 "%U/%U is %U dst deag",
8244 format_mpls_unicast_label, deag_label,
8245 format_mpls_eos_bit, MPLS_EOS,
8246 format_dpo_proto, lkd->lkd_proto);
8247
8248
8249 /*
8250 * A route deag route for EOS
8251 */
8252 fib_prefix_t pfx = {
8253 .fp_proto = FIB_PROTOCOL_MPLS,
8254 .fp_eos = MPLS_EOS,
8255 .fp_label = deag_label,
8256 .fp_payload_proto = DPO_PROTO_IP4,
8257 };
8258 lfe = fib_table_entry_path_add(lfib_index,
8259 &pfx,
8260 FIB_SOURCE_CLI,
8261 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008262 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008263 &zero_addr,
8264 ~0,
8265 fib_index,
8266 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008267 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008268 FIB_ROUTE_PATH_FLAG_NONE);
8269
8270 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8271 "%U/%U present",
8272 format_mpls_unicast_label, deag_label,
8273 format_mpls_eos_bit, MPLS_EOS);
8274
8275 fib_entry_contribute_forwarding(lfe,
8276 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8277 &dpo);
8278 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8279 lkd = lookup_dpo_get(dpo1->dpoi_index);
8280
8281 FIB_TEST((fib_index == lkd->lkd_fib_index),
8282 "%U/%U is deag in %d %U",
8283 format_mpls_unicast_label, deag_label,
8284 format_mpls_eos_bit, MPLS_EOS,
8285 lkd->lkd_fib_index,
8286 format_dpo_id, &dpo, 0);
8287 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8288 "%U/%U is dst deag",
8289 format_mpls_unicast_label, deag_label,
8290 format_mpls_eos_bit, MPLS_EOS);
8291 FIB_TEST((DPO_PROTO_IP4 == lkd->lkd_proto),
8292 "%U/%U is %U dst deag",
8293 format_mpls_unicast_label, deag_label,
8294 format_mpls_eos_bit, MPLS_EOS,
8295 format_dpo_proto, lkd->lkd_proto);
8296
8297 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8298
8299 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8300 &pfx)),
8301 "%U/%U not present",
8302 format_mpls_unicast_label, deag_label,
8303 format_mpls_eos_bit, MPLS_EOS);
8304
8305 /*
8306 * A route deag route for non-EOS
8307 */
8308 pfx.fp_eos = MPLS_NON_EOS;
8309 lfe = fib_table_entry_path_add(lfib_index,
8310 &pfx,
8311 FIB_SOURCE_CLI,
8312 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008313 DPO_PROTO_IP4,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008314 &zero_addr,
8315 ~0,
8316 lfib_index,
8317 1,
Neale Rannsad422ed2016-11-02 14:20:04 +00008318 NULL,
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008319 FIB_ROUTE_PATH_FLAG_NONE);
8320
8321 FIB_TEST((lfe == fib_table_lookup(lfib_index, &pfx)),
8322 "%U/%U present",
8323 format_mpls_unicast_label, deag_label,
8324 format_mpls_eos_bit, MPLS_NON_EOS);
8325
8326 fib_entry_contribute_forwarding(lfe,
8327 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8328 &dpo);
8329 dpo1 = load_balance_get_bucket(dpo.dpoi_index, 0);
8330 lkd = lookup_dpo_get(dpo1->dpoi_index);
8331
8332 FIB_TEST((fib_index == lkd->lkd_fib_index),
8333 "%U/%U is deag in %d %U",
8334 format_mpls_unicast_label, deag_label,
8335 format_mpls_eos_bit, MPLS_NON_EOS,
8336 lkd->lkd_fib_index,
8337 format_dpo_id, &dpo, 0);
8338 FIB_TEST((LOOKUP_INPUT_DST_ADDR == lkd->lkd_input),
8339 "%U/%U is dst deag",
8340 format_mpls_unicast_label, deag_label,
8341 format_mpls_eos_bit, MPLS_NON_EOS);
8342
8343 FIB_TEST((DPO_PROTO_MPLS == lkd->lkd_proto),
8344 "%U/%U is %U dst deag",
8345 format_mpls_unicast_label, deag_label,
8346 format_mpls_eos_bit, MPLS_NON_EOS,
8347 format_dpo_proto, lkd->lkd_proto);
8348
8349 fib_table_entry_delete_index(lfe, FIB_SOURCE_CLI);
8350
8351 FIB_TEST((FIB_NODE_INDEX_INVALID == fib_table_lookup(lfib_index,
8352 &pfx)),
8353 "%U/%U not present",
8354 format_mpls_unicast_label, deag_label,
8355 format_mpls_eos_bit, MPLS_EOS);
8356
Neale Rannsad422ed2016-11-02 14:20:04 +00008357 dpo_reset(&dpo);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008358
Neale Rannsad422ed2016-11-02 14:20:04 +00008359 /*
8360 * An MPLS x-connect
8361 */
8362 fib_prefix_t pfx_1200 = {
8363 .fp_len = 21,
8364 .fp_proto = FIB_PROTOCOL_MPLS,
8365 .fp_label = 1200,
8366 .fp_eos = MPLS_NON_EOS,
8367 };
8368 fib_test_lb_bucket_t neos_o_10_10_10_1 = {
8369 .type = FT_LB_LABEL_STACK_O_ADJ,
8370 .label_stack_o_adj = {
8371 .adj = ai_mpls_10_10_10_1,
8372 .label_stack_size = 4,
8373 .label_stack = {
8374 200, 300, 400, 500,
8375 },
8376 .eos = MPLS_NON_EOS,
8377 },
8378 };
8379 dpo_id_t neos_1200 = DPO_INVALID;
8380 dpo_id_t ip_1200 = DPO_INVALID;
8381 mpls_label_t *l200 = NULL;
8382 vec_add1(l200, 200);
8383 vec_add1(l200, 300);
8384 vec_add1(l200, 400);
8385 vec_add1(l200, 500);
8386
8387 lfe = fib_table_entry_update_one_path(fib_index,
8388 &pfx_1200,
8389 FIB_SOURCE_API,
8390 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008391 DPO_PROTO_IP4,
Neale Rannsad422ed2016-11-02 14:20:04 +00008392 &nh_10_10_10_1,
8393 tm->hw[0]->sw_if_index,
8394 ~0, // invalid fib index
8395 1,
8396 l200,
8397 FIB_ROUTE_PATH_FLAG_NONE);
8398
8399 FIB_TEST(fib_test_validate_entry(lfe,
8400 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8401 1,
8402 &neos_o_10_10_10_1),
8403 "1200/0 LB 1 buckets via: "
8404 "adj 10.10.11.1");
8405
8406 /*
8407 * A recursive route via the MPLS x-connect
8408 */
8409 fib_prefix_t pfx_2_2_2_3_s_32 = {
8410 .fp_len = 32,
8411 .fp_proto = FIB_PROTOCOL_IP4,
8412 .fp_addr = {
8413 .ip4.as_u32 = clib_host_to_net_u32(0x02020203),
8414 },
8415 };
8416 fib_route_path_t *rpaths = NULL, rpath = {
Neale Rannsda78f952017-05-24 09:15:43 -07008417 .frp_proto = DPO_PROTO_MPLS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008418 .frp_local_label = 1200,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008419 .frp_eos = MPLS_NON_EOS,
Neale Rannsad422ed2016-11-02 14:20:04 +00008420 .frp_sw_if_index = ~0, // recurive
8421 .frp_fib_index = 0, // Default MPLS fib
8422 .frp_weight = 1,
8423 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
8424 .frp_label_stack = NULL,
8425 };
8426 vec_add1(rpaths, rpath);
8427
8428 fib_table_entry_path_add2(fib_index,
8429 &pfx_2_2_2_3_s_32,
8430 FIB_SOURCE_API,
8431 FIB_ENTRY_FLAG_NONE,
8432 rpaths);
8433
8434 /*
8435 * A labelled recursive route via the MPLS x-connect
8436 */
8437 fib_prefix_t pfx_2_2_2_4_s_32 = {
8438 .fp_len = 32,
8439 .fp_proto = FIB_PROTOCOL_IP4,
8440 .fp_addr = {
8441 .ip4.as_u32 = clib_host_to_net_u32(0x02020204),
8442 },
8443 };
8444 mpls_label_t *l999 = NULL;
8445 vec_add1(l999, 999);
8446 rpaths[0].frp_label_stack = l999,
8447
8448 fib_table_entry_path_add2(fib_index,
8449 &pfx_2_2_2_4_s_32,
8450 FIB_SOURCE_API,
8451 FIB_ENTRY_FLAG_NONE,
8452 rpaths);
8453
8454 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8455 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8456 &ip_1200);
8457 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8458 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8459 &neos_1200);
8460
8461 fib_test_lb_bucket_t ip_o_1200 = {
8462 .type = FT_LB_O_LB,
8463 .lb = {
8464 .lb = ip_1200.dpoi_index,
8465 },
8466 };
8467 fib_test_lb_bucket_t mpls_o_1200 = {
8468 .type = FT_LB_LABEL_O_LB,
8469 .label_o_lb = {
8470 .lb = neos_1200.dpoi_index,
8471 .label = 999,
8472 .eos = MPLS_EOS,
8473 },
8474 };
8475
8476 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_3_s_32);
8477 FIB_TEST(fib_test_validate_entry(lfe,
8478 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8479 1,
8480 &ip_o_1200),
8481 "2.2.2.2.3/32 LB 1 buckets via: label 1200 EOS");
8482 lfe = fib_table_lookup(fib_index, &pfx_2_2_2_4_s_32);
8483 FIB_TEST(fib_test_validate_entry(lfe,
8484 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8485 1,
8486 &mpls_o_1200),
8487 "2.2.2.2.4/32 LB 1 buckets via: label 1200 non-EOS");
8488
8489 fib_table_entry_delete(fib_index, &pfx_1200, FIB_SOURCE_API);
8490 fib_table_entry_delete(fib_index, &pfx_2_2_2_3_s_32, FIB_SOURCE_API);
8491 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8492
8493 dpo_reset(&neos_1200);
8494 dpo_reset(&ip_1200);
8495
8496 /*
8497 * A recursive via a label that does not exist
8498 */
8499 fib_test_lb_bucket_t bucket_drop = {
8500 .type = FT_LB_SPECIAL,
8501 .special = {
Neale Rannsf12a83f2017-04-18 09:09:40 -07008502 .adj = DPO_PROTO_IP4,
8503 },
8504 };
8505 fib_test_lb_bucket_t mpls_bucket_drop = {
8506 .type = FT_LB_SPECIAL,
8507 .special = {
Neale Rannsad422ed2016-11-02 14:20:04 +00008508 .adj = DPO_PROTO_MPLS,
8509 },
8510 };
8511
8512 rpaths[0].frp_label_stack = NULL;
8513 lfe = fib_table_entry_path_add2(fib_index,
8514 &pfx_2_2_2_4_s_32,
8515 FIB_SOURCE_API,
8516 FIB_ENTRY_FLAG_NONE,
8517 rpaths);
8518
8519 fib_entry_contribute_forwarding(fib_table_lookup(fib_index, &pfx_1200),
8520 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8521 &ip_1200);
8522 ip_o_1200.lb.lb = ip_1200.dpoi_index;
8523
8524 FIB_TEST(fib_test_validate_entry(lfe,
8525 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8526 1,
Neale Ranns57b58602017-07-15 07:37:25 -07008527 &bucket_drop),
8528 "2.2.2.2.4/32 LB 1 buckets via: drop");
Neale Rannsad422ed2016-11-02 14:20:04 +00008529 lfe = fib_table_lookup(fib_index, &pfx_1200);
8530 FIB_TEST(fib_test_validate_entry(lfe,
8531 FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
8532 1,
8533 &bucket_drop),
Neale Rannsf12a83f2017-04-18 09:09:40 -07008534 "1200/neos LB 1 buckets via: ip4-DROP");
8535 FIB_TEST(fib_test_validate_entry(lfe,
8536 FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
8537 1,
8538 &mpls_bucket_drop),
8539 "1200/neos LB 1 buckets via: mpls-DROP");
Neale Rannsad422ed2016-11-02 14:20:04 +00008540
8541 fib_table_entry_delete(fib_index, &pfx_2_2_2_4_s_32, FIB_SOURCE_API);
8542
8543 dpo_reset(&ip_1200);
8544
8545 /*
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008546 * An rx-interface route.
8547 * like the tail of an mcast LSP
8548 */
8549 dpo_id_t idpo = DPO_INVALID;
8550
Neale Ranns43161a82017-08-12 02:12:00 -07008551 interface_rx_dpo_add_or_lock(DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008552 tm->hw[0]->sw_if_index,
8553 &idpo);
8554
8555 fib_prefix_t pfx_2500 = {
8556 .fp_len = 21,
8557 .fp_proto = FIB_PROTOCOL_MPLS,
8558 .fp_label = 2500,
8559 .fp_eos = MPLS_EOS,
8560 .fp_payload_proto = DPO_PROTO_IP4,
8561 };
8562 fib_test_lb_bucket_t rx_intf_0 = {
8563 .type = FT_LB_INTF,
8564 .adj = {
8565 .adj = idpo.dpoi_index,
8566 },
8567 };
8568
8569 lfe = fib_table_entry_update_one_path(fib_index,
8570 &pfx_2500,
8571 FIB_SOURCE_API,
8572 FIB_ENTRY_FLAG_NONE,
Neale Rannsda78f952017-05-24 09:15:43 -07008573 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008574 NULL,
8575 tm->hw[0]->sw_if_index,
8576 ~0, // invalid fib index
8577 0,
8578 NULL,
8579 FIB_ROUTE_PATH_INTF_RX);
8580 FIB_TEST(fib_test_validate_entry(lfe,
8581 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8582 1,
8583 &rx_intf_0),
8584 "2500 rx-interface 0");
8585 fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
8586
8587 /*
8588 * An MPLS mulicast entry
8589 */
8590 fib_prefix_t pfx_3500 = {
8591 .fp_len = 21,
8592 .fp_proto = FIB_PROTOCOL_MPLS,
8593 .fp_label = 3500,
8594 .fp_eos = MPLS_EOS,
8595 .fp_payload_proto = DPO_PROTO_IP4,
8596 };
8597 fib_test_rep_bucket_t mc_0 = {
8598 .type = FT_REP_LABEL_O_ADJ,
8599 .label_o_adj = {
8600 .adj = ai_mpls_10_10_10_1,
8601 .label = 3300,
8602 .eos = MPLS_EOS,
8603 },
8604 };
8605 fib_test_rep_bucket_t mc_intf_0 = {
8606 .type = FT_REP_INTF,
8607 .adj = {
8608 .adj = idpo.dpoi_index,
8609 },
8610 };
8611 mpls_label_t *l3300 = NULL;
8612 vec_add1(l3300, 3300);
8613
8614 lfe = fib_table_entry_update_one_path(lfib_index,
8615 &pfx_3500,
8616 FIB_SOURCE_API,
8617 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008618 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008619 &nh_10_10_10_1,
8620 tm->hw[0]->sw_if_index,
8621 ~0, // invalid fib index
8622 1,
8623 l3300,
8624 FIB_ROUTE_PATH_FLAG_NONE);
8625 FIB_TEST(fib_test_validate_entry(lfe,
8626 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8627 1,
8628 &mc_0),
8629 "3500 via replicate over 10.10.10.1");
8630
8631 /*
8632 * MPLS Bud-node. Add a replication via an interface-receieve path
8633 */
8634 lfe = fib_table_entry_path_add(lfib_index,
8635 &pfx_3500,
8636 FIB_SOURCE_API,
8637 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008638 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008639 NULL,
8640 tm->hw[0]->sw_if_index,
8641 ~0, // invalid fib index
8642 0,
8643 NULL,
8644 FIB_ROUTE_PATH_INTF_RX);
8645 FIB_TEST(fib_test_validate_entry(lfe,
8646 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8647 2,
8648 &mc_0,
8649 &mc_intf_0),
8650 "3500 via replicate over 10.10.10.1 and interface-rx");
8651
8652 /*
8653 * Add a replication via an interface-free for-us path
8654 */
8655 fib_test_rep_bucket_t mc_disp = {
8656 .type = FT_REP_DISP_MFIB_LOOKUP,
8657 .adj = {
8658 .adj = idpo.dpoi_index,
8659 },
8660 };
8661 lfe = fib_table_entry_path_add(lfib_index,
8662 &pfx_3500,
8663 FIB_SOURCE_API,
8664 FIB_ENTRY_FLAG_MULTICAST,
Neale Rannsda78f952017-05-24 09:15:43 -07008665 DPO_PROTO_IP4,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08008666 NULL,
8667 5, // rpf-id
8668 0, // default table
8669 0,
8670 NULL,
8671 FIB_ROUTE_PATH_RPF_ID);
8672 FIB_TEST(fib_test_validate_entry(lfe,
8673 FIB_FORW_CHAIN_TYPE_MPLS_EOS,
8674 3,
8675 &mc_0,
8676 &mc_disp,
8677 &mc_intf_0),
8678 "3500 via replicate over 10.10.10.1 and interface-rx");
8679
8680
8681
8682 fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
8683 dpo_reset(&idpo);
8684
8685 /*
Neale Rannsad422ed2016-11-02 14:20:04 +00008686 * cleanup
8687 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008688 mpls_sw_interface_enable_disable(&mpls_main,
8689 tm->hw[0]->sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07008690 0, 1);
8691 mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008692
Neale Rannsad422ed2016-11-02 14:20:04 +00008693 FIB_TEST(lb_count == pool_elts(load_balance_pool),
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008694 "Load-balance resources freed %d of %d",
Neale Rannsad422ed2016-11-02 14:20:04 +00008695 lb_count, pool_elts(load_balance_pool));
Neale Ranns43161a82017-08-12 02:12:00 -07008696 FIB_TEST(0 == pool_elts(interface_rx_dpo_pool),
8697 "interface_rx_dpo resources freed %d of %d",
8698 0, pool_elts(interface_rx_dpo_pool));
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008699
8700 return (0);
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008701}
8702
8703static clib_error_t *
8704fib_test (vlib_main_t * vm,
8705 unformat_input_t * input,
8706 vlib_cli_command_t * cmd_arg)
8707{
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008708 int res;
8709
8710 res = 0;
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008711 fib_test_mk_intf(4);
8712
Neale Ranns88fc83e2017-04-05 08:11:14 -07008713 if (unformat (input, "debug"))
8714 {
8715 fib_test_do_debug = 1;
8716 }
8717
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008718 if (unformat (input, "ip"))
8719 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008720 res += fib_test_v4();
8721 res += fib_test_v6();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008722 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008723 else if (unformat (input, "label"))
8724 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008725 res += fib_test_label();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008726 }
8727 else if (unformat (input, "ae"))
8728 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008729 res += fib_test_ae();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008730 }
Neale Ranns57b58602017-07-15 07:37:25 -07008731 else if (unformat (input, "pref"))
8732 {
8733 res += fib_test_pref();
8734 }
Neale Rannsad422ed2016-11-02 14:20:04 +00008735 else if (unformat (input, "lfib"))
8736 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008737 res += lfib_test();
Neale Rannsad422ed2016-11-02 14:20:04 +00008738 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008739 else if (unformat (input, "walk"))
8740 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008741 res += fib_test_walk();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008742 }
Neale Ranns88fc83e2017-04-05 08:11:14 -07008743 else if (unformat (input, "bfd"))
8744 {
8745 res += fib_test_bfd();
8746 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008747 else
8748 {
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008749 res += fib_test_v4();
8750 res += fib_test_v6();
8751 res += fib_test_ae();
Neale Ranns88fc83e2017-04-05 08:11:14 -07008752 res += fib_test_bfd();
Neale Ranns57b58602017-07-15 07:37:25 -07008753 res += fib_test_pref();
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008754 res += fib_test_label();
8755 res += lfib_test();
Neale Rannsf12a83f2017-04-18 09:09:40 -07008756
8757 /*
8758 * fib-walk process must be disabled in order for the walk tests to work
8759 */
8760 fib_walk_process_disable();
8761 res += fib_test_walk();
8762 fib_walk_process_enable();
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008763 }
8764
Neale Ranns0ebe8d72016-12-08 19:48:11 +00008765 if (res)
8766 {
8767 return clib_error_return(0, "FIB Unit Test Failed");
8768 }
8769 else
8770 {
8771 return (NULL);
8772 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008773}
8774
8775VLIB_CLI_COMMAND (test_fib_command, static) = {
8776 .path = "test fib",
8777 .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM",
8778 .function = fib_test,
8779};
8780
Neale Ranns0bfe5d82016-08-25 15:29:12 +01008781clib_error_t *
8782fib_test_init (vlib_main_t *vm)
8783{
8784 return 0;
8785}
8786
8787VLIB_INIT_FUNCTION (fib_test_init);