LCOV - code coverage report
Current view: top level - vnet/bier - bier_table.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 253 309 81.9 %
Date: 2023-10-26 01:39:38 Functions: 38 43 88.4 %

          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         575 : bier_table_module_init (vlib_main_t *vm)
     515             : {
     516         575 :     dpo_register(DPO_BIER_TABLE, &bier_table_dpo_vft, bier_table_nodes);
     517             : 
     518         575 :     return (NULL);
     519             : }
     520             : 
     521       92159 : 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             : }

Generated by: LCOV version 1.14