LCOV - code coverage report
Current view: top level - vnet/mfib - ip4_mfib.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 159 187 85.0 %
Date: 2023-07-05 22:20:52 Functions: 17 17 100.0 %

          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/mfib/ip4_mfib.h>
      17             : 
      18             : #include <vnet/mfib/mfib_table.h>
      19             : #include <vnet/mfib/mfib_entry.h>
      20             : 
      21             : static const mfib_prefix_t all_zeros =
      22             : {
      23             :     .fp_proto = FIB_PROTOCOL_IP4,
      24             : };
      25             : static const mfib_prefix_t ip4_specials[] =
      26             : {
      27             :     /* ALL prefixes are in network order */
      28             :     {
      29             :         /* (*,224.0.0.1)/32 - all hosts */
      30             :         .fp_grp_addr = {
      31             :             .ip4.data_u32 = 0x010000e0,
      32             :         },
      33             :         .fp_len = 32,
      34             :         .fp_proto = FIB_PROTOCOL_IP4,
      35             :     },
      36             :     {
      37             :         /* (*,224.0.0.2)/32 - all routers */
      38             :         .fp_grp_addr = {
      39             :             .ip4.data_u32 = 0x020000e0,
      40             :         },
      41             :         .fp_len = 32,
      42             :         .fp_proto = FIB_PROTOCOL_IP4,
      43             :     },
      44             : };
      45             : static const fib_route_path_t ip4_special_path =
      46             :   {
      47             :    .frp_proto = DPO_PROTO_IP4,
      48             :    .frp_addr = {
      49             :                 .ip4.data_u32 = 0x0,
      50             :                 },
      51             :    .frp_sw_if_index = ~0,
      52             :    .frp_fib_index = ~0,
      53             :    .frp_weight = 1,
      54             :    .frp_flags = FIB_ROUTE_PATH_LOCAL,
      55             :    .frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
      56             :   };
      57             : 
      58             : static u32
      59         818 : ip4_create_mfib_with_table_id (u32 table_id,
      60             :                                mfib_source_t src)
      61             : {
      62             :     mfib_table_t *mfib_table;
      63             : 
      64         818 :     pool_get_aligned(ip4_main.mfibs, mfib_table, CLIB_CACHE_LINE_BYTES);
      65         818 :     clib_memset(mfib_table, 0, sizeof(*mfib_table));
      66             : 
      67         818 :     mfib_table->mft_proto = FIB_PROTOCOL_IP4;
      68         818 :     mfib_table->mft_index =
      69         818 :         mfib_table->v4.index =
      70         818 :             (mfib_table - ip4_main.mfibs);
      71             : 
      72         818 :     hash_set (ip4_main.mfib_index_by_table_id,
      73             :               table_id,
      74             :               mfib_table->mft_index);
      75             : 
      76         818 :     mfib_table->mft_table_id =
      77         818 :         mfib_table->v4.table_id =
      78             :             table_id;
      79             : 
      80         818 :     mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4, src);
      81             : 
      82             :     /*
      83             :      * add the default route into the new FIB
      84             :      */
      85         818 :     mfib_table_entry_update(mfib_table->mft_index,
      86             :                             &all_zeros,
      87             :                             MFIB_SOURCE_DEFAULT_ROUTE,
      88             :                             MFIB_RPF_ID_NONE,
      89             :                             MFIB_ENTRY_FLAG_DROP);
      90             : 
      91             :     int ii;
      92             : 
      93        2454 :     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
      94             :     {
      95        1636 :         mfib_table_entry_path_update(mfib_table->mft_index,
      96             :                                      &ip4_specials[ii],
      97             :                                      MFIB_SOURCE_SPECIAL,
      98             :                                      MFIB_ENTRY_FLAG_NONE,
      99             :                                      &ip4_special_path);
     100             :     }
     101             : 
     102         818 :     return (mfib_table->mft_index);
     103             : }
     104             : 
     105             : void
     106         236 : ip4_mfib_table_destroy (ip4_mfib_t *mfib)
     107             : {
     108         236 :     mfib_table_t *mfib_table = (mfib_table_t*)mfib;
     109             :     int ii;
     110             : 
     111             :     /*
     112             :      * remove all the specials we added when the table was created.
     113             :      */
     114         236 :     mfib_table_entry_delete(mfib_table->mft_index,
     115             :                             &all_zeros,
     116             :                             MFIB_SOURCE_DEFAULT_ROUTE);
     117             : 
     118         708 :     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
     119             :       {
     120         472 :         mfib_table_entry_path_remove(mfib_table->mft_index,
     121             :                                      &ip4_specials[ii],
     122             :                                      MFIB_SOURCE_SPECIAL,
     123             :                                      &ip4_special_path);
     124             :       }
     125             : 
     126             :     /*
     127             :      * validate no more routes.
     128             :      */
     129         236 :     ASSERT(0 == mfib_table->mft_total_route_counts);
     130         236 :     ASSERT(~0 != mfib_table->mft_table_id);
     131             : 
     132       15576 :     for (u32 i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     133       15340 :       hash_free (mfib->fib_entry_by_dst_address[i]);
     134         236 :     hash_unset (ip4_main.mfib_index_by_table_id, mfib_table->mft_table_id);
     135         236 :     pool_put(ip4_main.mfibs, mfib_table);
     136         236 : }
     137             : 
     138             : void
     139        8878 : ip4_mfib_interface_enable_disable (u32 sw_if_index, int is_enable)
     140             : {
     141        8878 :     const fib_route_path_t path = {
     142             :         .frp_proto = DPO_PROTO_IP4,
     143             :         .frp_addr = zero_addr,
     144             :         .frp_sw_if_index = sw_if_index,
     145             :         .frp_fib_index = ~0,
     146             :         .frp_weight = 1,
     147             :         .frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
     148             :     };
     149             :     u32 mfib_index;
     150             :     int ii;
     151             : 
     152        8878 :     mfib_index = ip4_mfib_table_get_index_for_sw_if_index(sw_if_index);
     153             : 
     154       26634 :     for (ii = 0; ii < ARRAY_LEN(ip4_specials); ii++)
     155             :     {
     156       17756 :         if (is_enable)
     157             :         {
     158        4952 :             mfib_table_entry_path_update(mfib_index,
     159             :                                          &ip4_specials[ii],
     160             :                                          MFIB_SOURCE_SPECIAL,
     161             :                                          MFIB_ENTRY_FLAG_NONE,
     162             :                                          &path);
     163             :         }
     164             :         else
     165             :         {
     166       12804 :             mfib_table_entry_path_remove(mfib_index,
     167             :                                          &ip4_specials[ii],
     168             :                                          MFIB_SOURCE_SPECIAL,
     169             :                                          &path);
     170             :         }
     171             :     }
     172        8878 : }
     173             : 
     174             : u32
     175        1182 : ip4_mfib_table_find_or_create_and_lock (u32 table_id,
     176             :                                         mfib_source_t src)
     177             : {
     178             :     u32 index;
     179             : 
     180        1182 :     index = ip4_mfib_index_from_table_id(table_id);
     181        1182 :     if (~0 == index)
     182         818 :         return ip4_create_mfib_with_table_id(table_id, src);
     183         364 :     mfib_table_lock(index, FIB_PROTOCOL_IP4, src);
     184             : 
     185         364 :     return (index);
     186             : }
     187             : 
     188             : u32
     189        8933 : ip4_mfib_table_get_index_for_sw_if_index (u32 sw_if_index)
     190             : {
     191        8933 :     if (sw_if_index >= vec_len(ip4_main.mfib_index_by_sw_if_index))
     192             :     {
     193             :         /*
     194             :          * This is the case for interfaces that are not yet mapped to
     195             :          * a IP table
     196             :          */
     197           0 :         return (~0);
     198             :     }
     199        8933 :     return (ip4_main.mfib_index_by_sw_if_index[sw_if_index]);
     200             : }
     201             : 
     202             : #define IPV4_MFIB_GRP_LEN(_len)\
     203             :     (_len > 32 ? 32 : _len)
     204             : 
     205             : #define IP4_MFIB_MK_KEY(_grp, _src, _len, _key)                         \
     206             : {                                                                       \
     207             :     _key  = ((u64)(_grp->data_u32 &                                     \
     208             :                    ip4_main.fib_masks[IPV4_MFIB_GRP_LEN(_len)])) << 32; \
     209             :     _key |= _src->data_u32;                                             \
     210             : }
     211             : #define IP4_MFIB_MK_GRP_KEY(_grp, _len, _key)                           \
     212             : {                                                                       \
     213             :     _key  = ((u64)(_grp->data_u32 &                                     \
     214             :                    ip4_main.fib_masks[IPV4_MFIB_GRP_LEN(_len)])) << 32; \
     215             : }
     216             : 
     217             : /*
     218             :  * ip4_fib_table_lookup_exact_match
     219             :  *
     220             :  * Exact match prefix lookup
     221             :  */
     222             : fib_node_index_t
     223       26054 : ip4_mfib_table_lookup_exact_match (const ip4_mfib_t *mfib,
     224             :                                    const ip4_address_t *grp,
     225             :                                    const ip4_address_t *src,
     226             :                                    u32 len)
     227             : {
     228             :     uword * hash, * result;
     229             :     u64 key;
     230             : 
     231       26054 :     hash = mfib->fib_entry_by_dst_address[len];
     232       26054 :     IP4_MFIB_MK_KEY(grp, src, len, key);
     233             : 
     234       26054 :     result = hash_get(hash, key);
     235             : 
     236       26054 :     if (NULL != result) {
     237       21095 :         return (result[0]);
     238             :     }
     239        4959 :     return (FIB_NODE_INDEX_INVALID);
     240             : }
     241             : 
     242             : /*
     243             :  * ip4_fib_table_lookup
     244             :  *
     245             :  * Longest prefix match
     246             :  */
     247             : fib_node_index_t
     248        7698 : ip4_mfib_table_lookup (const ip4_mfib_t *mfib,
     249             :                        const ip4_address_t *src,
     250             :                        const ip4_address_t *grp,
     251             :                        u32 len)
     252             : {
     253             :     uword * hash, * result;
     254             :     i32 mask_len;
     255             :     u64 key;
     256             : 
     257        7698 :     mask_len = len;
     258             : 
     259        7698 :     if (PREDICT_TRUE(64 == mask_len))
     260             :     {
     261        2745 :         hash = mfib->fib_entry_by_dst_address[mask_len];
     262        2745 :         IP4_MFIB_MK_KEY(grp, src, mask_len, key);
     263             : 
     264        2745 :         result = hash_get (hash, key);
     265             : 
     266        2745 :         if (NULL != result) {
     267         429 :             return (result[0]);
     268             :         }
     269             :     }
     270             : 
     271      140219 :     for (mask_len = (len == 64 ? 32 : len); mask_len >= 0; mask_len--)
     272             :     {
     273      140219 :         hash = mfib->fib_entry_by_dst_address[mask_len];
     274      140219 :         IP4_MFIB_MK_GRP_KEY(grp, mask_len, key);
     275             : 
     276      140219 :         result = hash_get (hash, key);
     277             : 
     278      140219 :         if (NULL != result) {
     279        7269 :             return (result[0]);
     280             :         }
     281             :     }
     282           0 :     return (FIB_NODE_INDEX_INVALID);
     283             : }
     284             : 
     285             : fib_node_index_t
     286        4949 : ip4_mfib_table_get_less_specific (const ip4_mfib_t *mfib,
     287             :                                   const ip4_address_t *src,
     288             :                                   const ip4_address_t *grp,
     289             :                                   u32 len)
     290             : {
     291             :     u32 mask_len;
     292             : 
     293             :     /*
     294             :      * in the absence of a tree structure for the table that allows for an O(1)
     295             :      * parent get, a cheeky way to find the cover is to LPM for the prefix with
     296             :      * mask-1.
     297             :      * there should always be a cover, though it may be the default route. the
     298             :      * default route's cover is the default route.
     299             :      */
     300        4949 :     if (len == 64)
     301             :     {
     302             :         /* go from (S,G) to (*,G*) */
     303           9 :         mask_len = 32;
     304             :     }
     305        4940 :     else if (len != 0)
     306             :     {
     307        4122 :         mask_len = len - 1;
     308             :     }
     309             :     else
     310             :     {
     311         818 :         mask_len = len;
     312             :     }
     313             : 
     314        4949 :     return (ip4_mfib_table_lookup(mfib, src, grp, mask_len));
     315             : }
     316             : 
     317             : void
     318        4945 : ip4_mfib_table_entry_insert (ip4_mfib_t *mfib,
     319             :                              const ip4_address_t *grp,
     320             :                              const ip4_address_t *src,
     321             :                              u32 len,
     322             :                              fib_node_index_t fib_entry_index)
     323             : {
     324             :     uword * hash, * result;
     325             :     u64 key;
     326             : 
     327        4945 :     IP4_MFIB_MK_KEY(grp, src, len, key);
     328        4945 :     hash = mfib->fib_entry_by_dst_address[len];
     329        4945 :     result = hash_get (hash, key);
     330             : 
     331        4945 :     if (NULL == result) {
     332             :         /*
     333             :          * adding a new entry
     334             :          */
     335        4945 :         if (NULL == hash) {
     336        1644 :             hash = hash_create (32 /* elts */, sizeof (uword));
     337        1644 :             hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
     338             :         }
     339        4945 :         hash = hash_set(hash, key, fib_entry_index);
     340        4945 :         mfib->fib_entry_by_dst_address[len] = hash;
     341             :     }
     342             :     else
     343             :     {
     344           0 :         ASSERT(0);
     345             :     }
     346        4945 : }
     347             : 
     348             : void
     349        3196 : ip4_mfib_table_entry_remove (ip4_mfib_t *mfib,
     350             :                              const ip4_address_t *grp,
     351             :                              const ip4_address_t *src,
     352             :                              u32 len)
     353             : {
     354             :     uword * hash, * result;
     355             :     u64 key;
     356             : 
     357        3196 :     IP4_MFIB_MK_KEY(grp, src, len, key);
     358        3196 :     hash = mfib->fib_entry_by_dst_address[len];
     359        3196 :     result = hash_get (hash, key);
     360             : 
     361        3196 :     if (NULL == result)
     362             :     {
     363             :         /*
     364             :          * removing a non-existent entry. i'll allow it.
     365             :          */
     366             :     }
     367             :     else
     368             :     {
     369        3196 :         hash_unset(hash, key);
     370             :     }
     371             : 
     372        3196 :     mfib->fib_entry_by_dst_address[len] = hash;
     373        3196 : }
     374             : 
     375             : void
     376         707 : ip4_mfib_table_walk (ip4_mfib_t *mfib,
     377             :                      mfib_table_walk_fn_t fn,
     378             :                      void *ctx)
     379             : {
     380             :     int i;
     381             : 
     382       46662 :     for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     383             :     {
     384       45955 :         uword * hash = mfib->fib_entry_by_dst_address[i];
     385             : 
     386       45955 :         if (NULL != hash)
     387             :         {
     388             :             hash_pair_t * p;
     389             : 
     390      142241 :             hash_foreach_pair (p, hash,
     391             :             ({
     392             :                 fn(p->value[0], ctx);
     393             :             }));
     394             :         }
     395             :     }
     396         707 : }
     397             : 
     398             : u8 *
     399           1 : format_ip4_mfib_table_memory (u8 * s, va_list * args)
     400             : {
     401             :     mfib_table_t *mfib_table;
     402             :     u64 total_memory;
     403             : 
     404           1 :     total_memory = 0;
     405             : 
     406           2 :     pool_foreach (mfib_table, ip4_main.mfibs)
     407             :      {
     408           1 :         ip4_mfib_t *mfib = &mfib_table->v4;
     409             :         uword mfib_size;
     410             :         int i;
     411             : 
     412           1 :         mfib_size = 0;
     413             : 
     414          66 :         for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     415             :         {
     416          65 :             uword * hash = mfib->fib_entry_by_dst_address[i];
     417             : 
     418          65 :             if (NULL != hash)
     419             :             {
     420           2 :                 mfib_size += hash_bytes(hash);
     421             :             }
     422             :         }
     423             : 
     424           1 :         total_memory += mfib_size;
     425             :     }
     426             : 
     427           1 :     s = format(s, "%=30s %=6d %=12ld\n",
     428             :                "IPv4 multicast",
     429           1 :                pool_elts(ip4_main.mfibs), total_memory);
     430             : 
     431           1 :     return (s);
     432             : }
     433             : 
     434             : static void
     435           1 : ip4_mfib_table_show_all (ip4_mfib_t *mfib,
     436             :                          vlib_main_t * vm)
     437             : {
     438             :     fib_node_index_t *mfib_entry_indicies;
     439             :     fib_node_index_t *mfib_entry_index;
     440             :     int i;
     441             : 
     442           1 :     mfib_entry_indicies = NULL;
     443             : 
     444          66 :     for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     445             :     {
     446          65 :         uword * hash = mfib->fib_entry_by_dst_address[i];
     447             : 
     448          65 :         if (NULL != hash)
     449             :         {
     450             :             hash_pair_t * p;
     451             : 
     452         197 :             hash_foreach_pair (p, hash,
     453             :             ({
     454             :                 vec_add1(mfib_entry_indicies, p->value[0]);
     455             :             }));
     456             :         }
     457             :     }
     458             : 
     459           1 :     vec_sort_with_function(mfib_entry_indicies, mfib_entry_cmp_for_sort);
     460             : 
     461           5 :     vec_foreach(mfib_entry_index, mfib_entry_indicies)
     462             :     {
     463           4 :         vlib_cli_output(vm, "%U",
     464             :                         format_mfib_entry,
     465             :                         *mfib_entry_index,
     466             :                         MFIB_ENTRY_FORMAT_BRIEF);
     467             :     }
     468             : 
     469           1 :     vec_free(mfib_entry_indicies);
     470           1 : }
     471             : 
     472             : static void
     473           1 : ip4_mfib_table_show_one (ip4_mfib_t *mfib,
     474             :                          vlib_main_t * vm,
     475             :                          ip4_address_t *src,
     476             :                          ip4_address_t *grp,
     477             :                          u32 mask_len)
     478             : {
     479           1 :     vlib_cli_output(vm, "%U",
     480             :                     format_mfib_entry,
     481             :                     ip4_mfib_table_lookup(mfib, src, grp, mask_len),
     482             :                     MFIB_ENTRY_FORMAT_DETAIL);
     483           1 : }
     484             : 
     485             : static clib_error_t *
     486           2 : ip4_show_mfib (vlib_main_t * vm,
     487             :                unformat_input_t * input,
     488             :                vlib_cli_command_t * cmd)
     489             : {
     490           2 :     ip4_main_t * im4 = &ip4_main;
     491             :     mfib_table_t *mfib_table;
     492             :     int verbose, matching, memory;
     493           2 :     ip4_address_t grp, src = {{0}};
     494           2 :     u32 mask = 32;
     495             :     u64 total_hash_memory;
     496           2 :     int i, table_id = -1, fib_index = ~0;
     497             : 
     498           2 :     verbose = 1;
     499           2 :     memory = matching = 0;
     500           2 :     total_hash_memory = 0;
     501             : 
     502           5 :     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     503             :     {
     504           3 :         if (unformat (input, "brief") || unformat (input, "summary")
     505           3 :             || unformat (input, "sum"))
     506           0 :             verbose = 0;
     507           3 :         else if (unformat (input, "mem") || unformat (input, "memory"))
     508           0 :             memory = 1;
     509           3 :         else if (unformat (input, "%U %U",
     510             :                            unformat_ip4_address, &src,
     511             :                            unformat_ip4_address, &grp))
     512             :         {
     513           0 :             matching = 1;
     514           0 :             mask = 64;
     515             :         }
     516           3 :         else if (unformat (input, "%U/%d", unformat_ip4_address, &grp, &mask))
     517             :         {
     518           0 :             clib_memset(&src, 0, sizeof(src));
     519           0 :             matching = 1;
     520             :         }
     521           3 :         else if (unformat (input, "%U", unformat_ip4_address, &grp))
     522             :         {
     523           1 :             clib_memset(&src, 0, sizeof(src));
     524           1 :             matching = 1;
     525           1 :             mask = 32;
     526             :         }
     527           2 :         else if (unformat (input, "table %d", &table_id))
     528             :             ;
     529           2 :         else if (unformat (input, "index %d", &fib_index))
     530             :             ;
     531             :         else
     532           0 :             break;
     533             :     }
     534             : 
     535          10 :     pool_foreach (mfib_table, im4->mfibs)
     536             :      {
     537           8 :         ip4_mfib_t *mfib = &mfib_table->v4;
     538             : 
     539           8 :         if (table_id >= 0 && table_id != (int)mfib->table_id)
     540           0 :             continue;
     541           8 :         if (fib_index != ~0 && fib_index != (int)mfib->index)
     542           6 :             continue;
     543             : 
     544           2 :         if (memory)
     545             :         {
     546             :             uword hash_size;
     547             : 
     548           0 :             hash_size = 0;
     549             : 
     550           0 :             for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     551             :             {
     552           0 :                 uword * hash = mfib->fib_entry_by_dst_address[i];
     553           0 :                 if (NULL != hash)
     554             :                 {
     555           0 :                     hash_size += hash_bytes(hash);
     556             :                 }
     557             :             }
     558           0 :             if (verbose)
     559           0 :                 vlib_cli_output (vm, "%U hash:%d",
     560             :                                  format_mfib_table_name, mfib->index,
     561             :                                  FIB_PROTOCOL_IP4,
     562             :                                  hash_size);
     563           0 :             total_hash_memory += hash_size;
     564           0 :             continue;
     565             :         }
     566             : 
     567           2 :         vlib_cli_output (vm, "%U, fib_index:%d flags:%U",
     568             :                          format_mfib_table_name, mfib->index, FIB_PROTOCOL_IP4,
     569             :                          mfib->index,
     570           2 :                          format_mfib_table_flags, mfib_table->mft_flags);
     571             : 
     572             :         /* Show summary? */
     573           2 :         if (! verbose)
     574             :         {
     575           0 :             vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
     576           0 :             for (i = 0; i < ARRAY_LEN (mfib->fib_entry_by_dst_address); i++)
     577             :             {
     578           0 :                 uword * hash = mfib->fib_entry_by_dst_address[i];
     579           0 :                 uword n_elts = hash_elts (hash);
     580           0 :                 if (n_elts > 0)
     581           0 :                     vlib_cli_output (vm, "%20d%16d", i, n_elts);
     582             :             }
     583           0 :             continue;
     584             :         }
     585             : 
     586           2 :         if (!matching)
     587             :         {
     588           1 :             ip4_mfib_table_show_all(mfib, vm);
     589             :         }
     590             :         else
     591             :         {
     592           1 :             ip4_mfib_table_show_one(mfib, vm, &src, &grp, mask);
     593             :         }
     594             :     }
     595           2 :     if (memory)
     596           0 :         vlib_cli_output (vm, "totals: hash:%ld", total_hash_memory);
     597             : 
     598           2 :     return 0;
     599             : }
     600             : 
     601             : /* clang-format off */
     602             : /*?
     603             :  * This command displays the IPv4 MulticasrFIB Tables (VRF Tables) and
     604             :  * the route entries for each table.
     605             :  *
     606             :  * @note This command will run for a long time when the FIB tables are
     607             :  * comprised of millions of entries. For those scenarios, consider displaying
     608             :  * a single table or summary mode.
     609             :  *
     610             :  * @cliexpar
     611             :  * Example of how to display all the IPv4 Multicast FIB tables:
     612             :  * @cliexstart{show ip fib}
     613             :  * ipv4-VRF:0, fib_index 0
     614             :  * (*, 0.0.0.0/0):  flags:D,
     615             :  *  Interfaces:
     616             :  *  multicast-ip4-chain
     617             :  *   [@1]: dpo-drop ip4
     618             :  * (*, 232.1.1.1/32):
     619             :  * Interfaces:
     620             :  *  test-eth1: Forward,
     621             :  *  test-eth2: Forward,
     622             :  *  test-eth0: Accept,
     623             :  * multicast-ip4-chain
     624             :  * [@2]: dpo-replicate: [index:1 buckets:2 to:[0:0]]
     625             :  *   [0] [@1]: ipv4-mcast: test-eth1: IP4: d0:d1:d2:d3:d4:01 -> 01:00:05:00:00:00
     626             :  *   [1] [@1]: ipv4-mcast: test-eth2: IP4: d0:d1:d2:d3:d4:02 -> 01:00:05:00:00:00
     627             :  *
     628             :  * @cliexend
     629             :  * Example of how to display a summary of all IPv4 FIB tables:
     630             :  * @cliexstart{show ip fib summary}
     631             :  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
     632             :  *     Prefix length         Count
     633             :  *                    0               1
     634             :  *                    8               2
     635             :  *                   32               4
     636             :  * ipv4-VRF:7, fib_index 1, flow hash: src dst sport dport proto
     637             :  *     Prefix length         Count
     638             :  *                    0               1
     639             :  *                    8               2
     640             :  *                   24               2
     641             :  *                   32               4
     642             :  * @cliexend
     643             :  ?*/
     644             : /* clang-format on */
     645      272887 : VLIB_CLI_COMMAND (ip4_show_mfib_command, static) = {
     646             :     .path = "show ip mfib",
     647             :     .short_help = "show ip mfib [summary] [table <table-id>] [index <fib-id>] [<grp-addr>[/<mask>]] [<grp-addr>] [<src-addr> <grp-addr>]",
     648             :     .function = ip4_show_mfib,
     649             : };

Generated by: LCOV version 1.14