LCOV - code coverage report
Current view: top level - vnet/bier - bier_fmask.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 136 191 71.2 %
Date: 2023-07-05 22:20:52 Functions: 24 29 82.8 %

          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 <vnet/fib/fib_entry.h>
      17             : #include <vnet/fib/fib_table.h>
      18             : #include <vnet/fib/fib_walk.h>
      19             : #include <vnet/fib/fib_path_list.h>
      20             : 
      21             : #include <vnet/bier/bier_table.h>
      22             : #include <vnet/bier/bier_fmask.h>
      23             : #include <vnet/bier/bier_bit_string.h>
      24             : #include <vnet/bier/bier_disp_table.h>
      25             : 
      26             : #include <vnet/mpls/mpls.h>
      27             : #include <vnet/dpo/drop_dpo.h>
      28             : #include <vnet/dpo/load_balance.h>
      29             : 
      30             : /*
      31             :  * attributes names for formatting
      32             :  */
      33             : static const char *const bier_fmask_attr_names[] = BIER_FMASK_ATTR_NAMES;
      34             : 
      35             : /*
      36             :  * pool of BIER fmask objects
      37             :  */
      38             : bier_fmask_t *bier_fmask_pool;
      39             : 
      40             : /**
      41             :  * Stats for each BIER fmask object
      42             :  */
      43             : vlib_combined_counter_main_t bier_fmask_counters;
      44             : 
      45             : static inline index_t
      46         231 : bier_fmask_get_index (const bier_fmask_t *bfm)
      47             : {
      48         231 :     return (bfm - bier_fmask_pool);
      49             : }
      50             : 
      51             : static void
      52          77 : bier_fmask_bits_init (bier_fmask_bits_t *bits,
      53             :                       bier_hdr_len_id_t hlid)
      54             : {
      55         154 :     bits->bfmb_refs = clib_mem_alloc(sizeof(bits->bfmb_refs[0]) *
      56          77 :                                      bier_hdr_len_id_to_num_bits(hlid));
      57          77 :     clib_memset(bits->bfmb_refs,
      58             :            0,
      59             :            (sizeof(bits->bfmb_refs[0]) *
      60             :             bier_hdr_len_id_to_num_bits(hlid)));
      61             : 
      62          77 :     bits->bfmb_input_reset_string.bbs_len =
      63          77 :         bier_hdr_len_id_to_num_buckets(hlid);
      64             : 
      65             :     /*
      66             :      * The buckets are accessed in the switch path
      67             :      */
      68          77 :     bits->bfmb_input_reset_string.bbs_buckets =
      69          77 :         clib_mem_alloc_aligned(
      70             :             sizeof(bits->bfmb_input_reset_string.bbs_buckets[0]) *
      71          77 :             bier_hdr_len_id_to_num_buckets(hlid),
      72             :             CLIB_CACHE_LINE_BYTES);
      73          77 :     clib_memset(bits->bfmb_input_reset_string.bbs_buckets,
      74             :            0,
      75             :            sizeof(bits->bfmb_input_reset_string.bbs_buckets[0]) *
      76             :            bier_hdr_len_id_to_num_buckets(hlid));
      77          77 : }
      78             : 
      79             : static void
      80         154 : bier_fmask_stack (bier_fmask_t *bfm)
      81             : {
      82         154 :     dpo_id_t via_dpo = DPO_INVALID;
      83             :     fib_forward_chain_type_t fct;
      84             : 
      85         154 :     if (bfm->bfm_flags & BIER_FMASK_FLAG_MPLS)
      86             :     {
      87         149 :         fct = FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS;
      88             :     }
      89             :     else
      90             :     {
      91           5 :         fct = FIB_FORW_CHAIN_TYPE_BIER;
      92             :     }
      93             : 
      94         154 :     fib_path_list_contribute_forwarding(bfm->bfm_pl, fct,
      95             :                                         FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
      96             :                                         &via_dpo);
      97             : 
      98             :     /*
      99             :      * If the via PL entry provides no forwarding (i.e. a drop)
     100             :      * then neither does this fmask. That way children consider this fmask
     101             :      * unresolved and other ECMP options are used instead.
     102             :      */
     103         154 :     if (dpo_is_drop(&via_dpo))
     104             :     {
     105           8 :         bfm->bfm_flags &= ~BIER_FMASK_FLAG_FORWARDING;
     106             :     }
     107             :     else
     108             :     {
     109         146 :         bfm->bfm_flags |= BIER_FMASK_FLAG_FORWARDING;
     110             :     }
     111             : 
     112         154 :     dpo_stack(DPO_BIER_FMASK,
     113             :               DPO_PROTO_BIER,
     114             :               &bfm->bfm_dpo,
     115             :               &via_dpo);
     116         154 :     dpo_reset(&via_dpo);
     117         154 : }
     118             : 
     119             : void
     120        2669 : bier_fmask_contribute_forwarding (index_t bfmi,
     121             :                                   dpo_id_t *dpo)
     122             : {
     123             :     bier_fmask_t *bfm;
     124             : 
     125        2669 :     bfm = bier_fmask_get(bfmi);
     126             : 
     127        2669 :     if (bfm->bfm_flags & BIER_FMASK_FLAG_FORWARDING)
     128             :     {
     129        2661 :         dpo_set(dpo,
     130             :                 DPO_BIER_FMASK,
     131             :                 DPO_PROTO_BIER,
     132             :                 bfmi);
     133             :     }
     134             :     else
     135             :     {
     136           8 :         dpo_copy(dpo, drop_dpo_get(DPO_PROTO_BIER));
     137             :     }
     138        2669 : }
     139             : 
     140             : u32
     141          87 : bier_fmask_child_add (fib_node_index_t bfmi,
     142             :                      fib_node_type_t child_type,
     143             :                      fib_node_index_t child_index)
     144             : {
     145          87 :     return (fib_node_child_add(FIB_NODE_TYPE_BIER_FMASK,
     146             :                                bfmi,
     147             :                                child_type,
     148             :                                child_index));
     149             : };
     150             : 
     151             : void
     152         244 : bier_fmask_child_remove (fib_node_index_t bfmi,
     153             :                          u32 sibling_index)
     154             : {
     155         244 :     if (INDEX_INVALID == bfmi)
     156             :     {
     157         157 :         return;
     158             :     }
     159             : 
     160          87 :     fib_node_child_remove(FIB_NODE_TYPE_BIER_FMASK,
     161             :                           bfmi,
     162             :                           sibling_index);
     163             : }
     164             : 
     165             : static void
     166          77 : bier_fmask_init (bier_fmask_t *bfm,
     167             :                  const bier_fmask_id_t *fmid,
     168             :                  const fib_route_path_t *rpath)
     169             : {
     170             :     const bier_table_id_t *btid;
     171             :     fib_route_path_t *rpaths;
     172             :     mpls_label_t olabel;
     173             : 
     174          77 :     clib_memset(bfm, 0, sizeof(*bfm));
     175             :     
     176          77 :     bfm->bfm_id = clib_mem_alloc(sizeof(*bfm->bfm_id));
     177             : 
     178          77 :     fib_node_init(&bfm->bfm_node, FIB_NODE_TYPE_BIER_FMASK);
     179          77 :     *bfm->bfm_id = *fmid;
     180          77 :     dpo_reset(&bfm->bfm_dpo);
     181          77 :     btid = bier_table_get_id(bfm->bfm_id->bfmi_bti);
     182          77 :     bier_fmask_bits_init(&bfm->bfm_bits, btid->bti_hdr_len);
     183             : 
     184          77 :     if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
     185             :     {
     186           1 :         bfm->bfm_id->bfmi_nh_type = BIER_NH_UDP;
     187             :     }
     188          76 :     else if (ip46_address_is_zero(&(bfm->bfm_id->bfmi_nh)))
     189             :     {
     190           4 :         bfm->bfm_flags |= BIER_FMASK_FLAG_DISP;
     191             :     }
     192             : 
     193          77 :     if (!(bfm->bfm_flags & BIER_FMASK_FLAG_DISP))
     194             :     {
     195          73 :         if (NULL != rpath->frp_label_stack)
     196             :         {
     197          72 :             olabel = rpath->frp_label_stack[0].fml_value;
     198          72 :             vnet_mpls_uc_set_label(&bfm->bfm_label, olabel);
     199          72 :             vnet_mpls_uc_set_exp(&bfm->bfm_label, 0);
     200          72 :             vnet_mpls_uc_set_s(&bfm->bfm_label, 1);
     201          72 :             vnet_mpls_uc_set_ttl(&bfm->bfm_label, 64);
     202          72 :             bfm->bfm_flags |= BIER_FMASK_FLAG_MPLS;
     203             :         }
     204             :         else
     205             :         {
     206             :             bier_bift_id_t id;
     207             : 
     208             :             /*
     209             :              * not an MPLS label
     210             :              */
     211           1 :             bfm->bfm_flags &= ~BIER_FMASK_FLAG_MPLS;
     212             : 
     213             :             /*
     214             :              * use a label as encoded for BIFT value
     215             :              */
     216           1 :             id = bier_bift_id_encode(btid->bti_set,
     217             :                                      btid->bti_sub_domain,
     218           1 :                                      btid->bti_hdr_len);
     219           1 :             vnet_mpls_uc_set_label(&bfm->bfm_label, id);
     220           1 :             vnet_mpls_uc_set_s(&bfm->bfm_label, 1);
     221           1 :             vnet_mpls_uc_set_exp(&bfm->bfm_label, 0);
     222           1 :             vnet_mpls_uc_set_ttl(&bfm->bfm_label, 64);
     223             :         }
     224          73 :         bfm->bfm_label = clib_host_to_net_u32(bfm->bfm_label);
     225             :     }
     226             : 
     227          77 :     rpaths = NULL;
     228          77 :     vec_add1(rpaths, *rpath);
     229          77 :     bfm->bfm_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
     230             :                                         FIB_PATH_LIST_FLAG_NO_URPF),
     231             :                                        rpaths);
     232          77 :     bfm->bfm_sibling = fib_path_list_child_add(bfm->bfm_pl,
     233             :                                                FIB_NODE_TYPE_BIER_FMASK,
     234             :                                                bier_fmask_get_index(bfm));
     235          77 :     vec_free(rpaths);
     236          77 :     bier_fmask_stack(bfm);
     237          77 : }
     238             : 
     239             : static void
     240          77 : bier_fmask_destroy (bier_fmask_t *bfm)
     241             : {
     242          77 :     clib_mem_free(bfm->bfm_bits.bfmb_refs);
     243          77 :     clib_mem_free(bfm->bfm_bits.bfmb_input_reset_string.bbs_buckets);
     244             : 
     245          77 :     bier_fmask_db_remove(bfm->bfm_id);
     246          77 :     fib_path_list_child_remove(bfm->bfm_pl,
     247             :                                bfm->bfm_sibling);
     248          77 :     dpo_reset(&bfm->bfm_dpo);
     249          77 :     clib_mem_free(bfm->bfm_id);
     250          77 :     pool_put(bier_fmask_pool, bfm);
     251          77 : }
     252             : 
     253             : void
     254       35746 : bier_fmask_unlock (index_t bfmi)
     255             : {
     256             :     bier_fmask_t *bfm;
     257             : 
     258       35746 :     if (INDEX_INVALID == bfmi)
     259             :     {
     260       33232 :         return;
     261             :     }
     262             : 
     263        2514 :     bfm = bier_fmask_get(bfmi);
     264             : 
     265        2514 :     fib_node_unlock(&bfm->bfm_node);
     266             : }
     267             : 
     268             : void
     269        3842 : bier_fmask_lock (index_t bfmi)
     270             : {
     271             :     bier_fmask_t *bfm;
     272             : 
     273        3842 :     if (INDEX_INVALID == bfmi)
     274             :     {
     275        1328 :         return;
     276             :     }
     277             : 
     278        2514 :     bfm = bier_fmask_get(bfmi);
     279             : 
     280        2514 :     fib_node_lock(&bfm->bfm_node);
     281             : }
     282             : 
     283             : index_t
     284          77 : bier_fmask_create_and_lock (const bier_fmask_id_t *fmid,
     285             :                             const fib_route_path_t *rpath)
     286             : {
     287             :     bier_fmask_t *bfm;
     288             :     index_t bfmi;
     289             : 
     290          77 :     pool_get_aligned(bier_fmask_pool, bfm, CLIB_CACHE_LINE_BYTES);
     291          77 :     bfmi = bier_fmask_get_index(bfm);
     292             : 
     293          77 :     vlib_validate_combined_counter (&(bier_fmask_counters), bfmi);
     294          77 :     vlib_zero_combined_counter (&(bier_fmask_counters), bfmi);
     295             : 
     296          77 :     bier_fmask_init(bfm, fmid, rpath);
     297             : 
     298          77 :     bier_fmask_lock(bfmi);
     299             : 
     300          77 :     return (bfmi);
     301             : }
     302             : 
     303             : void
     304          90 : bier_fmask_link (index_t bfmi,
     305             :                  bier_bp_t bp)
     306             : {
     307             :     bier_fmask_t *bfm;
     308             : 
     309          90 :     bfm = bier_fmask_get(bfmi);
     310             : 
     311          90 :     if (0 == bfm->bfm_bits.bfmb_refs[BIER_BP_TO_INDEX(bp)])
     312             :     {
     313             :         /*
     314             :          * 0 -> 1 transition - set the bit in the string
     315             :          */
     316          80 :         bier_bit_string_set_bit(&bfm->bfm_bits.bfmb_input_reset_string, bp);
     317             :     }
     318             : 
     319          90 :     ++bfm->bfm_bits.bfmb_refs[BIER_BP_TO_INDEX(bp)];
     320          90 :     ++bfm->bfm_bits.bfmb_count;
     321          90 : }
     322             : 
     323             : void
     324          90 : bier_fmask_unlink (index_t bfmi,
     325             :                    bier_bp_t bp)
     326             : {
     327             :     bier_fmask_t *bfm;
     328             : 
     329          90 :     bfm = bier_fmask_get(bfmi);
     330             : 
     331          90 :     --bfm->bfm_bits.bfmb_refs[BIER_BP_TO_INDEX(bp)];
     332          90 :     --bfm->bfm_bits.bfmb_count;
     333             : 
     334          90 :     if (0 == bfm->bfm_bits.bfmb_refs[BIER_BP_TO_INDEX(bp)])
     335             :     {
     336             :         /*
     337             :          * 1 -> 0 transition - clear the bit in the string
     338             :          */
     339          80 :         bier_bit_string_clear_bit(&bfm->bfm_bits.bfmb_input_reset_string, bp);
     340             :     }
     341          90 : }
     342             : 
     343             : u8*
     344           0 : format_bier_fmask (u8 *s, va_list *ap)
     345             : {
     346           0 :     index_t bfmi = va_arg(*ap, index_t);
     347           0 :     u32 indent = va_arg(*ap, u32);
     348             :     bier_fmask_attributes_t attr;
     349             :     bier_fmask_t *bfm;
     350             :     vlib_counter_t to;
     351             : 
     352           0 :     if (pool_is_free_index(bier_fmask_pool, bfmi))
     353             :     {
     354           0 :         return (format(s, "No BIER f-mask %d", bfmi));
     355             :     }
     356             : 
     357           0 :     bfm = bier_fmask_get(bfmi);
     358             : 
     359           0 :     s = format(s, "fmask: nh:%U bs:%U locks:%d ",
     360           0 :                format_ip46_address, &bfm->bfm_id->bfmi_nh, IP46_TYPE_ANY,
     361             :                format_bier_bit_string, &bfm->bfm_bits.bfmb_input_reset_string,
     362             :                bfm->bfm_node.fn_locks);
     363           0 :     s = format(s, "flags:");
     364           0 :     FOR_EACH_BIER_FMASK_ATTR(attr) {
     365           0 :         if ((1<<attr) & bfm->bfm_flags) {
     366           0 :             s = format (s, "%s,", bier_fmask_attr_names[attr]);
     367             :         }
     368             :     }
     369           0 :     vlib_get_combined_counter (&(bier_fmask_counters), bfmi, &to);
     370           0 :     s = format (s, " to:[%Ld:%Ld]]", to.packets, to.bytes);
     371           0 :     s = format(s, "\n");
     372           0 :     s = fib_path_list_format(bfm->bfm_pl, s);
     373             : 
     374           0 :     if (bfm->bfm_flags & BIER_FMASK_FLAG_MPLS)
     375             :     {
     376           0 :         s = format(s, "  output-label:%U",
     377             :                    format_mpls_unicast_label,
     378             :                    vnet_mpls_uc_get_label(clib_net_to_host_u32(bfm->bfm_label)));
     379             :     }
     380             :     else
     381             :     {
     382           0 :         s = format(s, "  output-bfit:[%U]",
     383             :                    format_bier_bift_id,
     384             :                    vnet_mpls_uc_get_label(clib_net_to_host_u32(bfm->bfm_label)));
     385             :     }
     386           0 :     s = format(s, "\n %U%U",
     387             :                format_white_space, indent,
     388             :                format_dpo_id, &bfm->bfm_dpo, indent+2);
     389             : 
     390           0 :     return (s);
     391             : }
     392             : 
     393             : void
     394           0 : bier_fmask_get_stats (index_t bfmi, u64 * packets, u64 * bytes)
     395             : {
     396             :   vlib_counter_t to;
     397             : 
     398           0 :   vlib_get_combined_counter (&(bier_fmask_counters), bfmi, &to);
     399             : 
     400           0 :   *packets = to.packets;
     401           0 :   *bytes = to.bytes;
     402           0 : }
     403             : 
     404             : void
     405           0 : bier_fmask_encode (index_t bfmi,
     406             :                    bier_table_id_t *btid,
     407             :                    fib_route_path_t *rpath)
     408             : {
     409             :     bier_fmask_t *bfm;
     410             : 
     411           0 :     bfm = bier_fmask_get(bfmi);
     412           0 :     *btid = *bier_table_get_id(bfm->bfm_id->bfmi_bti);
     413             : 
     414           0 :     clib_memset(rpath, 0, sizeof(*rpath));
     415             : 
     416           0 :     rpath->frp_sw_if_index = ~0;
     417             : 
     418           0 :     switch (bfm->bfm_id->bfmi_nh_type)
     419             :     {
     420           0 :     case BIER_NH_UDP:
     421           0 :         rpath->frp_flags = FIB_ROUTE_PATH_UDP_ENCAP;
     422           0 :         rpath->frp_udp_encap_id = bfm->bfm_id->bfmi_id;
     423           0 :         break;
     424           0 :     case BIER_NH_IP:
     425           0 :         memcpy(&rpath->frp_addr, &bfm->bfm_id->bfmi_nh,
     426             :                sizeof(rpath->frp_addr));
     427           0 :         break;
     428             :     }
     429           0 : }
     430             : 
     431             : static fib_node_t *
     432         482 : bier_fmask_get_node (fib_node_index_t index)
     433             : {
     434         482 :     bier_fmask_t *bfm = bier_fmask_get(index);
     435         482 :     return (&(bfm->bfm_node));
     436             : }
     437             : 
     438             : static bier_fmask_t*
     439         154 : bier_fmask_get_from_node (fib_node_t *node)
     440             : {
     441         154 :     return ((bier_fmask_t*)(((char*)node) -
     442             :                             STRUCT_OFFSET_OF(bier_fmask_t,
     443             :                                              bfm_node)));
     444             : }
     445             : 
     446             : /*
     447             :  * bier_fmask_last_lock_gone
     448             :  */
     449             : static void
     450          77 : bier_fmask_last_lock_gone (fib_node_t *node)
     451             : {
     452          77 :     bier_fmask_destroy(bier_fmask_get_from_node(node));
     453          77 : }
     454             : 
     455             : /*
     456             :  * bier_fmask_back_walk_notify
     457             :  *
     458             :  * A back walk has reached this BIER fmask
     459             :  */
     460             : static fib_node_back_walk_rc_t
     461          77 : bier_fmask_back_walk_notify (fib_node_t *node,
     462             :                              fib_node_back_walk_ctx_t *ctx)
     463             : {
     464             :     /*
     465             :      * re-stack the fmask on the n-eos of the via
     466             :      */
     467          77 :     bier_fmask_t *bfm = bier_fmask_get_from_node(node);
     468             : 
     469          77 :     bier_fmask_stack(bfm);
     470             : 
     471             :     /*
     472             :      * propagate further up the graph.
     473             :      * we can do this synchronously since the fan out is small.
     474             :      */
     475          77 :     fib_walk_sync(FIB_NODE_TYPE_BIER_FMASK, bier_fmask_get_index(bfm), ctx);
     476             : 
     477          77 :     return (FIB_NODE_BACK_WALK_CONTINUE);
     478             : }
     479             : 
     480             : /*
     481             :  * The BIER fmask's graph node virtual function table
     482             :  */
     483             : static const fib_node_vft_t bier_fmask_vft = {
     484             :     .fnv_get = bier_fmask_get_node,
     485             :     .fnv_last_lock = bier_fmask_last_lock_gone,
     486             :     .fnv_back_walk = bier_fmask_back_walk_notify,
     487             : };
     488             : 
     489             : static void
     490       10668 : bier_fmask_dpo_lock (dpo_id_t *dpo)
     491             : {
     492       10668 : }
     493             : 
     494             : static void
     495       10668 : bier_fmask_dpo_unlock (dpo_id_t *dpo)
     496             : {
     497       10668 : }
     498             : 
     499             : static void
     500           0 : bier_fmask_dpo_mem_show (void)
     501             : {
     502           0 :     fib_show_memory_usage("BIER-fmask",
     503           0 :                           pool_elts(bier_fmask_pool),
     504           0 :                           pool_len(bier_fmask_pool),
     505             :                           sizeof(bier_fmask_t));
     506           0 : }
     507             : 
     508             : const static dpo_vft_t bier_fmask_dpo_vft = {
     509             :     .dv_lock = bier_fmask_dpo_lock,
     510             :     .dv_unlock = bier_fmask_dpo_unlock,
     511             :     .dv_mem_show = bier_fmask_dpo_mem_show,
     512             :     .dv_format = format_bier_fmask,
     513             : };
     514             : 
     515             : const static char *const bier_fmask_mpls_nodes[] =
     516             : {
     517             :     "bier-output",
     518             :     NULL
     519             : };
     520             : const static char * const * const bier_fmask_nodes[DPO_PROTO_NUM] =
     521             : {
     522             :     [DPO_PROTO_BIER] = bier_fmask_mpls_nodes,
     523             :     [DPO_PROTO_MPLS] = bier_fmask_mpls_nodes,
     524             : };
     525             : 
     526             : clib_error_t *
     527         559 : bier_fmask_module_init (vlib_main_t * vm)
     528             : {
     529         559 :     fib_node_register_type (FIB_NODE_TYPE_BIER_FMASK, &bier_fmask_vft);
     530         559 :     dpo_register(DPO_BIER_FMASK, &bier_fmask_dpo_vft, bier_fmask_nodes);
     531             : 
     532         559 :     return (NULL);
     533             : }
     534             : 
     535       88479 : VLIB_INIT_FUNCTION (bier_fmask_module_init);
     536             : 
     537             : static clib_error_t *
     538           0 : bier_fmask_show (vlib_main_t * vm,
     539             :                  unformat_input_t * input,
     540             :                  vlib_cli_command_t * cmd)
     541             : {
     542             :     bier_fmask_t *bfm;
     543             :     index_t bfmi;
     544             : 
     545           0 :     bfmi = INDEX_INVALID;
     546             : 
     547           0 :     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
     548           0 :         if (unformat (input, "%d", &bfmi))
     549             :         {
     550             :             ;
     551             :         } else
     552             :         {
     553           0 :             break;
     554             :         }
     555             :     }
     556             : 
     557           0 :     if (INDEX_INVALID == bfmi)
     558             :     {
     559           0 :         pool_foreach (bfm, bier_fmask_pool)
     560             :          {
     561           0 :             vlib_cli_output (vm, "[@%d] %U",
     562             :                              bier_fmask_get_index(bfm),
     563             :                              format_bier_fmask, bier_fmask_get_index(bfm), 0);
     564             :         }
     565             :     }
     566             :     else
     567             :     {
     568           0 :         vlib_cli_output (vm, "%U", format_bier_fmask, bfmi, 0);
     569             :     }
     570             : 
     571           0 :     return (NULL);
     572             : }
     573             : 
     574      272887 : VLIB_CLI_COMMAND (show_bier_fmask, static) = {
     575             :     .path = "show bier fmask",
     576             :     .short_help = "show bier fmask",
     577             :     .function = bier_fmask_show,
     578             : };

Generated by: LCOV version 1.14