LCOV - code coverage report
Current view: top level - vnet/mfib - mfib_table.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 276 316 87.3 %
Date: 2023-07-05 22:20:52 Functions: 44 44 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 <vlib/vlib.h>
      17             : #include <vnet/dpo/drop_dpo.h>
      18             : 
      19             : #include <vnet/mfib/mfib_table.h>
      20             : #include <vnet/mfib/ip4_mfib.h>
      21             : #include <vnet/mfib/ip6_mfib.h>
      22             : #include <vnet/mfib/mfib_entry.h>
      23             : #include <vnet/mfib/mfib_entry_src.h>
      24             : #include <vnet/mfib/mfib_entry_cover.h>
      25             : #include <vnet/mfib/mfib_signal.h>
      26             : 
      27             : const static char * mfib_table_flags_strings[] = MFIB_TABLE_ATTRIBUTES;
      28             : 
      29             : mfib_table_t *
      30       76099 : mfib_table_get (fib_node_index_t index,
      31             :                 fib_protocol_t proto)
      32             : {
      33       76099 :     switch (proto)
      34             :     {
      35       34263 :     case FIB_PROTOCOL_IP4:
      36       34263 :         return (pool_elt_at_index(ip4_main.mfibs, index));
      37       41836 :     case FIB_PROTOCOL_IP6:
      38       41836 :         return (pool_elt_at_index(ip6_main.mfibs, index));
      39           0 :     case FIB_PROTOCOL_MPLS:
      40           0 :         break;
      41             :     }
      42           0 :     ASSERT(0);
      43           0 :     return (NULL);
      44             : }
      45             : 
      46             : static inline fib_node_index_t
      47          10 : mfib_table_lookup_i (const mfib_table_t *mfib_table,
      48             :                      const mfib_prefix_t *prefix)
      49             : {
      50          10 :     switch (prefix->fp_proto)
      51             :     {
      52           5 :     case FIB_PROTOCOL_IP4:
      53           5 :         return (ip4_mfib_table_lookup(&mfib_table->v4,
      54             :                                       &prefix->fp_src_addr.ip4,
      55             :                                       &prefix->fp_grp_addr.ip4,
      56           5 :                                       prefix->fp_len));
      57           5 :     case FIB_PROTOCOL_IP6:
      58           5 :         return (ip6_mfib_table_lookup(&mfib_table->v6,
      59             :                                       &prefix->fp_src_addr.ip6,
      60             :                                       &prefix->fp_grp_addr.ip6,
      61           5 :                                       prefix->fp_len));
      62           0 :     case FIB_PROTOCOL_MPLS:
      63           0 :         break;
      64             :     }
      65           0 :     return (FIB_NODE_INDEX_INVALID);
      66             : }
      67             : 
      68             : fib_node_index_t
      69          10 : mfib_table_lookup (u32 fib_index,
      70             :                    const mfib_prefix_t *prefix)
      71             : {
      72          10 :     return (mfib_table_lookup_i(mfib_table_get(fib_index, prefix->fp_proto), prefix));
      73             : }
      74             : 
      75             : static inline fib_node_index_t
      76       62970 : mfib_table_lookup_exact_match_i (const mfib_table_t *mfib_table,
      77             :                                  const mfib_prefix_t *prefix)
      78             : {
      79       62970 :     switch (prefix->fp_proto)
      80             :     {
      81       26054 :     case FIB_PROTOCOL_IP4:
      82       26054 :         return (ip4_mfib_table_lookup_exact_match(&mfib_table->v4,
      83             :                                                   &prefix->fp_grp_addr.ip4,
      84             :                                                   &prefix->fp_src_addr.ip4,
      85       26054 :                                                   prefix->fp_len));
      86       36916 :     case FIB_PROTOCOL_IP6:
      87       36916 :         return (ip6_mfib_table_lookup_exact_match(&mfib_table->v6,
      88             :                                                   &prefix->fp_grp_addr.ip6,
      89             :                                                   &prefix->fp_src_addr.ip6,
      90       36916 :                                                   prefix->fp_len));
      91           0 :     case FIB_PROTOCOL_MPLS:
      92           0 :         break;
      93             :     }
      94           0 :     return (FIB_NODE_INDEX_INVALID);
      95             : }
      96             : 
      97             : fib_node_index_t
      98         417 : mfib_table_lookup_exact_match (u32 fib_index,
      99             :                               const mfib_prefix_t *prefix)
     100             : {
     101         417 :     return (mfib_table_lookup_exact_match_i(mfib_table_get(fib_index,
     102         417 :                                                           prefix->fp_proto),
     103             :                                             prefix));
     104             : }
     105             : 
     106             : static fib_node_index_t
     107        8581 : mfib_table_get_less_specific_i (const mfib_table_t *mfib_table,
     108             :                                 const mfib_prefix_t *prefix)
     109             : {
     110        8581 :     switch (prefix->fp_proto)
     111             :     {
     112        4949 :     case FIB_PROTOCOL_IP4:
     113        4949 :         return (ip4_mfib_table_get_less_specific(&mfib_table->v4,
     114             :                                                  &prefix->fp_src_addr.ip4,
     115             :                                                  &prefix->fp_grp_addr.ip4,
     116        4949 :                                                  prefix->fp_len));
     117        3632 :     case FIB_PROTOCOL_IP6:
     118        3632 :         return (ip6_mfib_table_get_less_specific(&mfib_table->v6,
     119             :                                                  &prefix->fp_src_addr.ip6,
     120             :                                                  &prefix->fp_grp_addr.ip6,
     121        3632 :                                                  prefix->fp_len));
     122           0 :     case FIB_PROTOCOL_MPLS:
     123           0 :         break;
     124             :     }
     125           0 :     return (FIB_NODE_INDEX_INVALID);
     126             : }
     127             : 
     128             : fib_node_index_t
     129           8 : mfib_table_get_less_specific (u32 fib_index,
     130             :                               const mfib_prefix_t *prefix)
     131             : {
     132           8 :     return (mfib_table_get_less_specific_i(mfib_table_get(fib_index,
     133           8 :                                                           prefix->fp_proto),
     134             :                                            prefix));
     135             : }
     136             : 
     137             : static void
     138        3987 : mfib_table_entry_remove (mfib_table_t *mfib_table,
     139             :                          const mfib_prefix_t *prefix,
     140             :                          fib_node_index_t mfib_entry_index)
     141             : {
     142        3987 :     vlib_smp_unsafe_warning();
     143             : 
     144        3987 :     mfib_table->mft_total_route_counts--;
     145             : 
     146        3987 :     switch (prefix->fp_proto)
     147             :     {
     148        3196 :     case FIB_PROTOCOL_IP4:
     149        3196 :         ip4_mfib_table_entry_remove(&mfib_table->v4,
     150             :                                     &prefix->fp_grp_addr.ip4,
     151             :                                     &prefix->fp_src_addr.ip4,
     152        3196 :                                     prefix->fp_len);
     153        3196 :         break;
     154         791 :     case FIB_PROTOCOL_IP6:
     155         791 :         ip6_mfib_table_entry_remove(&mfib_table->v6,
     156             :                                     &prefix->fp_grp_addr.ip6,
     157             :                                     &prefix->fp_src_addr.ip6,
     158         791 :                                     prefix->fp_len);
     159         791 :         break;
     160           0 :     case FIB_PROTOCOL_MPLS:
     161           0 :         ASSERT(0);
     162           0 :         break;
     163             :     }
     164             : 
     165        3987 :     mfib_entry_cover_change_notify(mfib_entry_index,
     166             :                                    FIB_NODE_INDEX_INVALID);
     167        3987 :     mfib_entry_unlock(mfib_entry_index);
     168        3987 : }
     169             : 
     170             : static void
     171        8573 : mfib_table_post_insert_actions (mfib_table_t *mfib_table,
     172             :                                 const mfib_prefix_t *prefix,
     173             :                                 fib_node_index_t mfib_entry_index)
     174             : {
     175             :     fib_node_index_t mfib_entry_cover_index;
     176             : 
     177             :     /*
     178             :      * find  the covering entry
     179             :      */
     180        8573 :     mfib_entry_cover_index = mfib_table_get_less_specific_i(mfib_table,
     181             :                                                             prefix);
     182             :     /*
     183             :      * the indicies are the same when the default route is first added
     184             :      */
     185        8573 :     if (mfib_entry_cover_index != mfib_entry_index)
     186             :     {
     187             :         /*
     188             :          * inform the covering entry that a new more specific
     189             :          * has been inserted beneath it.
     190             :          * If the prefix that has been inserted is a host route
     191             :          * then it is not possible that it will be the cover for any
     192             :          * other entry, so we can elide the walk.
     193             :          */
     194        7073 :         if (!mfib_entry_is_host(mfib_entry_index))
     195             :         {
     196        7059 :             mfib_entry_cover_change_notify(mfib_entry_cover_index,
     197             :                                            mfib_entry_index);
     198             :         }
     199             :     }
     200        8573 : }
     201             : 
     202             : 
     203             : static void
     204        8573 : mfib_table_entry_insert (mfib_table_t *mfib_table,
     205             :                          const mfib_prefix_t *prefix,
     206             :                          fib_node_index_t mfib_entry_index)
     207             : {
     208        8573 :     vlib_smp_unsafe_warning();
     209             : 
     210        8573 :     mfib_entry_lock(mfib_entry_index);
     211        8573 :     mfib_table->mft_total_route_counts++;
     212             : 
     213        8573 :     switch (prefix->fp_proto)
     214             :     {
     215        4945 :     case FIB_PROTOCOL_IP4:
     216        4945 :         ip4_mfib_table_entry_insert(&mfib_table->v4,
     217             :                                     &prefix->fp_grp_addr.ip4,
     218             :                                     &prefix->fp_src_addr.ip4,
     219        4945 :                                     prefix->fp_len,
     220             :                                     mfib_entry_index);
     221        4945 :         break;
     222        3628 :     case FIB_PROTOCOL_IP6:
     223        3628 :         ip6_mfib_table_entry_insert(&mfib_table->v6,
     224             :                                     &prefix->fp_grp_addr.ip6,
     225             :                                     &prefix->fp_src_addr.ip6,
     226        3628 :                                     prefix->fp_len,
     227             :                                     mfib_entry_index);
     228        3628 :         break;
     229           0 :     case FIB_PROTOCOL_MPLS:
     230           0 :         break;
     231             :     }
     232             : 
     233        8573 :     mfib_table_post_insert_actions(mfib_table, prefix, mfib_entry_index);
     234        8573 : }
     235             : 
     236             : fib_node_index_t
     237        1524 : mfib_table_entry_update (u32 fib_index,
     238             :                          const mfib_prefix_t *prefix,
     239             :                          mfib_source_t source,
     240             :                          fib_rpf_id_t rpf_id,
     241             :                          mfib_entry_flags_t entry_flags)
     242             : {
     243             :     fib_node_index_t mfib_entry_index;
     244             :     mfib_table_t *mfib_table;
     245             : 
     246        1524 :     mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
     247        1524 :     mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
     248             : 
     249        1524 :     if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
     250             :     {
     251        1500 :         if (MFIB_ENTRY_FLAG_NONE != entry_flags)
     252             :         {
     253             :             /*
     254             :              * update to a non-existing entry with non-zero flags
     255             :              */
     256        1500 :             mfib_entry_index = mfib_entry_create(fib_index, source,
     257             :                                                  prefix, rpf_id,
     258             :                                                  entry_flags,
     259             :                                                  INDEX_INVALID);
     260             : 
     261        1500 :             mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
     262             :         }
     263             :         /*
     264             :          * else
     265             :          *   the entry doesn't exist and the request is to set no flags
     266             :          *   the result would be an entry that doesn't exist - so do nothing
     267             :          */
     268             :     }
     269             :     else
     270             :     {
     271          24 :         mfib_entry_lock(mfib_entry_index);
     272             : 
     273          24 :         if (mfib_entry_update(mfib_entry_index,
     274             :                               source,
     275             :                               entry_flags,
     276             :                               rpf_id,
     277             :                               INDEX_INVALID))
     278             :         {
     279             :             /*
     280             :              * this update means we can now remove the entry.
     281             :              */
     282           2 :             mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
     283             :         }
     284             : 
     285          24 :         mfib_entry_unlock(mfib_entry_index);
     286             :     }
     287             : 
     288        1524 :     return (mfib_entry_index);
     289             : }
     290             : 
     291             : static fib_node_index_t
     292       22994 : mfib_table_entry_paths_update_i (u32 fib_index,
     293             :                                  const mfib_prefix_t *prefix,
     294             :                                  mfib_source_t source,
     295             :                                  mfib_entry_flags_t entry_flags,
     296             :                                  const fib_route_path_t *rpaths)
     297             : {
     298             :     fib_node_index_t mfib_entry_index;
     299             :     mfib_table_t *mfib_table;
     300             : 
     301       22994 :     mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
     302       22994 :     mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
     303             : 
     304       22994 :     if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
     305             :     {
     306        7067 :         mfib_entry_index = mfib_entry_create(fib_index,
     307             :                                              source,
     308             :                                              prefix,
     309             :                                              MFIB_RPF_ID_NONE,
     310             :                                              entry_flags,
     311             :                                              INDEX_INVALID);
     312             : 
     313        7067 :         mfib_entry_path_update(mfib_entry_index, source, rpaths);
     314             : 
     315        7067 :         mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
     316             :     }
     317             :     else
     318             :     {
     319       15927 :         mfib_entry_path_update(mfib_entry_index, source, rpaths);
     320             :     }
     321       22994 :     return (mfib_entry_index);
     322             : }
     323             : 
     324             : 
     325             : fib_node_index_t
     326       22096 : mfib_table_entry_path_update (u32 fib_index,
     327             :                               const mfib_prefix_t *prefix,
     328             :                               mfib_source_t source,
     329             :                               mfib_entry_flags_t entry_flags,
     330             :                               const fib_route_path_t *rpath)
     331             : {
     332             :     fib_node_index_t mfib_entry_index;
     333       22096 :     fib_route_path_t *rpaths = NULL;
     334             : 
     335       22096 :     vec_add1(rpaths, *rpath);
     336             : 
     337       22096 :     mfib_entry_index = mfib_table_entry_paths_update_i(fib_index, prefix,
     338             :                                                        source, entry_flags,
     339             :                                                        rpaths);
     340             : 
     341       22096 :     vec_free(rpaths);
     342       22096 :     return (mfib_entry_index);
     343             : }
     344             : 
     345             : fib_node_index_t
     346         898 : mfib_table_entry_paths_update (u32 fib_index,
     347             :                               const mfib_prefix_t *prefix,
     348             :                               mfib_source_t source,
     349             :                               mfib_entry_flags_t entry_flags,
     350             :                               const fib_route_path_t *rpaths)
     351             : {
     352         898 :     return (mfib_table_entry_paths_update_i(fib_index, prefix,
     353             :                                             source, entry_flags, rpaths));
     354             : }
     355             : 
     356             : static void
     357       38023 : mfib_table_entry_paths_remove_i (u32 fib_index,
     358             :                                  const mfib_prefix_t *prefix,
     359             :                                  mfib_source_t source,
     360             :                                  const fib_route_path_t *rpaths)
     361             : {
     362             :     fib_node_index_t mfib_entry_index;
     363             :     mfib_table_t *mfib_table;
     364             : 
     365       38023 :     mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
     366       38023 :     mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
     367             : 
     368       38023 :     if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
     369             :     {
     370             :         /*
     371             :          * removing an entry that does not exist. i'll allow it.
     372             :          */
     373             :     }
     374             :     else
     375             :     {
     376             :         int no_more_sources;
     377             : 
     378             :         /*
     379             :          * don't nobody go nowhere
     380             :          */
     381       38017 :         mfib_entry_lock(mfib_entry_index);
     382             : 
     383       38017 :         no_more_sources = mfib_entry_path_remove(mfib_entry_index,
     384             :                                                  source,
     385             :                                                  rpaths);
     386             : 
     387       38017 :         if (no_more_sources)
     388             :         {
     389             :             /*
     390             :              * last source gone. remove from the table
     391             :              */
     392         971 :             mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
     393             :         }
     394             : 
     395       38017 :         mfib_entry_unlock(mfib_entry_index);
     396             :     }
     397       38023 : }
     398             : void
     399          29 : mfib_table_entry_paths_remove (u32 fib_index,
     400             :                               const mfib_prefix_t *prefix,
     401             :                               mfib_source_t source,
     402             :                               const fib_route_path_t *rpaths)
     403             : {
     404          29 :     mfib_table_entry_paths_remove_i(fib_index,
     405             :                                     prefix,
     406             :                                     source,
     407             :                                     rpaths);
     408          29 : }
     409             : 
     410             : void
     411       37994 : mfib_table_entry_path_remove (u32 fib_index,
     412             :                               const mfib_prefix_t *prefix,
     413             :                               mfib_source_t source,
     414             :                               const fib_route_path_t *rpath)
     415             : {
     416       37994 :     fib_route_path_t *rpaths = NULL;
     417             : 
     418       37994 :     vec_add1(rpaths, *rpath);
     419             : 
     420       37994 :     mfib_table_entry_paths_remove_i(fib_index,
     421             :                                     prefix,
     422             :                                     source,
     423             :                                     rpaths);
     424             : 
     425       37994 :     vec_free(rpaths);
     426       37994 : }
     427             : 
     428             : fib_node_index_t
     429          12 : mfib_table_entry_special_add (u32 fib_index,
     430             :                               const mfib_prefix_t *prefix,
     431             :                               mfib_source_t source,
     432             :                               mfib_entry_flags_t entry_flags,
     433             :                               index_t repi)
     434             : {
     435             :     fib_node_index_t mfib_entry_index;
     436             :     mfib_table_t *mfib_table;
     437             : 
     438          12 :     mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
     439          12 :     mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix);
     440             : 
     441          12 :     if (INDEX_INVALID != repi)
     442             :     {
     443           2 :         entry_flags |= MFIB_ENTRY_FLAG_EXCLUSIVE;
     444             :     }
     445             : 
     446          12 :     if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
     447             :     {
     448           6 :         mfib_entry_index = mfib_entry_create(fib_index,
     449             :                                              source,
     450             :                                              prefix,
     451             :                                              MFIB_RPF_ID_NONE,
     452             :                                              entry_flags,
     453             :                                              repi);
     454             : 
     455           6 :         mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index);
     456             :     }
     457             :     else
     458             :     {
     459           6 :         mfib_entry_special_add(mfib_entry_index, source, entry_flags,
     460             :                                MFIB_RPF_ID_NONE, repi);
     461             :     }
     462             : 
     463          12 :     return (mfib_entry_index);
     464             : }
     465             : 
     466             : static void
     467        3027 : mfib_table_entry_delete_i (u32 fib_index,
     468             :                            fib_node_index_t mfib_entry_index,
     469             :                            const mfib_prefix_t *prefix,
     470             :                            mfib_source_t source)
     471             : {
     472             :     mfib_table_t *mfib_table;
     473             : 
     474        3027 :     mfib_table = mfib_table_get(fib_index, prefix->fp_proto);
     475             : 
     476             :     /*
     477             :      * don't nobody go nowhere
     478             :      */
     479        3027 :     mfib_entry_lock(mfib_entry_index);
     480             : 
     481        3027 :     if (mfib_entry_delete(mfib_entry_index, source))
     482             :     {
     483             :         /*
     484             :          * last source gone. remove from the table
     485             :          */
     486        3014 :         mfib_table_entry_remove(mfib_table, prefix, mfib_entry_index);
     487             :     }
     488             :     /*
     489             :      * else
     490             :      *   still has sources, leave it be.
     491             :      */
     492             : 
     493        3027 :     mfib_entry_unlock(mfib_entry_index);
     494        3027 : }
     495             : 
     496             : void
     497         268 : mfib_table_entry_delete (u32 fib_index,
     498             :                          const mfib_prefix_t *prefix,
     499             :                          mfib_source_t source)
     500             : {
     501             :     fib_node_index_t mfib_entry_index;
     502             : 
     503         268 :     mfib_entry_index = mfib_table_lookup_exact_match(fib_index, prefix);
     504             : 
     505         268 :     if (FIB_NODE_INDEX_INVALID == mfib_entry_index)
     506             :     {
     507             :         /*
     508             :          * removing an etry that does not exist.
     509             :          * i'll allow it, but i won't like it.
     510             :          */
     511           2 :         clib_warning("%U not in FIB", format_mfib_prefix, prefix);
     512             :     }
     513             :     else
     514             :     {
     515         266 :         mfib_table_entry_delete_i(fib_index, mfib_entry_index,
     516             :                                   prefix, source);
     517             :     }
     518         268 : }
     519             : 
     520             : void
     521        2761 : mfib_table_entry_delete_index (fib_node_index_t mfib_entry_index,
     522             :                                mfib_source_t source)
     523             : {
     524        2761 :     mfib_table_entry_delete_i(mfib_entry_get_fib_index(mfib_entry_index),
     525             :                               mfib_entry_index,
     526             :                               mfib_entry_get_prefix(mfib_entry_index),
     527             :                               source);
     528        2761 : }
     529             : 
     530             : u32
     531          63 : mfib_table_get_index_for_sw_if_index (fib_protocol_t proto,
     532             :                                       u32 sw_if_index)
     533             : {
     534          63 :     switch (proto)
     535             :     {
     536          55 :     case FIB_PROTOCOL_IP4:
     537          55 :         return (ip4_mfib_table_get_index_for_sw_if_index(sw_if_index));
     538           8 :     case FIB_PROTOCOL_IP6:
     539           8 :         return (ip6_mfib_table_get_index_for_sw_if_index(sw_if_index));
     540           0 :     case FIB_PROTOCOL_MPLS:
     541           0 :         ASSERT(0);
     542           0 :         break;
     543             :     }
     544           0 :     return (~0);
     545             : }
     546             : 
     547             : u32
     548        4053 : mfib_table_get_table_id (u32 fib_index,
     549             :                         fib_protocol_t proto)
     550             : {
     551             :     mfib_table_t *mfib_table;
     552             : 
     553        4053 :     mfib_table = mfib_table_get(fib_index, proto);
     554             : 
     555        4053 :     return ((NULL != mfib_table ? mfib_table->mft_table_id : ~0));
     556             : }
     557             : 
     558             : u32
     559        4098 : mfib_table_find (fib_protocol_t proto,
     560             :                  u32 table_id)
     561             : {
     562        4098 :     switch (proto)
     563             :     {
     564        2560 :     case FIB_PROTOCOL_IP4:
     565        2560 :         return (ip4_mfib_index_from_table_id(table_id));
     566        1538 :     case FIB_PROTOCOL_IP6:
     567        1538 :         return (ip6_mfib_index_from_table_id(table_id));
     568           0 :     case FIB_PROTOCOL_MPLS:
     569           0 :         ASSERT(0);
     570           0 :         break;
     571             :     }
     572           0 :     return (~0);
     573             : }
     574             : 
     575             : static u32
     576        1924 : mfib_table_find_or_create_and_lock_i (fib_protocol_t proto,
     577             :                                       u32 table_id,
     578             :                                       mfib_source_t src,
     579             :                                       const u8 *name)
     580             : {
     581             :     mfib_table_t *mfib_table;
     582             :     fib_node_index_t fi;
     583             : 
     584        1924 :     switch (proto)
     585             :     {
     586        1182 :     case FIB_PROTOCOL_IP4:
     587        1182 :         fi = ip4_mfib_table_find_or_create_and_lock(table_id, src);
     588        1182 :         break;
     589         742 :     case FIB_PROTOCOL_IP6:
     590         742 :         fi = ip6_mfib_table_find_or_create_and_lock(table_id, src);
     591         742 :         break;
     592           0 :     case FIB_PROTOCOL_MPLS:
     593             :     default:
     594           0 :         return (~0);
     595             :     }
     596             : 
     597        1924 :     mfib_table = mfib_table_get(fi, proto);
     598             : 
     599        1924 :     if (NULL == mfib_table->mft_desc)
     600             :     {
     601        1500 :         if (name && name[0])
     602             :         {
     603           0 :             mfib_table->mft_desc = format(NULL, "%s", name);
     604             :         }
     605             :         else
     606             :         {
     607        1500 :             mfib_table->mft_desc = format(NULL, "%U-VRF:%d",
     608             :                                           format_fib_protocol, proto,
     609             :                                           table_id);
     610             :         }
     611             :     }
     612             : 
     613        1924 :     return (fi);
     614             : }
     615             : 
     616             : u32
     617        1483 : mfib_table_find_or_create_and_lock (fib_protocol_t proto,
     618             :                                     u32 table_id,
     619             :                                     mfib_source_t src)
     620             : {
     621        1483 :     return (mfib_table_find_or_create_and_lock_i(proto, table_id,
     622             :                                                  src, NULL));
     623             : }
     624             : 
     625             : u32
     626         441 : mfib_table_find_or_create_and_lock_w_name (fib_protocol_t proto,
     627             :                                            u32 table_id,
     628             :                                            mfib_source_t src,
     629             :                                            const u8 *name)
     630             : {
     631         441 :     return (mfib_table_find_or_create_and_lock_i(proto, table_id,
     632             :                                                  src, name));
     633             : }
     634             : 
     635             : /**
     636             :  * @brief Table flush context. Store the indicies of matching FIB entries
     637             :  * that need to be removed.
     638             :  */
     639             : typedef struct mfib_table_flush_ctx_t_
     640             : {
     641             :     /**
     642             :      * The list of entries to flush
     643             :      */
     644             :     fib_node_index_t *mftf_entries;
     645             : 
     646             :     /**
     647             :      * The source we are flushing
     648             :      */
     649             :     mfib_source_t mftf_source;
     650             : } mfib_table_flush_ctx_t;
     651             : 
     652             : static walk_rc_t
     653        3185 : mfib_table_flush_cb (fib_node_index_t mfib_entry_index,
     654             :                      void *arg)
     655             : {
     656        3185 :     mfib_table_flush_ctx_t *ctx = arg;
     657             : 
     658        3185 :     if (mfib_entry_is_sourced(mfib_entry_index, ctx->mftf_source))
     659             :     {
     660         166 :         vec_add1(ctx->mftf_entries, mfib_entry_index);
     661             :     }
     662        3185 :     return (WALK_CONTINUE);
     663             : }
     664             : 
     665             : void
     666         805 : mfib_table_flush (u32 mfib_index,
     667             :                   fib_protocol_t proto,
     668             :                   mfib_source_t source)
     669             : {
     670             :     fib_node_index_t *mfib_entry_index;
     671         805 :     mfib_table_flush_ctx_t ctx = {
     672             :         .mftf_entries = NULL,
     673             :         .mftf_source = source,
     674             :     };
     675             : 
     676         805 :     mfib_table_walk(mfib_index, proto,
     677             :                     mfib_table_flush_cb,
     678             :                     &ctx);
     679             : 
     680         971 :     vec_foreach(mfib_entry_index, ctx.mftf_entries)
     681             :     {
     682         166 :         mfib_table_entry_delete_index(*mfib_entry_index, source);
     683             :     }
     684             : 
     685         805 :     vec_free(ctx.mftf_entries);
     686         805 : }
     687             : 
     688             : static walk_rc_t
     689         564 : mfib_table_mark_cb (fib_node_index_t fib_entry_index,
     690             :                    void *arg)
     691             : {
     692         564 :     mfib_table_flush_ctx_t *ctx = arg;
     693             : 
     694         564 :     if (mfib_entry_is_sourced(fib_entry_index, ctx->mftf_source))
     695             :     {
     696         468 :         mfib_entry_mark(fib_entry_index, ctx->mftf_source);
     697             :     }
     698         564 :     return (WALK_CONTINUE);
     699             : }
     700             : 
     701             : void
     702          24 : mfib_table_mark (u32 fib_index,
     703             :                  fib_protocol_t proto,
     704             :                  mfib_source_t source)
     705             : {
     706          24 :     mfib_table_flush_ctx_t ctx = {
     707             :         .mftf_source = source,
     708             :     };
     709             :     mfib_table_t *mfib_table;
     710             : 
     711          24 :     mfib_table = mfib_table_get(fib_index, proto);
     712             : 
     713          24 :     mfib_table->mft_epoch++;
     714          24 :     mfib_table->mft_flags |= MFIB_TABLE_FLAG_RESYNC;
     715             : 
     716          24 :     mfib_table_walk(fib_index, proto,
     717             :                    mfib_table_mark_cb,
     718             :                    &ctx);
     719          24 : }
     720             : 
     721             : static walk_rc_t
     722         564 : mfib_table_sweep_cb (fib_node_index_t fib_entry_index,
     723             :                     void *arg)
     724             : {
     725         564 :     mfib_table_flush_ctx_t *ctx = arg;
     726             : 
     727         564 :     if (mfib_entry_is_marked(fib_entry_index, ctx->mftf_source))
     728             :     {
     729         228 :         vec_add1(ctx->mftf_entries, fib_entry_index);
     730             :     }
     731         564 :     return (WALK_CONTINUE);
     732             : }
     733             : 
     734             : void
     735          24 : mfib_table_sweep (u32 fib_index,
     736             :                   fib_protocol_t proto,
     737             :                   mfib_source_t source)
     738             : {
     739          24 :     mfib_table_flush_ctx_t ctx = {
     740             :         .mftf_source = source,
     741             :     };
     742             :     fib_node_index_t *fib_entry_index;
     743             :     mfib_table_t *mfib_table;
     744             : 
     745          24 :     mfib_table = mfib_table_get(fib_index, proto);
     746             : 
     747          24 :     mfib_table->mft_flags &= ~MFIB_TABLE_FLAG_RESYNC;
     748             : 
     749          24 :     mfib_table_walk(fib_index, proto,
     750             :                     mfib_table_sweep_cb,
     751             :                     &ctx);
     752             : 
     753         252 :     vec_foreach(fib_entry_index, ctx.mftf_entries)
     754             :     {
     755         228 :         mfib_table_entry_delete_index(*fib_entry_index, source);
     756             :     }
     757             : 
     758          24 :     vec_free(ctx.mftf_entries);
     759          24 : }
     760             : 
     761             : static void
     762         351 : mfib_table_destroy (mfib_table_t *mfib_table)
     763             : {
     764         351 :     vec_free(mfib_table->mft_desc);
     765             : 
     766         351 :     switch (mfib_table->mft_proto)
     767             :     {
     768         236 :     case FIB_PROTOCOL_IP4:
     769         236 :         ip4_mfib_table_destroy(&mfib_table->v4);
     770         236 :         break;
     771         115 :     case FIB_PROTOCOL_IP6:
     772         115 :         ip6_mfib_table_destroy(&mfib_table->v6);
     773         115 :         break;
     774           0 :     case FIB_PROTOCOL_MPLS:
     775           0 :         ASSERT(0);
     776           0 :         break;
     777             :     }
     778         351 : }
     779             : 
     780             : void
     781         974 : mfib_table_unlock (u32 fib_index,
     782             :                    fib_protocol_t proto,
     783             :                    mfib_source_t source)
     784             : {
     785             :     mfib_table_t *mfib_table;
     786             : 
     787         974 :     mfib_table = mfib_table_get(fib_index, proto);
     788         974 :     mfib_table->mft_locks[source]--;
     789         974 :     mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]--;
     790             : 
     791         974 :     if (0 == mfib_table->mft_locks[source])
     792             :     {
     793             :         /*
     794             :          * The source no longer needs the table. flush any routes
     795             :          * from it just in case
     796             :          */
     797         771 :         mfib_table_flush(fib_index, proto, source);
     798             :     }
     799             : 
     800         974 :     if (0 == mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS])
     801             :     {
     802             :         /*
     803             :          * no more locak from any source - kill it
     804             :          */
     805         351 :         mfib_table_destroy(mfib_table);
     806             :     }
     807         974 : }
     808             : 
     809             : void
     810        2198 : mfib_table_lock (u32 fib_index,
     811             :                  fib_protocol_t proto,
     812             :                  mfib_source_t source)
     813             : {
     814             :     mfib_table_t *mfib_table;
     815             : 
     816        2198 :     mfib_table = mfib_table_get(fib_index, proto);
     817        2198 :     mfib_table->mft_locks[source]++;
     818        2198 :     mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]++;
     819        2198 : }
     820             : 
     821             : u32
     822           2 : mfib_table_get_n_routes (fib_node_index_t fib_index,
     823             :                          fib_protocol_t proto)
     824             : {
     825             :     mfib_table_t *mfib_table;
     826             : 
     827           2 :     mfib_table = mfib_table_get(fib_index, proto);
     828             : 
     829           2 :     return (mfib_table->mft_total_route_counts);
     830             : }
     831             : 
     832             : void
     833        1163 : mfib_table_walk (u32 fib_index,
     834             :                  fib_protocol_t proto,
     835             :                  mfib_table_walk_fn_t fn,
     836             :                  void *ctx)
     837             : {
     838        1163 :     switch (proto)
     839             :     {
     840         707 :     case FIB_PROTOCOL_IP4:
     841         707 :         ip4_mfib_table_walk(ip4_mfib_get(fib_index), fn, ctx);
     842         707 :         break;
     843         456 :     case FIB_PROTOCOL_IP6:
     844         456 :         ip6_mfib_table_walk(ip6_mfib_get(fib_index), fn, ctx);
     845         456 :         break;
     846           0 :     case FIB_PROTOCOL_MPLS:
     847           0 :         break;
     848             :     }
     849        1163 : }
     850             : 
     851             : u8*
     852           2 : format_mfib_table_flags (u8 *s, va_list *args)
     853             : {
     854           2 :     mfib_table_flags_t flags = va_arg(*args, int);
     855             :     mfib_table_attribute_t attr;
     856             : 
     857           2 :     if (!flags)
     858             :     {
     859           2 :         return format(s, "none");
     860             :     }
     861             : 
     862           0 :     FOR_EACH_MFIB_TABLE_ATTRIBUTE(attr) {
     863           0 :         if (1 << attr & flags) {
     864           0 :             s = format(s, "%s", mfib_table_flags_strings[attr]);
     865             :         }
     866             :     }
     867             : 
     868           0 :     return (s);
     869             : }
     870             : 
     871             : u8*
     872         867 : format_mfib_table_name (u8* s, va_list *ap)
     873             : {
     874         867 :     fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t);
     875         867 :     fib_protocol_t proto = va_arg(*ap, int); // int promotion
     876             :     mfib_table_t *mfib_table;
     877             : 
     878         867 :     mfib_table = mfib_table_get(fib_index, proto);
     879             : 
     880         867 :     s = format(s, "%v", mfib_table->mft_desc);
     881             : 
     882         867 :     return (s);
     883             : }
     884             : 
     885             : u8 *
     886           1 : format_mfib_table_memory (u8 *s, va_list *args)
     887             : {
     888           1 :     s = format(s, "%U", format_ip4_mfib_table_memory);
     889           1 :     s = format(s, "%U", format_ip6_mfib_table_memory);
     890             : 
     891           1 :     return (s);
     892             : }
     893             : 
     894             : static clib_error_t *
     895         559 : mfib_module_init (vlib_main_t * vm)
     896             : {
     897             :     clib_error_t * error;
     898             : 
     899         559 :     mfib_entry_src_module_init();
     900         559 :     mfib_entry_module_init();
     901         559 :     mfib_signal_module_init();
     902             : 
     903         559 :     if ((error = vlib_call_init_function (vm, fib_module_init)))
     904           0 :         return (error);
     905         559 :     if ((error = vlib_call_init_function (vm, rn_module_init)))
     906           0 :         return (error);
     907             : 
     908         559 :     return (error);
     909             : }
     910             : 
     911       14559 : VLIB_INIT_FUNCTION(mfib_module_init);

Generated by: LCOV version 1.14