Line data Source code
1 : /*
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 <vppinfra/vec.h>
17 :
18 : #include <vnet/bier/bier_table.h>
19 : #include <vnet/bier/bier_entry.h>
20 : #include <vnet/bier/bier_update.h>
21 : #include <vnet/bier/bier_fmask_db.h>
22 : #include <vnet/bier/bier_fmask.h>
23 : #include <vnet/bier/bier_bift_table.h>
24 :
25 : #include <vnet/fib/mpls_fib.h>
26 : #include <vnet/mpls/mpls.h>
27 : #include <vnet/fib/fib_path_list.h>
28 :
29 : /**
30 : * Memory pool of all the allocated tables
31 : */
32 : bier_table_t *bier_table_pool;
33 :
34 : /**
35 : * DB store of all BIER tables index by SD/set/hdr-len
36 : */
37 : static uword *bier_tables_by_key;
38 :
39 : /**
40 : * The magic number of BIER ECMP tables to create.
41 : * The load-balance distribution algorithm will use a power of 2
42 : * for the number of buckets, which constrains the choice.
43 : */
44 : #define BIER_N_ECMP_TABLES 16
45 :
46 : static inline index_t
47 521 : bier_table_get_index (const bier_table_t *bt)
48 : {
49 521 : return (bt - bier_table_pool);
50 : }
51 :
52 : int
53 1819 : bier_table_is_main (const bier_table_t *bt)
54 : {
55 1819 : return (BIER_ECMP_TABLE_ID_MAIN == bt->bt_id.bti_ecmp);
56 : }
57 :
58 : /*
59 : * Construct the key to use to find a BIER table
60 : * in the global hash map
61 : */
62 : static u32
63 789 : bier_table_mk_key (const bier_table_id_t *id)
64 : {
65 : /*
66 : * the set and sub-domain Ids are 8 bit values.
67 : * we have space for ECMP table ID and talbe type (SPF/TE)
68 : * for later
69 : */
70 789 : u32 key = ((id->bti_sub_domain << 24) |
71 789 : (id->bti_set << 16) |
72 789 : (id->bti_ecmp << 8) |
73 789 : (id->bti_hdr_len << 4) |
74 789 : (id->bti_type));
75 :
76 789 : return (key);
77 : }
78 :
79 : static void
80 170 : bier_table_init (bier_table_t *bt,
81 : const bier_table_id_t *id,
82 : mpls_label_t ll)
83 : {
84 : u32 num_entries;
85 :
86 170 : bt->bt_lfei = FIB_NODE_INDEX_INVALID;
87 170 : bt->bt_id = *id;
88 170 : bt->bt_ll = ll;
89 170 : num_entries = bier_hdr_len_id_to_num_bits(bt->bt_id.bti_hdr_len);
90 :
91 : /*
92 : * create the lookup table of entries.
93 : */
94 170 : if (bier_table_is_main(bt))
95 : {
96 2004 : vec_validate_init_empty_aligned(bt->bt_entries,
97 : num_entries,
98 : INDEX_INVALID,
99 : CLIB_CACHE_LINE_BYTES);
100 : }
101 : else
102 : {
103 32064 : vec_validate_init_empty_aligned(bt->bt_fmasks,
104 : num_entries,
105 : INDEX_INVALID,
106 : CLIB_CACHE_LINE_BYTES);
107 : }
108 170 : }
109 :
110 : static void
111 1 : bier_table_rm_bift (bier_table_t *bt)
112 : {
113 1 : ASSERT(MPLS_LABEL_INVALID == bt->bt_ll);
114 :
115 1 : bier_bift_table_entry_remove(bier_bift_id_encode(bt->bt_id.bti_set,
116 : bt->bt_id.bti_sub_domain,
117 1 : bt->bt_id.bti_hdr_len));
118 1 : }
119 :
120 : static void
121 1 : bier_table_mk_bift (bier_table_t *bt)
122 : {
123 1 : dpo_id_t dpo = DPO_INVALID;
124 :
125 1 : ASSERT(MPLS_LABEL_INVALID == bt->bt_ll);
126 :
127 1 : bier_table_contribute_forwarding(bier_table_get_index(bt), &dpo);
128 :
129 1 : bier_bift_table_entry_add(bier_bift_id_encode(bt->bt_id.bti_set,
130 : bt->bt_id.bti_sub_domain,
131 1 : bt->bt_id.bti_hdr_len),
132 : &dpo);
133 :
134 1 : dpo_reset(&dpo);
135 1 : }
136 :
137 : static void
138 10 : bier_table_rm_lfib (bier_table_t *bt)
139 : {
140 10 : if (FIB_NODE_INDEX_INVALID != bt->bt_lfei)
141 : {
142 10 : fib_table_entry_delete_index(bt->bt_lfei,
143 : FIB_SOURCE_BIER);
144 10 : fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID,
145 : FIB_PROTOCOL_MPLS,
146 : FIB_SOURCE_BIER);
147 : }
148 10 : bt->bt_lfei = FIB_NODE_INDEX_INVALID;
149 10 : }
150 :
151 : static void
152 170 : bier_table_destroy (bier_table_t *bt)
153 : {
154 170 : if (bier_table_is_main(bt))
155 : {
156 : index_t *bei;
157 :
158 10 : if (MPLS_LABEL_INVALID != bt->bt_ll)
159 : {
160 9 : bier_table_rm_lfib(bt);
161 : }
162 : else
163 : {
164 1 : bier_table_rm_bift(bt);
165 : }
166 :
167 10 : fib_path_list_unlock(bt->bt_pl);
168 10 : bt->bt_pl = FIB_NODE_INDEX_INVALID;
169 : /*
170 : * unresolve/remove all entries from the table
171 : */
172 2004 : vec_foreach (bei, bt->bt_entries)
173 : {
174 1994 : if (INDEX_INVALID != *bei)
175 : {
176 0 : bier_entry_delete(*bei);
177 : }
178 : }
179 10 : vec_free (bt->bt_entries);
180 : }
181 : else
182 : {
183 : index_t *bfmi;
184 :
185 : /*
186 : * unlock any fmasks
187 : */
188 32064 : vec_foreach (bfmi, bt->bt_fmasks)
189 : {
190 31904 : bier_fmask_unlock(*bfmi);
191 : }
192 160 : vec_free(bt->bt_fmasks);
193 : }
194 :
195 170 : hash_unset(bier_tables_by_key,
196 : bier_table_mk_key(&bt->bt_id));
197 170 : pool_put(bier_table_pool, bt);
198 170 : }
199 :
200 : static void
201 194 : bier_table_lock_i (bier_table_t *bt)
202 : {
203 194 : bt->bt_locks++;
204 194 : }
205 :
206 : static void
207 194 : bier_table_unlock_i (bier_table_t *bt)
208 : {
209 194 : bt->bt_locks--;
210 :
211 194 : if (0 == bt->bt_locks)
212 : {
213 170 : bier_table_destroy(bt);
214 : }
215 194 : }
216 :
217 : void
218 18 : bier_table_unlock (const bier_table_id_t *bti)
219 : {
220 : uword *p;
221 : u32 key;
222 :
223 18 : key = bier_table_mk_key(bti);
224 :
225 18 : p = hash_get (bier_tables_by_key, key);
226 :
227 18 : if (NULL != p) {
228 18 : bier_table_unlock_i(bier_table_get(p[0]));
229 : }
230 18 : }
231 :
232 : static void
233 10 : bier_table_mk_lfib (bier_table_t *bt)
234 : {
235 : /*
236 : * Add a new MPLS lfib entry
237 : */
238 10 : if (MPLS_LABEL_INVALID != bt->bt_ll) {
239 10 : fib_prefix_t pfx = {
240 : .fp_proto = FIB_PROTOCOL_MPLS,
241 : .fp_len = 21,
242 10 : .fp_label = bt->bt_ll,
243 : .fp_eos = MPLS_EOS,
244 : .fp_payload_proto = DPO_PROTO_BIER,
245 : };
246 : u32 mpls_fib_index;
247 10 : dpo_id_t dpo = DPO_INVALID;
248 :
249 10 : fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
250 : MPLS_FIB_DEFAULT_TABLE_ID,
251 : FIB_SOURCE_BIER);
252 :
253 : /*
254 : * stack the entry on the forwarding chain produced by the
255 : * path-list via the ECMP tables.
256 : */
257 10 : fib_path_list_contribute_forwarding(bt->bt_pl,
258 : FIB_FORW_CHAIN_TYPE_BIER,
259 : FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
260 : &dpo);
261 :
262 10 : mpls_fib_index = fib_table_find(FIB_PROTOCOL_MPLS,
263 : MPLS_FIB_DEFAULT_TABLE_ID);
264 10 : bt->bt_lfei = fib_table_entry_special_dpo_add(mpls_fib_index,
265 : &pfx,
266 : FIB_SOURCE_BIER,
267 : FIB_ENTRY_FLAG_EXCLUSIVE,
268 : &dpo);
269 10 : dpo_reset(&dpo);
270 : }
271 10 : }
272 :
273 : static bier_table_t *
274 431 : bier_table_find (const bier_table_id_t *bti)
275 : {
276 : uword *p;
277 : u32 key;
278 :
279 431 : key = bier_table_mk_key(bti);
280 :
281 431 : p = hash_get(bier_tables_by_key, key);
282 :
283 431 : if (NULL != p)
284 : {
285 261 : return (bier_table_get(p[0]));
286 : }
287 :
288 170 : return (NULL);
289 : }
290 :
291 : static bier_table_t *
292 10 : bier_table_mk_ecmp (index_t bti)
293 : {
294 : fib_route_path_t *rpaths;
295 : fib_node_index_t pli;
296 : bier_table_t *bt;
297 : int ii;
298 :
299 10 : rpaths = NULL;
300 10 : bt = bier_table_get(bti);
301 :
302 10 : vec_validate(rpaths, BIER_N_ECMP_TABLES-1);
303 :
304 170 : vec_foreach_index(ii, rpaths)
305 : {
306 160 : rpaths[ii].frp_bier_tbl = bt->bt_id;
307 160 : rpaths[ii].frp_bier_tbl.bti_ecmp = ii;
308 160 : rpaths[ii].frp_flags = FIB_ROUTE_PATH_BIER_TABLE;
309 : }
310 :
311 : /*
312 : * no opportunity to share, this the resolving ECMP tables are unique
313 : * to this table.
314 : * no need to be a child of the path list, we can do nothing with any
315 : * notifications it would generate [not that it will].
316 : */
317 10 : pli = fib_path_list_create(FIB_PATH_LIST_FLAG_NO_URPF, rpaths);
318 10 : fib_path_list_lock(pli);
319 :
320 : /*
321 : * constructing the path-list will have created many more BIER tables,
322 : * so this main table will no doubt have re-alloc.
323 : */
324 10 : bt = bier_table_get(bti);
325 10 : bt->bt_pl = pli;
326 :
327 10 : vec_free(rpaths);
328 :
329 10 : return (bt);
330 : }
331 :
332 :
333 : static index_t
334 170 : bier_table_create (const bier_table_id_t *btid,
335 : mpls_label_t local_label)
336 : {
337 : /*
338 : * add a new table
339 : */
340 : bier_table_t *bt;
341 : index_t bti;
342 : u32 key;
343 :
344 170 : key = bier_table_mk_key(btid);
345 :
346 170 : pool_get_aligned(bier_table_pool, bt, CLIB_CACHE_LINE_BYTES);
347 170 : bier_table_init(bt, btid, local_label);
348 :
349 170 : hash_set(bier_tables_by_key, key, bier_table_get_index(bt));
350 170 : bti = bier_table_get_index(bt);
351 :
352 170 : if (bier_table_is_main(bt))
353 : {
354 10 : bt = bier_table_mk_ecmp(bti);
355 :
356 : /*
357 : * add whichever mpls-fib or bift we need
358 : */
359 10 : if (local_label != MPLS_LABEL_INVALID)
360 : {
361 9 : bt->bt_ll = local_label;
362 9 : bier_table_mk_lfib(bt);
363 : }
364 : else
365 : {
366 1 : bier_table_mk_bift(bt);
367 : }
368 : }
369 :
370 170 : return (bti);
371 : }
372 :
373 : index_t
374 7 : bier_table_lock (const bier_table_id_t *btid)
375 : {
376 : bier_table_t *bt;
377 : index_t bti;
378 :
379 7 : bt = bier_table_find(btid);
380 :
381 7 : if (NULL == bt)
382 : {
383 0 : bti = bier_table_create(btid, MPLS_LABEL_INVALID);
384 0 : bt = bier_table_get(bti);
385 : }
386 : else
387 : {
388 7 : bti = bier_table_get_index(bt);
389 : }
390 :
391 7 : bier_table_lock_i(bt);
392 :
393 7 : return (bti);
394 : }
395 :
396 : index_t
397 187 : bier_table_add_or_lock (const bier_table_id_t *btid,
398 : mpls_label_t local_label)
399 : {
400 : bier_table_t *bt;
401 : index_t bti;
402 :
403 187 : bt = bier_table_find(btid);
404 :
405 187 : if (NULL != bt) {
406 : /*
407 : * modify an existing table.
408 : * change the lfib entry to the new local label
409 : */
410 17 : if (bier_table_is_main(bt))
411 : {
412 : /*
413 : * remove the mpls-fib or bift entry
414 : */
415 1 : if (MPLS_LABEL_INVALID != bt->bt_ll)
416 : {
417 1 : bier_table_rm_lfib(bt);
418 : }
419 : else
420 : {
421 0 : bier_table_rm_bift(bt);
422 : }
423 :
424 : /*
425 : * reset
426 : */
427 1 : bt->bt_ll = MPLS_LABEL_INVALID;
428 :
429 : /*
430 : * add whichever mpls-fib or bift we need
431 : */
432 1 : if (local_label != MPLS_LABEL_INVALID)
433 : {
434 1 : bt->bt_ll = local_label;
435 1 : bier_table_mk_lfib(bt);
436 : }
437 : else
438 : {
439 0 : bier_table_mk_bift(bt);
440 : }
441 : }
442 17 : bti = bier_table_get_index(bt);
443 : }
444 : else
445 : {
446 170 : bti = bier_table_create(btid, local_label);
447 170 : bt = bier_table_get(bti);
448 : }
449 :
450 187 : bier_table_lock_i(bt);
451 :
452 187 : return (bti);
453 : }
454 :
455 : index_t
456 176 : bier_table_ecmp_create_and_lock (const bier_table_id_t *btid)
457 : {
458 176 : return (bier_table_add_or_lock(btid, MPLS_LABEL_INVALID));
459 : }
460 :
461 : void
462 176 : bier_table_ecmp_unlock (index_t bti)
463 : {
464 176 : bier_table_unlock_i(bier_table_get(bti));
465 176 : }
466 :
467 : static void
468 1360 : bier_table_dpo_lock (dpo_id_t *dpo)
469 : {
470 1360 : }
471 :
472 : static void
473 1360 : bier_table_dpo_unlock (dpo_id_t *dpo)
474 : {
475 1360 : }
476 :
477 : static void
478 0 : bier_table_dpo_mem_show (void)
479 : {
480 0 : fib_show_memory_usage("BIER-table",
481 0 : pool_elts(bier_table_pool),
482 0 : pool_len(bier_table_pool),
483 : sizeof(bier_table_t));
484 0 : }
485 : static u8 *
486 2736 : format_bier_table_dpo (u8 *s, va_list *ap)
487 : {
488 2736 : index_t bti = va_arg(*ap, index_t);
489 : bier_table_t *bt;
490 :
491 2736 : bt = bier_table_get(bti);
492 :
493 2736 : return (format(s, "[%U]", format_bier_table_id, &bt->bt_id));
494 : }
495 :
496 : const static dpo_vft_t bier_table_dpo_vft = {
497 : .dv_lock = bier_table_dpo_lock,
498 : .dv_unlock = bier_table_dpo_unlock,
499 : .dv_format = format_bier_table_dpo,
500 : .dv_mem_show = bier_table_dpo_mem_show,
501 : };
502 :
503 : const static char *const bier_table_mpls_nodes[] =
504 : {
505 : "bier-input",
506 : NULL
507 : };
508 : const static char * const * const bier_table_nodes[DPO_PROTO_NUM] =
509 : {
510 : [DPO_PROTO_BIER] = bier_table_mpls_nodes,
511 : };
512 :
513 : static clib_error_t *
514 559 : bier_table_module_init (vlib_main_t *vm)
515 : {
516 559 : dpo_register(DPO_BIER_TABLE, &bier_table_dpo_vft, bier_table_nodes);
517 :
518 559 : return (NULL);
519 : }
520 :
521 90159 : VLIB_INIT_FUNCTION (bier_table_module_init);
522 :
523 : const bier_table_id_t *
524 2621 : bier_table_get_id (index_t bti)
525 : {
526 : bier_table_t *bt;
527 :
528 2621 : bt = bier_table_get(bti);
529 :
530 2621 : return (&bt->bt_id);
531 : }
532 :
533 : static void
534 76 : bier_table_insert (bier_table_t *bt,
535 : bier_bp_t bp,
536 : index_t bei)
537 : {
538 76 : bt->bt_entries[BIER_BP_TO_INDEX(bp)] = bei;
539 76 : }
540 :
541 : static void
542 76 : bier_table_remove (bier_table_t *bt,
543 : bier_bp_t bp)
544 : {
545 76 : bt->bt_entries[BIER_BP_TO_INDEX(bp)] = INDEX_INVALID;
546 76 : }
547 :
548 : void
549 78 : bier_table_route_path_update_i (const bier_table_id_t *btid,
550 : bier_bp_t bp,
551 : fib_route_path_t *brps,
552 : u8 is_replace)
553 : {
554 78 : index_t bfmi, bti, bei, *bfmip, *bfmis = NULL;
555 : fib_route_path_t *brp;
556 : bier_table_t *bt;
557 :
558 78 : bt = bier_table_find(btid);
559 :
560 78 : if (NULL == bt) {
561 0 : return;
562 : }
563 :
564 78 : bti = bier_table_get_index(bt);
565 78 : bei = bier_table_lookup(bt, bp);
566 :
567 : /*
568 : * set the FIB index in the path to the BIER table index
569 : */
570 160 : vec_foreach(brp, brps)
571 : {
572 : /*
573 : * First use the path to find or construct an FMask object
574 : * via the next-hop
575 : */
576 82 : bfmi = bier_fmask_db_find_or_create_and_lock(bti, brp);
577 82 : vec_add1(bfmis, bfmi);
578 :
579 : /*
580 : * then modify the path to resolve via this fmask object
581 : * and use it to resolve the BIER entry.
582 : */
583 82 : brp->frp_flags = FIB_ROUTE_PATH_BIER_FMASK;
584 82 : brp->frp_bier_fmask = bfmi;
585 : }
586 :
587 78 : if (INDEX_INVALID == bei)
588 : {
589 76 : bei = bier_entry_create(bti, bp);
590 76 : bier_table_insert(bt, bp, bei);
591 : }
592 :
593 78 : if (is_replace)
594 : {
595 2 : bier_entry_path_update(bei, brps);
596 : }
597 : else
598 : {
599 76 : fib_route_path_t *t_paths = NULL;
600 :
601 153 : vec_foreach(brp, brps)
602 : {
603 77 : vec_add1(t_paths, *brp);
604 77 : bier_entry_path_add(bei, t_paths);
605 77 : vec_reset_length(t_paths);
606 : }
607 76 : vec_free(t_paths);
608 : }
609 :
610 160 : vec_foreach(bfmip, bfmis)
611 : {
612 82 : bier_fmask_unlock(*bfmip);
613 : }
614 78 : vec_free(bfmis);
615 : }
616 :
617 : void
618 2 : bier_table_route_path_update (const bier_table_id_t *btid,
619 : bier_bp_t bp,
620 : fib_route_path_t *brps)
621 : {
622 2 : bier_table_route_path_update_i(btid, bp, brps, 1);
623 2 : }
624 : void
625 76 : bier_table_route_path_add (const bier_table_id_t *btid,
626 : bier_bp_t bp,
627 : fib_route_path_t *brps)
628 : {
629 76 : bier_table_route_path_update_i(btid, bp, brps, 0);
630 76 : }
631 :
632 : void
633 2 : bier_table_route_delete (const bier_table_id_t *btid,
634 : bier_bp_t bp)
635 : {
636 : bier_table_t *bt;
637 : index_t bei;
638 :
639 2 : bt = bier_table_find(btid);
640 :
641 2 : if (NULL == bt) {
642 0 : return;
643 : }
644 :
645 2 : bei = bier_table_lookup(bt, bp);
646 :
647 2 : if (INDEX_INVALID == bei)
648 : {
649 : /* no such entry */
650 0 : return;
651 : }
652 :
653 2 : bier_table_remove(bt, bp);
654 2 : bier_entry_delete(bei);
655 : }
656 :
657 : void
658 78 : bier_table_route_path_remove (const bier_table_id_t *btid,
659 : bier_bp_t bp,
660 : fib_route_path_t *brps)
661 : {
662 78 : fib_route_path_t *brp = NULL, *t_paths = NULL;
663 : index_t bfmi, bti, bei;
664 : bier_table_t *bt;
665 : u32 ii;
666 :
667 78 : bt = bier_table_find(btid);
668 :
669 78 : if (NULL == bt) {
670 1 : return;
671 : }
672 :
673 78 : bti = bier_table_get_index(bt);
674 78 : bei = bier_table_lookup(bt, bp);
675 :
676 78 : if (INDEX_INVALID == bei)
677 : {
678 : /* no such entry */
679 0 : return;
680 : }
681 :
682 : /*
683 : * set the FIB index in the path to the BIER table index
684 : */
685 156 : vec_foreach_index(ii, brps)
686 : {
687 78 : brp = &brps[ii];
688 78 : bfmi = bier_fmask_db_find(bti, brp);
689 :
690 78 : if (INDEX_INVALID == bfmi)
691 : {
692 : /*
693 : * no matching fmask, not a path we can remove
694 : */
695 1 : vec_del1(brps, ii);
696 1 : continue;
697 : }
698 :
699 : /*
700 : * then modify the path to resolve via this fmask object
701 : * and use it to resolve the BIER entry.
702 : */
703 77 : brp->frp_flags = FIB_ROUTE_PATH_BIER_FMASK;
704 77 : brp->frp_bier_fmask = bfmi;
705 : }
706 :
707 78 : if (0 == vec_len(brps))
708 : {
709 1 : return;
710 : }
711 :
712 80 : vec_foreach(brp, brps)
713 : {
714 77 : vec_add1(t_paths, *brp);
715 77 : if (0 == bier_entry_path_remove(bei, t_paths))
716 : {
717 : /* 0 remaining paths */
718 74 : bier_table_remove(bt, bp);
719 74 : bier_entry_delete(bei);
720 74 : break;
721 : }
722 3 : vec_reset_length(t_paths);
723 : }
724 77 : vec_free(t_paths);
725 : }
726 :
727 : void
728 575 : bier_table_contribute_forwarding (index_t bti,
729 : dpo_id_t *dpo)
730 : {
731 : bier_table_t *bt;
732 :
733 575 : bt = bier_table_get(bti);
734 :
735 575 : if (BIER_ECMP_TABLE_ID_MAIN == bt->bt_id.bti_ecmp)
736 : {
737 : /*
738 : * return the load-balance for the ECMP tables
739 : */
740 15 : fib_path_list_contribute_forwarding(bt->bt_pl,
741 : FIB_FORW_CHAIN_TYPE_BIER,
742 : FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
743 : dpo);
744 : }
745 : else
746 : {
747 560 : dpo_set(dpo, DPO_BIER_TABLE, DPO_PROTO_BIER, bti);
748 : }
749 575 : }
750 :
751 : typedef struct bier_table_ecmp_walk_ctx_t_
752 : {
753 : bier_table_ecmp_walk_fn_t fn;
754 : void *ctx;
755 : } bier_table_ecmp_walk_ctx_t;
756 :
757 : static fib_path_list_walk_rc_t
758 3760 : bier_table_ecmp_walk_path_list (fib_node_index_t pl_index,
759 : fib_node_index_t path_index,
760 : void *arg)
761 : {
762 3760 : bier_table_ecmp_walk_ctx_t *ctx = arg;
763 :
764 3760 : ctx->fn(fib_path_get_resolving_index(path_index), ctx->ctx);
765 : /* continue */
766 3760 : return (FIB_PATH_LIST_WALK_CONTINUE);
767 : }
768 :
769 : void
770 235 : bier_table_ecmp_walk (index_t bti,
771 : bier_table_ecmp_walk_fn_t fn,
772 : void *ctx)
773 : {
774 235 : bier_table_ecmp_walk_ctx_t ewc = {
775 : .fn = fn,
776 : .ctx = ctx,
777 : };
778 : bier_table_t *bt;
779 :
780 235 : bt = bier_table_get(bti);
781 :
782 235 : if (FIB_NODE_INDEX_INVALID != bt->bt_pl)
783 : {
784 235 : fib_path_list_walk(bt->bt_pl,
785 : bier_table_ecmp_walk_path_list,
786 : &ewc);
787 : }
788 235 : }
789 :
790 : void
791 3760 : bier_table_ecmp_set_fmask (index_t bti,
792 : bier_bp_t bp,
793 : index_t bfmi)
794 : {
795 : bier_table_t *bt;
796 :
797 3760 : bt = bier_table_get(bti);
798 :
799 : /*
800 : * we hold a lock for fmasks in the table
801 : */
802 3760 : bier_fmask_lock(bfmi);
803 3760 : bier_fmask_unlock(bt->bt_fmasks[BIER_BP_TO_INDEX(bp)]);
804 :
805 3760 : bt->bt_fmasks[BIER_BP_TO_INDEX(bp)] = bfmi;
806 3760 : }
807 :
808 : u8 *
809 0 : format_bier_table_entry (u8 *s, va_list *ap)
810 : {
811 0 : index_t bti = va_arg(*ap, index_t);
812 0 : bier_bp_t bp = va_arg(*ap, bier_bp_t);
813 : bier_table_t *bt;
814 0 : bt = bier_table_get(bti);
815 :
816 0 : if (bier_table_is_main(bt))
817 : {
818 : index_t bei;
819 :
820 0 : bei = bier_table_lookup(bier_table_get(bti), bp);
821 :
822 0 : if (INDEX_INVALID != bei)
823 : {
824 0 : s = format(s, "%U", format_bier_entry, bei,
825 : BIER_SHOW_DETAIL);
826 : }
827 : }
828 : else
829 : {
830 : index_t bfmi;
831 :
832 0 : bfmi = bier_table_fwd_lookup(bier_table_get(bti), bp);
833 :
834 0 : if (INDEX_INVALID != bfmi)
835 : {
836 0 : s = format(s, "%U", format_bier_fmask, bfmi,
837 : BIER_SHOW_DETAIL);
838 : }
839 : }
840 0 : return (s);
841 : }
842 :
843 : u8 *
844 0 : format_bier_table (u8 *s, va_list *ap)
845 : {
846 0 : index_t bti = va_arg(*ap, index_t);
847 0 : bier_show_flags_t flags = va_arg(*ap, bier_show_flags_t);
848 : bier_table_t *bt;
849 :
850 0 : if (pool_is_free_index(bier_table_pool, bti))
851 : {
852 0 : return (format(s, "No BIER table %d", bti));
853 : }
854 :
855 0 : bt = bier_table_get(bti);
856 :
857 0 : s = format(s, "[@%d] bier-table:[%U local-label:%U",
858 : bti,
859 : format_bier_table_id, &bt->bt_id,
860 : format_mpls_unicast_label, bt->bt_ll);
861 :
862 0 : if (flags & BIER_SHOW_DETAIL)
863 : {
864 0 : s = format(s, " locks:%d", bt->bt_locks);
865 : }
866 0 : s = format(s, "]");
867 :
868 0 : if (flags & BIER_SHOW_DETAIL)
869 : {
870 0 : if (bier_table_is_main(bt))
871 : {
872 : index_t *bei;
873 :
874 0 : vec_foreach (bei, bt->bt_entries)
875 : {
876 0 : if (INDEX_INVALID != *bei)
877 : {
878 0 : s = format(s, "\n%U", format_bier_entry, *bei, 2);
879 : }
880 : }
881 : }
882 : else
883 : {
884 : u32 ii;
885 :
886 0 : vec_foreach_index (ii, bt->bt_fmasks)
887 : {
888 0 : if (INDEX_INVALID != bt->bt_fmasks[ii])
889 : {
890 0 : s = format(s, "\n bp:%d\n %U", ii,
891 0 : format_bier_fmask, bt->bt_fmasks[ii], 2);
892 : }
893 : }
894 : }
895 : }
896 :
897 0 : return (s);
898 : }
899 :
900 : void
901 0 : bier_table_show_all (vlib_main_t * vm,
902 : bier_show_flags_t flags)
903 : {
904 0 : if (!pool_elts(bier_table_pool))
905 : {
906 0 : vlib_cli_output (vm, "No BIER tables");
907 : }
908 : else
909 : {
910 : int ii;
911 :
912 0 : pool_foreach_index (ii, bier_table_pool)
913 : {
914 0 : vlib_cli_output (vm, "%U", format_bier_table, ii, flags);
915 : }
916 : }
917 0 : }
918 :
919 : void
920 0 : bier_tables_walk (bier_tables_walk_fn_t fn,
921 : void *ctx)
922 : {
923 0 : ASSERT(0);
924 0 : }
925 :
926 :
927 : void
928 79 : bier_table_walk (const bier_table_id_t *bti,
929 : bier_table_walk_fn_t fn,
930 : void *ctx)
931 : {
932 : bier_table_t *bt;
933 : bier_entry_t *be;
934 : index_t *bei;
935 :
936 79 : bt = bier_table_find(bti);
937 :
938 79 : if (NULL == bt)
939 : {
940 0 : return;
941 : }
942 :
943 7134 : vec_foreach (bei, bt->bt_entries)
944 : {
945 7055 : if (INDEX_INVALID != *bei)
946 : {
947 11 : be = bier_entry_get(*bei);
948 :
949 11 : fn(bt, be, ctx);
950 : }
951 : }
952 : }
|