LCOV - code coverage report
Current view: top level - vnet/fib - fib_entry_src_interpose.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 82 100 82.0 %
Date: 2023-10-26 01:39:38 Functions: 13 15 86.7 %

          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/ip/format.h>
      18             : #include <vnet/ip/lookup.h>
      19             : #include <vnet/adj/adj.h>
      20             : #include <vnet/dpo/drop_dpo.h>
      21             : 
      22             : #include "fib_entry_src.h"
      23             : #include "fib_entry_src_rr.h"
      24             : #include "fib_entry_cover.h"
      25             : #include "fib_entry.h"
      26             : #include "fib_table.h"
      27             : 
      28             : /*
      29             :  * Source initialisation Function
      30             :  */
      31             : static void
      32          42 : fib_entry_src_interpose_init (fib_entry_src_t *src)
      33             : {
      34          42 :     src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
      35          42 :     src->u.interpose.fesi_sibling = FIB_NODE_INDEX_INVALID;
      36          42 : }
      37             : 
      38             : /*
      39             :  * Source deinitialisation Function
      40             :  */
      41             : static void
      42          42 : fib_entry_src_interpose_deinit (fib_entry_src_t *src)
      43             : {
      44          42 :     ASSERT(src->u.interpose.fesi_cover == FIB_NODE_INDEX_INVALID);
      45             : 
      46          42 :     src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
      47          42 :     src->u.interpose.fesi_sibling = FIB_NODE_INDEX_INVALID;
      48             : 
      49          42 :     dpo_reset(&src->u.interpose.fesi_dpo);
      50          42 : }
      51             : 
      52             : static fib_entry_src_t *
      53         111 : fib_entry_src_rr_get_next_best (const fib_entry_src_t *src,
      54             :                                 const fib_entry_t *fib_entry)
      55             : {
      56         111 :     fib_entry_src_t *next_src, *best_src = NULL;
      57             :     fib_source_t source;
      58             : 
      59         225 :     FOR_EACH_SRC_ADDED(fib_entry, next_src, source,
      60             :     ({
      61             :         /*
      62             :          * skip to the next best source after this one
      63             :          */
      64             :         switch (fib_source_cmp(source, src->fes_src))
      65             :         {
      66             :         case FIB_SOURCE_CMP_BETTER:
      67             :         case FIB_SOURCE_CMP_EQUAL:
      68             :             continue;
      69             :         case FIB_SOURCE_CMP_WORSE:
      70             :             best_src = next_src;
      71             :             goto out;
      72             :         }
      73             :     }));
      74          16 :  out:
      75         111 :     return (best_src);
      76             : }
      77             : 
      78             : /*
      79             :  * Source activation. Called when the source is the new best source on the entry
      80             :  */
      81             : static int
      82          59 : fib_entry_src_interpose_activate (fib_entry_src_t *src,
      83             :                                   const fib_entry_t *fib_entry)
      84             : {
      85             :     fib_entry_src_t *best_src;
      86             :     fib_node_index_t old_pl;
      87             :     fib_entry_t *cover;
      88             : 
      89          59 :     old_pl = src->fes_pl;
      90          59 :     src->fes_pl = FIB_NODE_INDEX_INVALID;
      91             : 
      92             :     /*
      93             :      * The goal here is to find a path-list that will contribute forwarding
      94             :      * for the entry.
      95             :      * First check this entry for other sources that have a path-list
      96             :      */
      97          59 :     best_src = fib_entry_src_rr_get_next_best(src, fib_entry);
      98             : 
      99          59 :     if (NULL != best_src)
     100             :     {
     101             :         const fib_entry_src_vft_t *vft;
     102             : 
     103          51 :         best_src->fes_flags |= FIB_ENTRY_SRC_FLAG_CONTRIBUTING;
     104          51 :         vft = fib_entry_src_get_vft(best_src);
     105             :         /*
     106             :          * there is another source for this entry. activate it so it
     107             :          * can provide forwarding
     108             :          */
     109          51 :         if (NULL != vft->fesv_activate)
     110             :         {
     111          34 :             if (vft->fesv_activate(best_src, fib_entry))
     112             :             {
     113             :                 /*
     114             :                  * next best source activated ok, use its path list
     115             :                  */
     116          34 :                 src->fes_pl = best_src->fes_pl;
     117             :             }
     118             :             else
     119             :             {
     120             :                 /*
     121             :                  * the best source won't install so will use a drop
     122             :                  */
     123             :                 dpo_proto_t dproto;
     124             : 
     125           0 :                 dproto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto);
     126             : 
     127           0 :                 src->fes_pl =
     128           0 :                     fib_path_list_create_special(dproto,
     129             :                                                  FIB_PATH_LIST_FLAG_DROP,
     130             :                                                  drop_dpo_get(dproto));
     131             :             }
     132             :         }
     133             :         else
     134             :         {
     135             :             /*
     136             :              * next best source does not require activation, use its path list
     137             :              */
     138          17 :             src->fes_pl = best_src->fes_pl;
     139             :         }
     140             :     }
     141             :     else
     142             :     {
     143             :         /*
     144             :          * find the covering prefix. become a dependent thereof.
     145             :          * for IP there should always be a cover, though it may be the default route.
     146             :          * For MPLS there is never a cover.
     147             :          */
     148           8 :         if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
     149             :         {
     150           0 :             src->fes_pl = fib_path_list_create_special(DPO_PROTO_MPLS,
     151             :                                                        FIB_PATH_LIST_FLAG_DROP,
     152             :                                                        NULL);
     153             :         }
     154             :         else
     155             :         {
     156           8 :             src->u.interpose.fesi_cover =
     157           8 :                 fib_table_get_less_specific(fib_entry->fe_fib_index,
     158             :                                             &fib_entry->fe_prefix);
     159             : 
     160           8 :             ASSERT(FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover);
     161             : 
     162           8 :             cover = fib_entry_get(src->u.interpose.fesi_cover);
     163             : 
     164           8 :             src->u.interpose.fesi_sibling =
     165           8 :                 fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
     166             : 
     167             :             /*
     168             :              * if the cover is attached then install an attached-host path
     169             :              * (like an adj-fib). Otherwise inherit the forwarding from the cover
     170             :              */
     171           8 :             if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
     172             :             {
     173           0 :                 fib_entry_src_rr_resolve_via_connected(src, fib_entry, cover);
     174             :             }
     175             :             else
     176             :             {
     177           8 :                 fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
     178             :             }
     179             :         }
     180             :     }
     181             : 
     182          59 :     fib_path_list_unlock(old_pl);
     183          59 :     fib_path_list_lock(src->fes_pl);
     184             : 
     185             :     /*
     186             :      * return go for install
     187             :      */
     188          59 :     return (!0);
     189             : }
     190             : 
     191             : /**
     192             :  * Source Deactivate.
     193             :  * Called when the source is no longer best source on the entry
     194             :  */
     195             : static void
     196          60 : fib_entry_src_interpose_deactivate (fib_entry_src_t *src,
     197             :                                     const fib_entry_t *fib_entry)
     198             : {
     199             :     fib_entry_t *cover;
     200             : 
     201          60 :     if (FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover)
     202             :     {
     203             :         /*
     204             :          * remove the dependency on the covering entry, if that's
     205             :          * what was contributing the path-list
     206             :          */
     207           8 :         cover = fib_entry_get(src->u.interpose.fesi_cover);
     208           8 :         fib_entry_cover_untrack(cover, src->u.interpose.fesi_sibling);
     209           8 :         src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
     210             :     }
     211             :     else
     212             :     {
     213             :         fib_entry_src_t *best_src;
     214             : 
     215          52 :         best_src = fib_entry_src_rr_get_next_best(src, fib_entry);
     216             : 
     217          52 :         if (best_src)
     218             :         {
     219          44 :             best_src->fes_flags &= ~FIB_ENTRY_SRC_FLAG_CONTRIBUTING;
     220             :             /*
     221             :              * there is another source for this entry. activate it so it
     222             :              * can provide forwarding
     223             :              */
     224          44 :             FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, best_src, fesv_deactivate,
     225             :                                      (best_src, fib_entry));
     226             :         }
     227             :     }
     228             : 
     229          60 :     fib_path_list_unlock(src->fes_pl);
     230          60 :     src->fes_pl = FIB_NODE_INDEX_INVALID;
     231          60 :     src->fes_entry_flags &= ~FIB_ENTRY_FLAGS_RR_INHERITED;
     232          60 : }
     233             : 
     234             : static int
     235          14 : fib_entry_src_interpose_reactivate (fib_entry_src_t *src,
     236             :                                     const fib_entry_t *fib_entry)
     237             : {
     238          14 :     fib_entry_src_interpose_deactivate(src, fib_entry);
     239          14 :     return (fib_entry_src_interpose_activate(src, fib_entry));
     240             : }
     241             : 
     242             : static fib_entry_src_cover_res_t
     243           2 : fib_entry_src_interpose_cover_change (fib_entry_src_t *src,
     244             :                                       const fib_entry_t *fib_entry)
     245             : {
     246           2 :     fib_entry_src_cover_res_t res = {
     247             :        .install = !0,
     248             :        .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
     249             :     };
     250             : 
     251           2 :     if (FIB_NODE_INDEX_INVALID == src->u.interpose.fesi_cover)
     252             :     {
     253             :        /*
     254             :         * the source may be added, but it is not active
     255             :         * if it is not tracking the cover.
     256             :         */
     257           0 :        return (res);
     258             :     }
     259             : 
     260             :     /*
     261             :      * this function is called when this entry's cover has a more specific
     262             :      * entry inserted beneath it. That does not necessarily mean that this
     263             :      * entry is covered by the new prefix. check that
     264             :      */
     265           2 :     if (src->u.interpose.fesi_cover !=
     266           2 :         fib_table_get_less_specific(fib_entry->fe_fib_index,
     267             :                                     &fib_entry->fe_prefix))
     268             :     {
     269           2 :        fib_entry_src_interpose_deactivate(src, fib_entry);
     270           2 :        fib_entry_src_interpose_activate(src, fib_entry);
     271             : 
     272             :        /*
     273             :         * dependent children need to re-resolve to the new forwarding info
     274             :         */
     275           2 :        res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
     276             :     }
     277           2 :     return (res);
     278             : }
     279             : 
     280             : static void
     281          38 : fib_entry_src_interpose_add (fib_entry_src_t *src,
     282             :                              const fib_entry_t *entry,
     283             :                              fib_entry_flag_t flags,
     284             :                              dpo_proto_t proto,
     285             :                              const dpo_id_t *dpo)
     286             : {
     287          38 :     dpo_copy(&src->u.interpose.fesi_dpo, dpo);
     288          38 : }
     289             : 
     290             : static void
     291          42 : fib_entry_src_interpose_remove (fib_entry_src_t *src)
     292             : {
     293          42 :     dpo_reset(&src->u.interpose.fesi_dpo);
     294          42 : }
     295             : 
     296             : static void
     297           0 : fib_entry_src_interpose_set_data (fib_entry_src_t *src,
     298             :                                   const fib_entry_t *fib_entry,
     299             :                                   const void *data)
     300             : {
     301           0 :     const dpo_id_t *dpo = data;
     302             : 
     303           0 :     dpo_copy(&src->u.interpose.fesi_dpo, dpo);
     304           0 : }
     305             : 
     306             : /**
     307             :  * Contribute forwarding to interpose in the chain
     308             :  */
     309          47 : const dpo_id_t* fib_entry_src_interpose_contribute(const fib_entry_src_t *src,
     310             :                                                    const fib_entry_t *fib_entry)
     311             : {
     312          47 :     return (&src->u.interpose.fesi_dpo);
     313             : }
     314             : 
     315             : static void
     316           4 : fib_entry_src_interpose_copy (const fib_entry_src_t *orig_src,
     317             :                               const fib_entry_t *fib_entry,
     318             :                               fib_entry_src_t *copy_src)
     319             : {
     320           4 :     copy_src->u.interpose.fesi_cover = orig_src->u.interpose.fesi_cover;
     321             : 
     322           4 :     if (FIB_NODE_INDEX_INVALID != copy_src->u.interpose.fesi_cover)
     323             :     {
     324             :         fib_entry_t *cover;
     325             : 
     326           0 :         cover = fib_entry_get(orig_src->u.interpose.fesi_cover);
     327           0 :         copy_src->u.interpose.fesi_sibling =
     328           0 :             fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
     329             :     }
     330             : 
     331           4 :     dpo_copy(&copy_src->u.interpose.fesi_dpo,
     332             :              &orig_src->u.interpose.fesi_dpo);
     333           4 : }
     334             : 
     335             : static void
     336           0 : fib_entry_src_interpose_flag_change (fib_entry_src_t *src,
     337             :                                      const fib_entry_t *fib_entry,
     338             :                                      fib_entry_flag_t new_flags)
     339             : {
     340           0 :     if (!(new_flags & FIB_ENTRY_FLAG_INTERPOSE))
     341             :     {
     342             :         /*
     343             :          * stop tracking the source contributing forwarding
     344             :          * and reset the interposer DPO
     345             :          */
     346           0 :         fib_entry_src_interpose_deactivate(src, fib_entry);
     347           0 :         fib_entry_src_interpose_deinit(src);
     348             :     }
     349           0 : }
     350             : 
     351             : static u8*
     352           1 : fib_entry_src_interpose_format (fib_entry_src_t *src,
     353             :                                 u8* s)
     354             : {
     355           1 :     s = format(s, " cover:%d interpose:\n%U%U",
     356             :                src->u.interpose.fesi_cover,
     357             :                format_white_space, 6,
     358             :                format_dpo_id, &src->u.interpose.fesi_dpo, 8);
     359             : 
     360           1 :     return (s);
     361             : }
     362             : 
     363             : const static fib_entry_src_vft_t interpose_src_vft = {
     364             :     .fesv_init = fib_entry_src_interpose_init,
     365             :     .fesv_deinit = fib_entry_src_interpose_deinit,
     366             :     .fesv_activate = fib_entry_src_interpose_activate,
     367             :     .fesv_reactivate = fib_entry_src_interpose_reactivate,
     368             :     .fesv_deactivate = fib_entry_src_interpose_deactivate,
     369             :     .fesv_cover_change = fib_entry_src_interpose_cover_change,
     370             :     .fesv_cover_update = fib_entry_src_rr_cover_update,
     371             :     .fesv_format = fib_entry_src_interpose_format,
     372             :     .fesv_add = fib_entry_src_interpose_add,
     373             :     .fesv_remove = fib_entry_src_interpose_remove,
     374             :     .fesv_contribute_interpose = fib_entry_src_interpose_contribute,
     375             :     .fesv_set_data = fib_entry_src_interpose_set_data,
     376             :     .fesv_copy = fib_entry_src_interpose_copy,
     377             :     .fesv_flags_change = fib_entry_src_interpose_flag_change,
     378             : };
     379             : 
     380             : void
     381         575 : fib_entry_src_interpose_register (void)
     382             : {
     383         575 :     fib_entry_src_behaviour_register(FIB_SOURCE_BH_INTERPOSE,
     384             :                                      &interpose_src_vft);
     385         575 : }

Generated by: LCOV version 1.14