LCOV - code coverage report
Current view: top level - vnet/bier - bier_disp_table.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 90 130 69.2 %
Date: 2023-07-05 22:20:52 Functions: 21 25 84.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 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/bier/bier_disp_table.h>
      17             : #include <vnet/bier/bier_disp_entry.h>
      18             : 
      19             : /**
      20             :  * memory pool for disposition tables
      21             :  */
      22             : bier_disp_table_t *bier_disp_table_pool;
      23             : 
      24             : /**
      25             :  * Hash table to map client table IDs to VPP index
      26             :  */
      27             : static uword *bier_disp_table_id_to_index;
      28             : 
      29             : static index_t
      30           8 : bier_disp_table_get_index (const bier_disp_table_t *bdt)
      31             : {
      32           8 :     return (bdt - bier_disp_table_pool);
      33             : }
      34             : 
      35             : static void
      36          33 : bier_disp_table_lock_i (bier_disp_table_t *bdt)
      37             : {
      38          33 :     bdt->bdt_locks++;
      39          33 : }
      40             : 
      41             : index_t
      42          38 : bier_disp_table_find(u32 table_id)
      43             : {
      44             :     uword *p;
      45             : 
      46          38 :     p = hash_get(bier_disp_table_id_to_index, table_id);
      47             : 
      48          38 :     if (NULL != p)
      49             :     {
      50          34 :         return (p[0]);
      51             :     }
      52             : 
      53           4 :     return (INDEX_INVALID);
      54             : }
      55             : 
      56             : index_t
      57           4 : bier_disp_table_add_or_lock (u32 table_id)
      58             : {
      59             :     bier_disp_table_t *bdt;
      60             :     index_t bdti;
      61             : 
      62           4 :     bdti = bier_disp_table_find(table_id);
      63             : 
      64           4 :     if (INDEX_INVALID == bdti)
      65             :     {
      66           4 :         pool_get_aligned(bier_disp_table_pool, bdt,
      67             :                          CLIB_CACHE_LINE_BYTES);
      68             : 
      69           4 :         bdt->bdt_table_id = table_id;
      70           4 :         bdt->bdt_locks = 0;
      71             : 
      72           4 :         hash_set(bier_disp_table_id_to_index, table_id,
      73             :                  bier_disp_table_get_index(bdt));
      74             : 
      75             :         /**
      76             :          * Set the result for each entry in the DB to be invalid
      77             :          */
      78           4 :         clib_memset(bdt->bdt_db, 0xff, sizeof(bdt->bdt_db));
      79             :     }
      80             :     else
      81             :     {
      82           0 :         bdt = pool_elt_at_index(bier_disp_table_pool, bdti);
      83             :     }
      84             : 
      85           4 :     bier_disp_table_lock_i(bdt);
      86             : 
      87           4 :     return (bier_disp_table_get_index(bdt));
      88             : }
      89             : 
      90             : void
      91           4 : bier_disp_table_unlock_w_table_id (u32 table_id)
      92             : {
      93             :     index_t bdti;
      94             : 
      95           4 :     bdti = bier_disp_table_find(table_id);
      96             : 
      97           4 :     if (INDEX_INVALID != bdti)
      98             :     {
      99           4 :         bier_disp_table_unlock(bdti);
     100             :     }
     101           4 : }
     102             : 
     103             : void
     104          33 : bier_disp_table_unlock (index_t bdti)
     105             : {
     106             :     bier_disp_table_t *bdt;
     107             : 
     108          33 :     bdt = bier_disp_table_get(bdti);
     109             : 
     110          33 :     bdt->bdt_locks--;
     111             : 
     112          33 :     if (0 == bdt->bdt_locks)
     113             :     {
     114             :         u32 ii;
     115             : 
     116      262148 :         for (ii = 0; ii < BIER_BP_MAX; ii++)
     117             :         {
     118      262144 :             bier_disp_entry_unlock(bdt->bdt_db[ii]);
     119             :         }
     120           4 :         hash_unset(bier_disp_table_id_to_index, bdt->bdt_table_id);
     121           4 :         pool_put(bier_disp_table_pool, bdt);
     122             :     }
     123          33 : }
     124             : 
     125             : void
     126          29 : bier_disp_table_lock (index_t bdti)
     127             : {
     128          29 :     bier_disp_table_lock_i(bier_disp_table_get(bdti));
     129          29 : }
     130             : 
     131             : void
     132           5 : bier_disp_table_contribute_forwarding (index_t bdti,
     133             :                                        dpo_id_t *dpo)
     134             : {
     135           5 :     dpo_set(dpo,
     136             :             DPO_BIER_DISP_TABLE,
     137             :             DPO_PROTO_BIER,
     138             :             bdti);
     139           5 : }
     140             : 
     141             : 
     142             : u8*
     143           0 : format_bier_disp_table (u8* s, va_list *ap)
     144             : {
     145           0 :     index_t bdti = va_arg(*ap, index_t);
     146           0 :     u32 indent = va_arg(*ap, u32);
     147           0 :     bier_show_flags_t flags = va_arg(*ap, bier_show_flags_t);
     148             :     bier_disp_table_t *bdt;
     149             : 
     150           0 :     bdt = bier_disp_table_get(bdti);
     151             : 
     152           0 :     s = format(s, "bier-disp-table:[%d]; table-id:%d locks:%d",
     153           0 :                bdti, bdt->bdt_table_id, bdt->bdt_locks);
     154             : 
     155           0 :     if (flags & BIER_SHOW_DETAIL)
     156             :     {
     157             :         u32 ii;
     158             : 
     159           0 :         for (ii = 0; ii < BIER_BP_MAX; ii++)
     160             :         {
     161           0 :             if (INDEX_INVALID != bdt->bdt_db[ii])
     162             :             {
     163           0 :                 u16 src = ii;
     164           0 :                 s = format(s, "\n%Usrc:%d", format_white_space, indent+1,
     165           0 :                            clib_host_to_net_u16(src));
     166           0 :                 s = format(s, "\n%U",
     167             :                            format_bier_disp_entry, bdt->bdt_db[ii],
     168             :                            indent+4, BIER_SHOW_BRIEF);
     169             :             }
     170             :         }
     171             :     }
     172           0 :     return (s);
     173             : }
     174             : 
     175             : static u8*
     176           0 : format_bier_disp_table_dpo (u8* s, va_list *ap)
     177             : {
     178           0 :     index_t bdti = va_arg(*ap, index_t);
     179           0 :     u32 indent = va_arg(*ap, u32);
     180             : 
     181           0 :     return (format(s, "%U",
     182             :                    format_bier_disp_table, bdti, indent,
     183             :                    BIER_SHOW_BRIEF));
     184             : }
     185             : 
     186             : static void
     187           6 : bier_disp_table_entry_insert (index_t bdti,
     188             :                               bier_bp_t src,
     189             :                               index_t bdei)
     190             : {
     191             :     bier_disp_table_t *bdt;
     192             : 
     193           6 :     bdt = bier_disp_table_get(bdti);
     194           6 :     bdt->bdt_db[clib_host_to_net_u16(src)] = bdei;
     195           6 : }
     196             : 
     197             : static void
     198           6 : bier_disp_table_entry_remove (index_t bdti,
     199             :                               bier_bp_t src)
     200             : {
     201             :     bier_disp_table_t *bdt;
     202             : 
     203           6 :     bdt = bier_disp_table_get(bdti);
     204           6 :     bdt->bdt_db[clib_host_to_net_u16(src)] = INDEX_INVALID;
     205           6 : }
     206             : 
     207             : static index_t
     208          12 : bier_disp_table_lookup_hton(index_t bdti,
     209             :                             bier_bp_t bp)
     210             : {
     211          12 :     bier_hdr_src_id_t src = bp;
     212             : 
     213          12 :     return (bier_disp_table_lookup(bdti, clib_host_to_net_u16(src)));
     214             : }
     215             : 
     216             : void
     217           6 : bier_disp_table_entry_path_add (u32 table_id,
     218             :                                 bier_bp_t src,
     219             :                                 bier_hdr_proto_id_t payload_proto,
     220             :                                 const fib_route_path_t *rpaths)
     221             : {
     222             :     index_t bdti, bdei;
     223             : 
     224           6 :     bdti = bier_disp_table_find(table_id);
     225             : 
     226           6 :     if (INDEX_INVALID == bdti)
     227             :     {
     228           0 :         return;
     229             :     }
     230             : 
     231           6 :     bdei = bier_disp_table_lookup_hton(bdti, src);
     232             : 
     233           6 :     if (INDEX_INVALID == bdei)
     234             :     {
     235           6 :         bdei = bier_disp_entry_add_or_lock();
     236           6 :         bier_disp_table_entry_insert(bdti, src, bdei);
     237             :     }
     238             : 
     239           6 :     bier_disp_entry_path_add(bdei, payload_proto, rpaths);
     240             : }
     241             : 
     242             : void
     243           6 : bier_disp_table_entry_path_remove (u32 table_id,
     244             :                                    bier_bp_t src,
     245             :                                    bier_hdr_proto_id_t payload_proto,
     246             :                                    const fib_route_path_t *rpath)
     247             : {
     248             :     index_t bdti, bdei;
     249             : 
     250           6 :     bdti = bier_disp_table_find(table_id);
     251             : 
     252           6 :     if (INDEX_INVALID == bdti)
     253             :     {
     254           0 :         return;
     255             :     }
     256             : 
     257           6 :     bdei = bier_disp_table_lookup_hton(bdti, src);
     258             : 
     259           6 :     if (INDEX_INVALID != bdei)
     260             :     {
     261             :         int remove;
     262             : 
     263           6 :         remove = bier_disp_entry_path_remove(bdei, payload_proto, rpath);
     264             : 
     265           6 :         if (remove)
     266             :         {
     267           6 :             bier_disp_table_entry_remove(bdti, src);
     268           6 :             bier_disp_entry_unlock(bdei);
     269             :         }
     270             :     }
     271             : }
     272             : 
     273             : void
     274          10 : bier_disp_table_walk (u32 table_id,
     275             :                       bier_disp_table_walk_fn_t fn,
     276             :                       void *ctx)
     277             : {
     278             :     const bier_disp_table_t *bdt;
     279             :     const bier_disp_entry_t *bde;
     280             :     index_t bdti;
     281             :     u32 ii;
     282             : 
     283          10 :     bdti = bier_disp_table_find(table_id);
     284             : 
     285          10 :     if (INDEX_INVALID != bdti)
     286             :     {
     287          10 :         bdt = bier_disp_table_get(bdti);
     288             : 
     289      655370 :         for (ii = 0; ii < BIER_BP_MAX; ii++)
     290             :         {
     291      655360 :             if (INDEX_INVALID != bdt->bdt_db[ii])
     292             :             {
     293           9 :                 u16 src = ii;
     294             : 
     295           9 :                 bde = bier_disp_entry_get(bdt->bdt_db[ii]);
     296             : 
     297           9 :                 fn(bdt, bde, clib_host_to_net_u16(src), ctx);
     298             :             }
     299             :         }
     300             :     }
     301          10 : }
     302             : 
     303             : static void
     304          29 : bier_disp_table_dpo_lock (dpo_id_t *dpo)
     305             : {
     306          29 :     bier_disp_table_lock(dpo->dpoi_index);
     307          29 : }
     308             : 
     309             : static void
     310          29 : bier_disp_table_dpo_unlock (dpo_id_t *dpo)
     311             : {
     312          29 :     bier_disp_table_unlock(dpo->dpoi_index);
     313          29 : }
     314             : 
     315             : static void
     316           0 : bier_disp_table_dpo_mem_show (void)
     317             : {
     318           0 :     fib_show_memory_usage("BIER disposition table",
     319           0 :                           pool_elts(bier_disp_table_pool),
     320           0 :                           pool_len(bier_disp_table_pool),
     321             :                           sizeof(bier_disp_table_t));
     322           0 : }
     323             : 
     324             : const static dpo_vft_t bier_disp_table_dpo_vft = {
     325             :     .dv_lock = bier_disp_table_dpo_lock,
     326             :     .dv_unlock = bier_disp_table_dpo_unlock,
     327             :     .dv_mem_show = bier_disp_table_dpo_mem_show,
     328             :     .dv_format = format_bier_disp_table_dpo,
     329             : };
     330             : 
     331             : const static char *const bier_disp_table_bier_nodes[] =
     332             : {
     333             :     "bier-disp-lookup",
     334             :     NULL
     335             : };
     336             : 
     337             : const static char * const * const bier_disp_table_nodes[DPO_PROTO_NUM] =
     338             : {
     339             :     [DPO_PROTO_BIER] = bier_disp_table_bier_nodes,
     340             : };
     341             : 
     342             : clib_error_t *
     343         559 : bier_disp_table_module_init (vlib_main_t *vm)
     344             : {
     345         559 :     dpo_register(DPO_BIER_DISP_TABLE,
     346             :                  &bier_disp_table_dpo_vft,
     347             :                  bier_disp_table_nodes);
     348             : 
     349         559 :     bier_disp_table_id_to_index = hash_create(0, sizeof(index_t));
     350             : 
     351         559 :     return (NULL);
     352             : }
     353             : 
     354       91839 : VLIB_INIT_FUNCTION (bier_disp_table_module_init);
     355             : 
     356             : static clib_error_t *
     357           0 : show_bier_disp_table (vlib_main_t * vm,
     358             :                       unformat_input_t * input,
     359             :                       vlib_cli_command_t * cmd)
     360             : {
     361             :     bier_disp_table_t *bdt;
     362             :     index_t bdti;
     363             : 
     364           0 :     bdti = INDEX_INVALID;
     365             : 
     366           0 :     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
     367           0 :         if (unformat (input, "%d", &bdti))
     368             :             ;
     369           0 :         else if (unformat (input, "%d", &bdti))
     370             :             ;
     371             :         else
     372             :         {
     373           0 :             break;
     374             :         }
     375             :     }
     376             : 
     377           0 :     if (INDEX_INVALID == bdti)
     378             :     {
     379           0 :         pool_foreach (bdt, bier_disp_table_pool)
     380             :          {
     381           0 :             vlib_cli_output(vm, "%U", format_bier_disp_table,
     382             :                             bier_disp_table_get_index(bdt),
     383             :                             0, BIER_SHOW_BRIEF);
     384             :         }
     385             :     }
     386             :     else
     387             :     {
     388           0 :         if (pool_is_free_index(bier_disp_table_pool, bdti))
     389             :         {
     390           0 :             vlib_cli_output(vm, "No such BIER disp table: %d", bdti);
     391             :         }
     392             :         else
     393             :         {
     394           0 :             vlib_cli_output(vm, "%U", format_bier_disp_table, bdti, 0,
     395             :                             BIER_SHOW_DETAIL);
     396             :         }
     397             :     }
     398           0 :     return (NULL);
     399             : }
     400             : 
     401      272887 : VLIB_CLI_COMMAND (show_bier_disp_table_node, static) = {
     402             :     .path = "show bier disp table",
     403             :     .short_help = "show bier disp table [index]",
     404             :     .function = show_bier_disp_table,
     405             : };

Generated by: LCOV version 1.14