LCOV - code coverage report
Current view: top level - vnet/mfib - mfib_itf.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 73 86 84.9 %
Date: 2023-10-26 01:39:38 Functions: 14 15 93.3 %

          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/vnet.h>
      17             : 
      18             : #include <vnet/mfib/mfib_itf.h>
      19             : #include <vnet/mfib/mfib_signal.h>
      20             : #include <vnet/fib/fib_path.h>
      21             : #include <vnet/ethernet/mac_address.h>
      22             : 
      23             : mfib_itf_t *mfib_itf_pool;
      24             : 
      25             : index_t
      26       17367 : mfib_itf_create (fib_node_index_t path_index,
      27             :                  mfib_itf_flags_t mfi_flags)
      28             : {
      29             :     mfib_itf_t *mfib_itf;
      30             : 
      31       17367 :     pool_get_aligned(mfib_itf_pool, mfib_itf,
      32             :                      CLIB_CACHE_LINE_BYTES);
      33             : 
      34       17367 :     mfib_itf->mfi_sw_if_index = fib_path_get_resolving_interface(path_index);
      35       17367 :     mfib_itf->mfi_si = INDEX_INVALID;
      36             : 
      37             :     /*
      38             :      * add the path index to the per-path hash
      39             :      */
      40       17367 :     mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash, path_index, mfi_flags);
      41             : 
      42             :     /*
      43             :      * the combined flags from all the paths is from just the one contributor
      44             :      */
      45       17367 :     mfib_itf->mfi_flags = mfi_flags;
      46             : 
      47       17367 :     return (mfib_itf - mfib_itf_pool);
      48             : }
      49             : 
      50             : static mfib_itf_flags_t
      51       12384 : mfib_itf_mk_flags (const mfib_itf_t *mfib_itf)
      52             : {
      53             :     mfib_itf_flags_t combined_flags, flags;
      54             :     fib_node_index_t *path_index;
      55             : 
      56       12384 :     combined_flags = MFIB_ITF_FLAG_NONE;
      57             : 
      58      804972 :     hash_foreach(path_index, flags, mfib_itf->mfi_hash,
      59             :     {
      60             :         combined_flags |= flags;
      61             :     });
      62             : 
      63       12384 :     return (combined_flags);
      64             : }
      65             : 
      66             : int
      67       12384 : mfib_itf_update (mfib_itf_t *mfib_itf,
      68             :                  fib_node_index_t path_index,
      69             :                  mfib_itf_flags_t mfi_flags)
      70             : {
      71             :     /*
      72             :      * add or remove the path index to the per-path hash
      73             :      */
      74       12384 :     if (MFIB_ITF_FLAG_NONE == mfi_flags)
      75             :     {
      76       12376 :         hash_unset(mfib_itf->mfi_hash, path_index);
      77             :     }
      78             :     else
      79             :     {
      80           8 :         mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash,
      81             :                                       path_index,
      82             :                                       mfi_flags);
      83             :     }
      84             : 
      85             :     /*
      86             :      * re-generate the combined flags from all the paths.
      87             :      */
      88       12384 :     mfib_itf->mfi_flags = mfib_itf_mk_flags(mfib_itf);
      89             : 
      90             :     /*
      91             :      * The interface can be removed if there are no more flags
      92             :      */
      93       12384 :     return (MFIB_ITF_FLAG_NONE == mfib_itf->mfi_flags);
      94             : }
      95             : 
      96             : static void
      97       16192 : mfib_itf_hash_flush (mfib_itf_t *mfi)
      98             : {
      99       16192 :     fib_node_index_t path_index, *path_indexp, *all = NULL;
     100             :     mfib_itf_flags_t flags;
     101             : 
     102     1056300 :     hash_foreach(path_index, flags, mfi->mfi_hash,
     103             :     {
     104             :         vec_add1(all, path_index);
     105             :     });
     106             : 
     107       20010 :     vec_foreach(path_indexp, all)
     108             :     {
     109        3818 :         hash_unset(mfi->mfi_hash, *path_indexp);
     110             :     };
     111       16192 : }
     112             : 
     113             : static void
     114       12045 : mfib_itf_prefix4_to_mac (const mfib_prefix_t *pfx,
     115             :                          mac_address_t *mac)
     116             : {
     117       12045 :     mac->bytes[0] = 0x01;
     118       12045 :     mac->bytes[1] = 0x0;
     119       12045 :     mac->bytes[2] = 0x5e;
     120       12045 :     mac->bytes[3] = pfx->fp_grp_addr.ip4.as_u8[1] & 0x7f;
     121       12045 :     mac->bytes[4] = pfx->fp_grp_addr.ip4.as_u8[2];
     122       12045 :     mac->bytes[5] = pfx->fp_grp_addr.ip4.as_u8[3];
     123       12045 : }
     124             : 
     125             : static void
     126       16434 : mfib_itf_prefix6_to_mac (const mfib_prefix_t *pfx,
     127             :                          mac_address_t *mac)
     128             : {
     129       16434 :     mac->bytes[0] = 0x33;
     130       16434 :     mac->bytes[1] = 0x33;
     131       16434 :     mac->bytes[2] = pfx->fp_grp_addr.ip6.as_u8[12];
     132       16434 :     mac->bytes[3] = pfx->fp_grp_addr.ip6.as_u8[13];
     133       16434 :     mac->bytes[4] = pfx->fp_grp_addr.ip6.as_u8[14];
     134       16434 :     mac->bytes[5] = pfx->fp_grp_addr.ip6.as_u8[15];
     135       16434 : }
     136             : 
     137             : static void
     138       28479 : mfib_itf_prefix_to_mac (const mfib_prefix_t *pfx,
     139             :                         mac_address_t *mac)
     140             : {
     141       28479 :     switch (pfx->fp_proto)
     142             :     {
     143       12045 :     case FIB_PROTOCOL_IP4:
     144       12045 :         mfib_itf_prefix4_to_mac(pfx, mac);
     145       12045 :         break;
     146       16434 :     case FIB_PROTOCOL_IP6:
     147       16434 :         mfib_itf_prefix6_to_mac(pfx, mac);
     148       16434 :         break;
     149           0 :     case FIB_PROTOCOL_MPLS:
     150           0 :         break;
     151             :     }
     152       28479 : }
     153             : 
     154             : static void
     155       28479 : mfib_itf_mac_add_del (mfib_itf_t *itf,
     156             :                       const mfib_prefix_t *pfx,
     157             :                       int add)
     158             : {
     159             :     vnet_sw_interface_t *si;
     160             :     vnet_main_t *vnm;
     161             :     mac_address_t mac;
     162             : 
     163       28479 :     vnm = vnet_get_main();
     164       28479 :     mfib_itf_prefix_to_mac(pfx, &mac);
     165             : 
     166       28479 :     si = vnet_get_sw_interface(vnm, itf->mfi_sw_if_index);
     167       28479 :     vnet_hw_interface_add_del_mac_address (vnet_get_main(),
     168             :                                            si->hw_if_index,
     169             :                                            mac.bytes, add);
     170       28479 : }
     171             : 
     172             : void
     173       16152 : mfib_itf_mac_add (mfib_itf_t *itf,
     174             :                   const mfib_prefix_t *pfx)
     175             : {
     176       16152 :     mfib_itf_mac_add_del(itf, pfx, 1);
     177       16152 : }
     178             : 
     179             : void
     180       12327 : mfib_itf_mac_del (mfib_itf_t *itf,
     181             :                   const mfib_prefix_t *pfx)
     182             : {
     183       12327 :     mfib_itf_mac_add_del(itf, pfx, 0);
     184       12327 : }
     185             : 
     186             : void
     187       16192 : mfib_itf_delete (mfib_itf_t *mfi)
     188             : {
     189       16192 :     mfib_itf_hash_flush(mfi);
     190       16192 :     mfib_signal_remove_itf(mfi);
     191       16192 :     pool_put(mfib_itf_pool, mfi);
     192       16192 : }
     193             : 
     194             : u8 *
     195           6 : format_mfib_itf (u8 * s, va_list * args)
     196             : {
     197             :     mfib_itf_t *mfib_itf;
     198             :     vnet_main_t *vnm;
     199             :     index_t mfi;
     200             : 
     201           6 :     mfi = va_arg (*args, index_t);
     202             : 
     203           6 :     vnm = vnet_get_main();
     204           6 :     mfib_itf = mfib_itf_get(mfi);
     205             : 
     206           6 :     if (~0 != mfib_itf->mfi_sw_if_index)
     207             :     {
     208           6 :         return (format(s, " %U: %U",
     209             :                        format_vnet_sw_interface_name,
     210             :                        vnm,
     211             :                        vnet_get_sw_interface(vnm,
     212             :                                              mfib_itf->mfi_sw_if_index),
     213           6 :                        format_mfib_itf_flags, mfib_itf->mfi_flags));
     214             :     }
     215             :     else
     216             :     {
     217           0 :         return (format(s, " local: %U",
     218           0 :                        format_mfib_itf_flags, mfib_itf->mfi_flags));
     219             :     }
     220             :     return (s);
     221             : }
     222             : 
     223             : static clib_error_t *
     224           0 : show_mfib_itf_command (vlib_main_t * vm,
     225             :                         unformat_input_t * input,
     226             :                         vlib_cli_command_t * cmd)
     227             : {
     228             :     index_t mfii;
     229             : 
     230           0 :     if (unformat (input, "%d", &mfii))
     231             :     {
     232             :         /*
     233             :          * show one in detail
     234             :          */
     235           0 :         if (!pool_is_free_index(mfib_itf_pool, mfii))
     236             :         {
     237           0 :             vlib_cli_output (vm, "%d@%U",
     238             :                              mfii,
     239             :                              format_mfib_itf, mfii);
     240             :         }
     241             :         else
     242             :         {
     243           0 :             vlib_cli_output (vm, "itf %d invalid", mfii);
     244             :         }
     245             :     }
     246             :     else
     247             :     {
     248             :         /*
     249             :          * show all
     250             :          */
     251           0 :         vlib_cli_output (vm, "mFIB interfaces::");
     252           0 :         pool_foreach_index (mfii, mfib_itf_pool)
     253             :          {
     254           0 :             vlib_cli_output (vm, "%d@%U",
     255             :                              mfii,
     256             :                              format_mfib_itf, mfii);
     257             :         }
     258             :     }
     259             : 
     260           0 :     return (NULL);
     261             : }
     262             : 
     263             : /*?
     264             :  * This command displays an MFIB interface, or all interfaces, indexed by their
     265             :  * unique numerical identifier.
     266             :  ?*/
     267      285289 : VLIB_CLI_COMMAND (show_mfib_itf, static) = {
     268             :   .path = "show mfib interface",
     269             :   .function = show_mfib_itf_command,
     270             :   .short_help = "show mfib interface",
     271             : };

Generated by: LCOV version 1.14