LCOV - code coverage report
Current view: top level - vnet/fib - fib_entry_src_interface.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 89 92 96.7 %
Date: 2023-10-26 01:39:38 Functions: 13 14 92.9 %

          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 "fib_entry.h"
      17             : #include "fib_entry_src.h"
      18             : #include "fib_path_list.h"
      19             : #include "fib_internal.h"
      20             : #include "fib_table.h"
      21             : #include "fib_entry_cover.h"
      22             : #include "fib_attached_export.h"
      23             : 
      24             : /**
      25             :  * Source initialisation Function 
      26             :  */
      27             : static void
      28       14385 : fib_entry_src_interface_init (fib_entry_src_t *src)
      29             : {
      30       14385 :     src->u.interface.fesi_cover = FIB_NODE_INDEX_INVALID;
      31       14385 :     src->u.interface.fesi_sibling = FIB_NODE_INDEX_INVALID;
      32       14385 : }
      33             : 
      34             : static void
      35       14385 : fib_entry_src_interface_add (fib_entry_src_t *src,
      36             :                              const fib_entry_t *entry,
      37             :                              fib_entry_flag_t flags,
      38             :                              dpo_proto_t proto,
      39             :                              const dpo_id_t *dpo)
      40             : {
      41       14385 :     src->fes_pl = fib_path_list_create_special(
      42             :                       proto,
      43             :                       fib_entry_src_flags_2_path_list_flags(flags),
      44             :                       dpo);
      45       14385 : }
      46             : 
      47             : static void
      48       13114 : fib_entry_src_interface_remove (fib_entry_src_t *src)
      49             : {
      50       13114 :     src->fes_pl = FIB_NODE_INDEX_INVALID;
      51       13114 :     ASSERT(src->u.interface.fesi_sibling == ~0);
      52       13114 : }
      53             : 
      54             : static int
      55        7615 : fib_entry_src_interface_update_glean (fib_entry_t *cover,
      56             :                                       const fib_entry_t *local)
      57             : {
      58             :     fib_entry_src_t *src;
      59             :     adj_index_t ai;
      60             : 
      61        7615 :     src = fib_entry_src_find (cover, FIB_SOURCE_INTERFACE);
      62             : 
      63        7615 :     if (NULL == src)
      64             :     {
      65             :         /*
      66             :          * The cover is not an interface source, no work
      67             :          */
      68        1994 :         return 0;
      69             :     }
      70             : 
      71        5621 :     ai = fib_path_list_get_adj(src->fes_pl,
      72        5621 :                                fib_entry_get_default_chain_type(cover));
      73             : 
      74        5621 :     if (INDEX_INVALID != ai)
      75             :     {
      76             :         ip_adjacency_t *adj;
      77             : 
      78        5523 :         adj = adj_get(ai);
      79             : 
      80        5523 :         if (IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index)
      81             :         {
      82             :             /*
      83             :              * the connected prefix will link to a glean on a non-p2p
      84             :              * interface.
      85             :              * Ensure we are updating with a host in the connected's subnet
      86             :              */
      87        5250 :             if (fib_prefix_is_cover(&adj->sub_type.glean.rx_pfx,
      88             :                                     &local->fe_prefix))
      89             :             {
      90             :                 fib_entry_src_t *local_src;
      91             : 
      92        5250 :                 local_src = fib_entry_src_find (local, FIB_SOURCE_INTERFACE);
      93        5250 :                 if (local_src != NULL)
      94             :                   {
      95        4299 :                     adj->sub_type.glean.rx_pfx.fp_addr =
      96             :                       local->fe_prefix.fp_addr;
      97        4299 :                     local_src->fes_flags |= FIB_ENTRY_SRC_FLAG_PROVIDES_GLEAN;
      98        4299 :                     return (1);
      99             :                   }
     100             :             }
     101             :         }
     102             :     }
     103             : 
     104        1322 :     return (0);
     105             : }
     106             : 
     107             : static walk_rc_t
     108         979 : fib_entry_src_interface_update_glean_walk (fib_entry_t *cover,
     109             :                                            fib_node_index_t covered,
     110             :                                            void *ctx)
     111             : {
     112         979 :     if (fib_entry_src_interface_update_glean(cover, fib_entry_get(covered)))
     113          24 :         return (WALK_STOP);
     114             : 
     115         955 :     return (WALK_CONTINUE);
     116             : }
     117             : 
     118             : static void
     119        9438 : fib_entry_src_interface_path_swap (fib_entry_src_t *src,
     120             :                                    const fib_entry_t *entry,
     121             :                                    fib_path_list_flags_t pl_flags,
     122             :                                    const fib_route_path_t *paths)
     123             : {
     124        9438 :     src->fes_pl = fib_path_list_create(pl_flags, paths);
     125        9438 : }
     126             : 
     127             : typedef struct fesi_find_glean_ctx_t_ {
     128             :   fib_node_index_t glean_node_index;
     129             : } fesi_find_glean_ctx_t;
     130             : 
     131             : static walk_rc_t
     132         150 : fib_entry_src_interface_find_glean_walk (fib_entry_t *cover,
     133             :                                          fib_node_index_t covered,
     134             :                                          void *ctx)
     135             : {
     136         150 :   fesi_find_glean_ctx_t *find_glean_ctx = ctx;
     137             :   fib_entry_t *covered_entry;
     138             :   fib_entry_src_t *covered_src;
     139             : 
     140         150 :   covered_entry = fib_entry_get (covered);
     141         150 :   covered_src = fib_entry_src_find (covered_entry, FIB_SOURCE_INTERFACE);
     142         150 :   if ((covered_src != NULL) &&
     143          24 :       (covered_src->fes_flags & FIB_ENTRY_SRC_FLAG_PROVIDES_GLEAN))
     144             :     {
     145          24 :       find_glean_ctx->glean_node_index = covered;
     146          24 :       return WALK_STOP;
     147             :     }
     148             : 
     149         126 :   return WALK_CONTINUE;
     150             : }
     151             : 
     152             : static fib_entry_t *
     153        6660 : fib_entry_src_interface_find_glean (fib_entry_t *cover)
     154             : {
     155             :   fib_entry_src_t *src;
     156             : 
     157        6660 :   src = fib_entry_src_find (cover, FIB_SOURCE_INTERFACE);
     158        6660 :   if (src == NULL)
     159             :     /* the cover is not an interface source */
     160        1990 :     return NULL;
     161             : 
     162        4670 :   fesi_find_glean_ctx_t ctx = {
     163             :     .glean_node_index = ~0,
     164             :   };
     165             : 
     166        4670 :   fib_entry_cover_walk (cover, fib_entry_src_interface_find_glean_walk,
     167             :                         &ctx);
     168             : 
     169        4694 :   return (ctx.glean_node_index == ~0) ? NULL :
     170          24 :                                         fib_entry_get (ctx.glean_node_index);
     171             : }
     172             : 
     173             : /*
     174             :  * Source activate. 
     175             :  * Called when the source is teh new longer best source on the entry
     176             :  */
     177             : static int
     178       16365 : fib_entry_src_interface_activate (fib_entry_src_t *src,
     179             :                                   const fib_entry_t *fib_entry)
     180             : {
     181             :     fib_entry_t *cover;
     182             : 
     183       16365 :     if (FIB_ENTRY_FLAG_LOCAL & src->fes_entry_flags)
     184             :     {
     185             :         u8 update_glean;
     186             : 
     187             :         /*
     188             :          * Track the covering attached/connected cover. This is so that
     189             :          * during an attached export of the cover, this local prefix is
     190             :          * also exported
     191             :          */
     192        6660 :         src->u.interface.fesi_cover =
     193        6660 :             fib_table_get_less_specific(fib_entry->fe_fib_index,
     194             :                                         &fib_entry->fe_prefix);
     195             : 
     196        6660 :         ASSERT(FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover);
     197             : 
     198        6660 :         cover = fib_entry_get(src->u.interface.fesi_cover);
     199             : 
     200             :         /*
     201             :          * Before adding as a child of the cover, check whether an existing
     202             :          * child has already been used to populate the glean adjacency. If so,
     203             :          * we don't need to update the adjacency.
     204             :          */
     205        6660 :         update_glean = (fib_entry_src_interface_find_glean (cover) == NULL);
     206        6660 :         src->u.interface.fesi_sibling =
     207        6660 :             fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
     208             : 
     209        6660 :         if (update_glean)
     210        6636 :           fib_entry_src_interface_update_glean(cover, fib_entry);
     211             :     }
     212             : 
     213       16365 :     return (!0);
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :  * Source Deactivate. 
     219             :  * Called when the source is no longer best source on the entry
     220             :  */
     221             : static void
     222       15094 : fib_entry_src_interface_deactivate (fib_entry_src_t *src,
     223             :                                     const fib_entry_t *fib_entry)
     224             : {
     225             :     fib_entry_t *cover;
     226             : 
     227             :     /*
     228             :      * remove the dependency on the covering entry
     229             :      */
     230       15094 :     if (FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover)
     231             :     {
     232        6262 :         cover = fib_entry_get(src->u.interface.fesi_cover);
     233        6262 :         fib_entry_cover_untrack(cover, src->u.interface.fesi_sibling);
     234             : 
     235        6262 :         src->u.interface.fesi_cover = FIB_NODE_INDEX_INVALID;
     236        6262 :         src->u.interface.fesi_sibling = ~0;
     237             : 
     238             :         /* If this was the glean address, find a new one */
     239        6262 :         if (src->fes_flags & FIB_ENTRY_SRC_FLAG_PROVIDES_GLEAN)
     240             :           {
     241        3901 :             fib_entry_cover_walk(cover,
     242             :                                 fib_entry_src_interface_update_glean_walk,
     243             :                                 NULL);
     244        3901 :             src->fes_flags &= ~FIB_ENTRY_SRC_FLAG_PROVIDES_GLEAN;
     245             :           }
     246             :     }
     247       15094 : }
     248             : 
     249             : static fib_entry_src_cover_res_t
     250        1980 : fib_entry_src_interface_cover_change (fib_entry_src_t *src,
     251             :                                       const fib_entry_t *fib_entry)
     252             : {
     253        1980 :     fib_entry_src_cover_res_t res = {
     254             :         .install = !0,
     255             :         .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
     256             :     };
     257             : 
     258        1980 :     if (FIB_NODE_INDEX_INVALID == src->u.interface.fesi_cover)
     259             :     {
     260             :         /*
     261             :          * not tracking the cover. surprised we got poked?
     262             :          */
     263           0 :         return (res);
     264             :     }
     265             : 
     266             :     /*
     267             :      * this function is called when this entry's cover has a more specific
     268             :      * entry inserted benaeth it. That does not necessarily mean that this
     269             :      * entry is covered by the new prefix. check that
     270             :      */
     271        1980 :     if (src->u.interface.fesi_cover !=
     272        1980 :         fib_table_get_less_specific(fib_entry->fe_fib_index,
     273             :                                     &fib_entry->fe_prefix))
     274             :     {
     275        1980 :         fib_entry_src_interface_deactivate(src, fib_entry);
     276        1980 :         fib_entry_src_interface_activate(src, fib_entry);
     277             :     }
     278        1980 :     return (res);
     279             : }
     280             : 
     281             : static void
     282       16420 : fib_entry_src_interface_installed (fib_entry_src_t *src,
     283             :                                    const fib_entry_t *fib_entry)
     284             : {
     285             :     /*
     286             :      * The interface source now rules! poke our cover to get exported
     287             :      */
     288             :     fib_entry_t *cover;
     289             : 
     290       16420 :     if (FIB_NODE_INDEX_INVALID != src->u.interface.fesi_cover)
     291             :     {
     292        6662 :         cover = fib_entry_get(src->u.interface.fesi_cover);
     293             : 
     294        6662 :         fib_attached_export_covered_added(cover,
     295             :                                           fib_entry_get_index(fib_entry));
     296             :     }
     297       16420 : }
     298             : 
     299             : static u8*
     300           0 : fib_entry_src_interface_format (fib_entry_src_t *src,
     301             :                                 u8* s)
     302             : {
     303           0 :     return (format(s, " cover:%d", src->u.interface.fesi_cover));
     304             : }
     305             : 
     306             : const static fib_entry_src_vft_t interface_src_vft = {
     307             :     .fesv_init = fib_entry_src_interface_init,
     308             :     .fesv_add = fib_entry_src_interface_add,
     309             :     .fesv_remove = fib_entry_src_interface_remove,
     310             :     .fesv_path_swap = fib_entry_src_interface_path_swap,
     311             :     .fesv_activate = fib_entry_src_interface_activate,
     312             :     .fesv_deactivate = fib_entry_src_interface_deactivate,
     313             :     .fesv_format = fib_entry_src_interface_format,
     314             :     .fesv_installed = fib_entry_src_interface_installed,
     315             :     .fesv_cover_change = fib_entry_src_interface_cover_change,
     316             :     /*
     317             :      * not concerned about updates to the cover. the cover will
     318             :      * decide to export or not
     319             :      */
     320             : };
     321             : 
     322             : void
     323         575 : fib_entry_src_interface_register (void)
     324             : {
     325         575 :     fib_entry_src_behaviour_register(FIB_SOURCE_BH_INTERFACE,
     326             :                                      &interface_src_vft);
     327         575 : }

Generated by: LCOV version 1.14