LCOV - code coverage report
Current view: top level - vnet/bier - bier_disp_entry.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 74 127 58.3 %
Date: 2023-07-05 22:20:52 Functions: 13 21 61.9 %

          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             :  * bier_disposition : The BIER disposition object
      17             :  *
      18             :  * A BIER disposition object is present in the IP mcast output list
      19             :  * and represents the disposition of a BIER bitmask. After BIER header
      20             :  * disposition the packet is forward within the appropriate/specified
      21             :  * BIER table
      22             :  */
      23             : 
      24             : #include <vnet/bier/bier_disp_entry.h>
      25             : #include <vnet/bier/bier_hdr_inlines.h>
      26             : #include <vnet/fib/fib_path_list.h>
      27             : #include <vnet/dpo/drop_dpo.h>
      28             : 
      29             : /**
      30             :  * The memory pool of all imp objects
      31             :  */
      32             : bier_disp_entry_t *bier_disp_entry_pool;
      33             : 
      34             : /**
      35             :  * When constructing the BIER imp ID from an index and BSL, shift
      36             :  * the BSL this far
      37             :  */
      38             : #define BIER_DISP_ENTRY_ID_HLEN_SHIFT 24
      39             : 
      40             : static void
      41           6 : bier_disp_entry_lock_i (bier_disp_entry_t *bde)
      42             : {
      43           6 :     bde->bde_locks++;
      44           6 : }
      45             : 
      46             : void
      47           0 : bier_disp_entry_lock (index_t bdei)
      48             : {
      49           0 :     bier_disp_entry_lock_i(bier_disp_entry_get(bdei));
      50           0 : }
      51             : 
      52             : static index_t
      53           6 : bier_disp_entry_get_index(bier_disp_entry_t *bde)
      54             : {
      55           6 :     return (bde - bier_disp_entry_pool);
      56             : }
      57             : 
      58             : index_t
      59           6 : bier_disp_entry_add_or_lock (void)
      60             : {
      61           6 :     dpo_id_t invalid = DPO_INVALID;
      62             :     bier_hdr_proto_id_t pproto;
      63             :     bier_disp_entry_t *bde;
      64             : 
      65           6 :     pool_get_aligned(bier_disp_entry_pool, bde, CLIB_CACHE_LINE_BYTES);
      66             : 
      67           6 :     bde->bde_locks = 0;
      68             : 
      69          54 :     FOR_EACH_BIER_HDR_PROTO(pproto)
      70             :     {
      71          48 :         bde->bde_fwd[pproto].bde_dpo = invalid;
      72          48 :         bde->bde_fwd[pproto].bde_rpf_id = ~0;
      73          48 :         bde->bde_pl[pproto] = FIB_NODE_INDEX_INVALID;
      74             :     }
      75             : 
      76           6 :     bier_disp_entry_lock_i(bde);
      77           6 :     return (bier_disp_entry_get_index(bde));
      78             : }
      79             : 
      80             : void
      81      262150 : bier_disp_entry_unlock (index_t bdei)
      82             : {
      83             :     bier_disp_entry_t *bde;
      84             : 
      85      262150 :     if (INDEX_INVALID == bdei)
      86             :     {
      87      262144 :         return;
      88             :     }
      89             : 
      90           6 :     bde = bier_disp_entry_get(bdei);
      91             : 
      92           6 :     bde->bde_locks--;
      93             : 
      94           6 :     if (0 == bde->bde_locks)
      95             :     {
      96             :         bier_hdr_proto_id_t pproto;
      97             : 
      98          54 :         FOR_EACH_BIER_HDR_PROTO(pproto)
      99             :         {
     100          48 :             dpo_unlock(&bde->bde_fwd[pproto].bde_dpo);
     101          48 :             bde->bde_fwd[pproto].bde_rpf_id = ~0;
     102          48 :             fib_path_list_unlock(bde->bde_pl[pproto]);
     103             :         }
     104           6 :         pool_put(bier_disp_entry_pool, bde);
     105             :     }
     106             : }
     107             : 
     108             : typedef struct bier_disp_entry_path_list_walk_ctx_t_
     109             : {
     110             :     u32 bdew_rpf_id;
     111             : } bier_disp_entry_path_list_walk_ctx_t;
     112             : 
     113             : static fib_path_list_walk_rc_t
     114           6 : bier_disp_entry_path_list_walk (fib_node_index_t pl_index,
     115             :                                 fib_node_index_t path_index,
     116             :                                 void *arg)
     117             : {
     118           6 :     bier_disp_entry_path_list_walk_ctx_t *ctx = arg;
     119             : 
     120           6 :     ctx->bdew_rpf_id = fib_path_get_rpf_id(path_index);
     121             : 
     122           6 :     if (~0 != ctx->bdew_rpf_id)
     123             :     {
     124           6 :         return (FIB_PATH_LIST_WALK_STOP);
     125             :     }
     126           0 :     return (FIB_PATH_LIST_WALK_CONTINUE);
     127             : }
     128             : 
     129             : static void
     130          12 : bier_disp_entry_restack (bier_disp_entry_t *bde,
     131             :                          bier_hdr_proto_id_t pproto)
     132             : {
     133          12 :     dpo_id_t via_dpo = DPO_INVALID;
     134             :     fib_node_index_t pli;
     135             : 
     136          12 :     pli = bde->bde_pl[pproto];
     137             : 
     138          12 :     if (FIB_NODE_INDEX_INVALID == pli)
     139             :     {
     140           6 :         dpo_copy(&via_dpo,
     141           6 :                  drop_dpo_get(bier_hdr_proto_to_dpo(pproto)));
     142             :     }
     143             :     else
     144             :     {
     145           6 :         fib_path_list_contribute_forwarding(pli,
     146           6 :                                             fib_forw_chain_type_from_dpo_proto(
     147           6 :                                                 bier_hdr_proto_to_dpo(pproto)),
     148             :                                             FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
     149             :                                             &via_dpo);
     150             : 
     151           6 :         bier_disp_entry_path_list_walk_ctx_t ctx = {
     152             :             .bdew_rpf_id = ~0,
     153             :         };
     154             : 
     155           6 :         fib_path_list_walk(pli, bier_disp_entry_path_list_walk, &ctx);
     156           6 :         bde->bde_fwd[pproto].bde_rpf_id = ctx.bdew_rpf_id;
     157             :     }
     158             : 
     159          12 :     dpo_stack(DPO_BIER_DISP_ENTRY,
     160             :               DPO_PROTO_BIER,
     161          12 :               &bde->bde_fwd[pproto].bde_dpo,
     162             :               &via_dpo);
     163          12 : }
     164             : 
     165             : void
     166           6 : bier_disp_entry_path_add (index_t bdei,
     167             :                           bier_hdr_proto_id_t pproto,
     168             :                           const fib_route_path_t *rpaths)
     169             : {
     170             :     fib_node_index_t *pli, old_pli;
     171             :     bier_disp_entry_t *bde;
     172             : 
     173           6 :     bde = bier_disp_entry_get(bdei);
     174           6 :     pli = &bde->bde_pl[pproto];
     175           6 :     old_pli = *pli;
     176             : 
     177             :     /*
     178             :      * create a new or update the existing path-list for this
     179             :      * payload protocol
     180             :      */
     181           6 :     if (FIB_NODE_INDEX_INVALID == *pli)
     182             :     {
     183           6 :         *pli = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
     184             :                                      FIB_PATH_LIST_FLAG_NO_URPF),
     185             :                                     rpaths);
     186             :     }
     187             :     else
     188             :     {
     189           0 :         *pli = fib_path_list_copy_and_path_add(old_pli,
     190             :                                                (FIB_PATH_LIST_FLAG_SHARED |
     191             :                                                 FIB_PATH_LIST_FLAG_NO_URPF),
     192             :                                                rpaths);
     193             :     }
     194             : 
     195           6 :     fib_path_list_lock(*pli);
     196           6 :     fib_path_list_unlock(old_pli);
     197             : 
     198           6 :     bier_disp_entry_restack(bde, pproto);
     199           6 : }
     200             : 
     201             : int
     202           6 : bier_disp_entry_path_remove (index_t bdei,
     203             :                              bier_hdr_proto_id_t pproto,
     204             :                              const fib_route_path_t *rpaths)
     205             : {
     206             :     fib_node_index_t *pli, old_pli;
     207             :     bier_disp_entry_t *bde;
     208             : 
     209           6 :     bde = bier_disp_entry_get(bdei);
     210           6 :     pli = &bde->bde_pl[pproto];
     211           6 :     old_pli = *pli;
     212             : 
     213             :     /*
     214             :      * update the existing path-list for this payload protocol
     215             :      */
     216           6 :     if (FIB_NODE_INDEX_INVALID != *pli)
     217             :     {
     218           6 :         *pli = fib_path_list_copy_and_path_remove(old_pli,
     219             :                                                   (FIB_PATH_LIST_FLAG_SHARED |
     220             :                                                    FIB_PATH_LIST_FLAG_NO_URPF),
     221             :                                                   rpaths);
     222             : 
     223           6 :         fib_path_list_lock(*pli);
     224           6 :         fib_path_list_unlock(old_pli);
     225             : 
     226           6 :         bier_disp_entry_restack(bde, pproto);
     227             :     }
     228             : 
     229             :     /*
     230             :      * if there are no path-list defined for any payload protocol
     231             :      * then this entry is OK for removal
     232             :      */
     233           6 :     int remove = 1;
     234             : 
     235          54 :     FOR_EACH_BIER_HDR_PROTO(pproto)
     236             :     {
     237          48 :         if (FIB_NODE_INDEX_INVALID != bde->bde_pl[pproto])
     238             :         {
     239           0 :             remove = 0;
     240           0 :             break;
     241             :         }
     242             :     }
     243             : 
     244           6 :     return (remove);
     245             : }
     246             : 
     247             : u8*
     248           0 : format_bier_disp_entry (u8* s, va_list *args)
     249             : {
     250           0 :     index_t bdei = va_arg (*args, index_t);
     251           0 :     u32 indent = va_arg(*args, u32);
     252           0 :     bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
     253             :     bier_hdr_proto_id_t pproto;
     254             :     bier_disp_entry_t *bde;
     255             : 
     256           0 :     bde = bier_disp_entry_get(bdei);
     257             : 
     258           0 :     s = format(s, "%Ubier-disp:[%d]", format_white_space, indent, bdei);
     259             : 
     260           0 :     FOR_EACH_BIER_HDR_PROTO(pproto)
     261             :     {
     262           0 :         if (INDEX_INVALID != bde->bde_pl[pproto])
     263             :         {
     264           0 :             s = format(s, "\n%U%U\n",
     265             :                        format_white_space, indent+2,
     266             :                        format_bier_hdr_proto, pproto);
     267           0 :             s = format(s, "%U", format_fib_path_list, bde->bde_pl[pproto], indent+4);
     268             : 
     269           0 :             if (flags & BIER_SHOW_DETAIL)
     270             :             {
     271           0 :                 s = format(s, "\n%UForwarding:",
     272             :                            format_white_space, indent+4);
     273           0 :                 s = format(s, "\n%Urpf-id:%d",
     274             :                            format_white_space, indent+6,
     275             :                            bde->bde_fwd[pproto].bde_rpf_id);
     276           0 :                 s = format(s, "\n%U%U",
     277             :                            format_white_space, indent+6,
     278           0 :                            format_dpo_id, &bde->bde_fwd[pproto].bde_dpo, indent+2);
     279             :             }
     280             :         }
     281             :     }
     282           0 :     return (s);
     283             : }
     284             : 
     285             : void
     286           0 : bier_disp_entry_contribute_forwarding (index_t bdei,
     287             :                                        dpo_id_t *dpo)
     288             : {
     289           0 :     dpo_set(dpo, DPO_BIER_DISP_ENTRY, DPO_PROTO_BIER, bdei);
     290           0 : }
     291             : 
     292             : const static char* const bier_disp_entry_bier_nodes[] =
     293             : {
     294             :     "bier-disp-dispatch",
     295             :     NULL,
     296             : };
     297             : 
     298             : const static char* const * const bier_disp_entry_nodes[DPO_PROTO_NUM] =
     299             : {
     300             :     [DPO_PROTO_BIER]  = bier_disp_entry_bier_nodes,
     301             : };
     302             : 
     303             : static void
     304           0 : bier_disp_entry_dpo_lock (dpo_id_t *dpo)
     305             : {
     306           0 :     bier_disp_entry_lock(dpo->dpoi_index);
     307           0 : }
     308             : 
     309             : static void
     310           0 : bier_disp_entry_dpo_unlock (dpo_id_t *dpo)
     311             : {
     312           0 :     bier_disp_entry_unlock(dpo->dpoi_index);
     313           0 : }
     314             : 
     315             : static void
     316           0 : bier_disp_entry_dpo_mem_show (void)
     317             : {
     318           0 :     fib_show_memory_usage("BIER disposition",
     319           0 :                           pool_elts(bier_disp_entry_pool),
     320           0 :                           pool_len(bier_disp_entry_pool),
     321             :                           sizeof(bier_disp_entry_t));
     322           0 : }
     323             : 
     324             : static u8*
     325           0 : format_bier_disp_entry_dpo (u8* s, va_list *ap)
     326             : {
     327           0 :     index_t index = va_arg(*ap, index_t);
     328           0 :     u32 indent = va_arg(*ap, u32);
     329             : 
     330           0 :     s = format(s, "%U", format_bier_disp_entry, index, indent, BIER_SHOW_DETAIL);
     331             : 
     332           0 :     return (s);
     333             : }
     334             : 
     335             : const static dpo_vft_t bier_disp_entry_vft = {
     336             :     .dv_lock = bier_disp_entry_dpo_lock,
     337             :     .dv_unlock = bier_disp_entry_dpo_unlock,
     338             :     .dv_format = format_bier_disp_entry_dpo,
     339             :     .dv_mem_show = bier_disp_entry_dpo_mem_show,
     340             : };
     341             : 
     342             : clib_error_t *
     343         559 : bier_disp_entry_db_module_init (vlib_main_t *vm)
     344             : {
     345         559 :     dpo_register(DPO_BIER_DISP_ENTRY,
     346             :                  &bier_disp_entry_vft,
     347             :                  bier_disp_entry_nodes);
     348             : 
     349         559 :     return (NULL);
     350             : }
     351             : 
     352       91279 : VLIB_INIT_FUNCTION (bier_disp_entry_db_module_init);
     353             : 
     354             : static clib_error_t *
     355           0 : show_bier_disp_entry (vlib_main_t * vm,
     356             :                unformat_input_t * input,
     357             :                vlib_cli_command_t * cmd)
     358             : {
     359             :     index_t bdei;
     360             : 
     361           0 :     bdei = INDEX_INVALID;
     362             : 
     363           0 :     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
     364           0 :         if (unformat (input, "%d", &bdei))
     365             :             ;
     366             :         else
     367             :         {
     368           0 :             break;
     369             :         }
     370             :     }
     371             : 
     372           0 :     if (INDEX_INVALID == bdei)
     373             :     {
     374           0 :         return (NULL);
     375             :     }
     376             :     else
     377             :     {
     378           0 :         if (pool_is_free_index(bier_disp_entry_pool, bdei))
     379             :         {
     380           0 :             vlib_cli_output(vm, "No such BIER disp entry: %d", bdei);
     381             :         }
     382             :         else
     383             :         {
     384           0 :             vlib_cli_output(vm, "%U", format_bier_disp_entry, bdei, 1,
     385             :                             BIER_SHOW_DETAIL);
     386             :         }
     387             :     }
     388           0 :     return (NULL);
     389             : }
     390             : 
     391      272887 : VLIB_CLI_COMMAND (show_bier_disp_entry_node, static) = {
     392             :     .path = "show bier disp entry",
     393             :     .short_help = "show bier disp entry index",
     394             :     .function = show_bier_disp_entry,
     395             : };

Generated by: LCOV version 1.14