LCOV - code coverage report
Current view: top level - vnet/fib - fib_bfd.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 48 49 98.0 %
Date: 2023-07-05 22:20:52 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/bfd/bfd_main.h>
      17             : 
      18             : #include <vnet/fib/fib_entry_delegate.h>
      19             : #include <vnet/fib/fib_entry.h>
      20             : #include <vnet/fib/fib_table.h>
      21             : #include <vnet/fib/fib_walk.h>
      22             : 
      23             : static fib_bfd_state_t
      24           4 : fib_bfd_bfd_state_to_fib (bfd_state_e bstate)
      25             : {
      26           4 :     switch (bstate)
      27             :     {
      28           2 :     case BFD_STATE_up:
      29           2 :         return (FIB_BFD_STATE_UP);
      30           2 :     case BFD_STATE_down:
      31             :     case BFD_STATE_admin_down:
      32             :     case BFD_STATE_init:
      33           2 :         return (FIB_BFD_STATE_DOWN);
      34             :     }
      35           0 :     return (FIB_BFD_STATE_DOWN);
      36             : }
      37             : 
      38             : static void
      39           8 : fib_bfd_update_walk (fib_node_index_t fei)
      40             : {
      41             :     /*
      42             :      * initiate a backwalk of dependent children
      43             :      * to notify of the state change of this entry.
      44             :      */
      45           8 :     fib_node_back_walk_ctx_t ctx = {
      46             :         .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE,
      47             :     };
      48           8 :     fib_walk_sync(FIB_NODE_TYPE_ENTRY, fei, &ctx);
      49           8 : }
      50             : 
      51             : /**
      52             :  * @brief Callback function registered with BFD module to receive notifications
      53             :  * of the CRUD of BFD sessions
      54             :  * would be static but for the fact it's called from the unit-tests
      55             :  */
      56             : void
      57         348 : fib_bfd_notify (bfd_listen_event_e event,
      58             :                 const bfd_session_t *session)
      59             : {
      60             :     fib_entry_delegate_t *fed;
      61             :     const bfd_udp_key_t *key;
      62             :     fib_node_index_t fei;
      63             : 
      64         348 :     if (BFD_HOP_TYPE_MULTI != session->hop_type)
      65             :     {
      66             :         /*
      67             :          * multi-hop BFD sessions attach directly to the FIB entry
      68             :          * single-hop adj to the associate adjacency.
      69             :          */
      70         336 :         return;
      71             :     }
      72             : 
      73          12 :     key = &session->udp.key;
      74             : 
      75          12 :     fib_prefix_t pfx = {
      76             :         .fp_addr = key->peer_addr,
      77          12 :         .fp_proto = (ip46_address_is_ip4 (&key->peer_addr) ?
      78          12 :                      FIB_PROTOCOL_IP4:
      79             :                      FIB_PROTOCOL_IP6),
      80          12 :         .fp_len = (ip46_address_is_ip4 (&key->peer_addr) ?
      81             :                    32:
      82             :                    128),
      83             :     };
      84             : 
      85             :     /*
      86             :      * get the FIB entry
      87             :      */
      88          12 :     fei = fib_table_lookup_exact_match(key->fib_index, &pfx);
      89             : 
      90          12 :     switch (event)
      91             :     {
      92           4 :     case BFD_LISTEN_EVENT_CREATE:
      93             :         /*
      94             :          * The creation of a new session
      95             :          */
      96           6 :         if ((FIB_NODE_INDEX_INVALID != fei) &&
      97           2 :             (fed = fib_entry_delegate_find(fib_entry_get(fei),
      98             :                                            FIB_ENTRY_DELEGATE_BFD)))
      99             :         {
     100             :             /*
     101             :              * already got state for this entry
     102             :              */
     103             :         }
     104             :         else
     105             :         {
     106             :             /*
     107             :              * source and lock the entry. add the delegate
     108             :              */
     109           4 :             fei = fib_table_entry_special_add(key->fib_index,
     110             :                                               &pfx,
     111             :                                               FIB_SOURCE_RR,
     112             :                                               FIB_ENTRY_FLAG_NONE);
     113           4 :             fib_entry_lock(fei);
     114             : 
     115           4 :             fed = fib_entry_delegate_find_or_add(fib_entry_get(fei),
     116             :                                                  FIB_ENTRY_DELEGATE_BFD);
     117             : 
     118             :             /*
     119             :              * pretend the session is up and skip the walk.
     120             :              * If we set it down then we get traffic loss on new children.
     121             :              * if we walk then we lose traffic for existing children. Wait
     122             :              * for the first BFD UP/DOWN before we let the session's state
     123             :              * influence forwarding.
     124             :              */
     125           4 :             fed->fd_bfd_state = FIB_BFD_STATE_UP;
     126             :         }
     127           4 :         break;
     128             : 
     129           4 :     case BFD_LISTEN_EVENT_UPDATE:
     130             :         /*
     131             :          * state change up/dowm and
     132             :          */
     133           4 :         ASSERT(FIB_NODE_INDEX_INVALID != fei);
     134             : 
     135           4 :         fed = fib_entry_delegate_find(fib_entry_get(fei),
     136             :                                       FIB_ENTRY_DELEGATE_BFD);
     137             : 
     138           4 :         if (NULL != fed)
     139             :         {
     140           4 :             fed->fd_bfd_state = fib_bfd_bfd_state_to_fib(session->local_state);
     141           4 :             fib_bfd_update_walk(fei);
     142             :         }
     143             :         /*
     144             :          * else
     145             :          *   no BFD state
     146             :          */
     147           4 :         break;
     148             : 
     149           4 :     case BFD_LISTEN_EVENT_DELETE:
     150             :         /*
     151             :          * session has been removed.
     152             :          */
     153           4 :         if (FIB_NODE_INDEX_INVALID == fei)
     154             :         {
     155             :             /*
     156             :              * no FIB entry
     157             :              */
     158             :         }
     159           4 :         else if (fib_entry_delegate_find(fib_entry_get(fei),
     160             :                                          FIB_ENTRY_DELEGATE_BFD))
     161             :         {
     162             :             /*
     163             :              * has an associated BFD tracking delegate
     164             :              * usource the entry and remove the BFD tracking delegate
     165             :              */
     166           4 :             fib_entry_delegate_remove(fib_entry_get(fei),
     167             :                                       FIB_ENTRY_DELEGATE_BFD);
     168           4 :             fib_bfd_update_walk(fei);
     169             : 
     170           4 :             fib_table_entry_special_remove(key->fib_index,
     171             :                                            &pfx,
     172             :                                            FIB_SOURCE_RR);
     173           4 :             fib_entry_unlock(fei);
     174             :         }
     175             :         /*
     176             :          * else
     177             :          * no BFD associated state
     178             :          */
     179           4 :         break;
     180             :     }
     181          12 : }
     182             : 
     183             : static clib_error_t *
     184         559 : fib_bfd_main_init (vlib_main_t * vm)
     185             : {
     186         559 :     bfd_register_listener(fib_bfd_notify);
     187             : 
     188         559 :     return (NULL);
     189             : }
     190             : 
     191             : /* *INDENT-OFF* */
     192       81199 : VLIB_INIT_FUNCTION (fib_bfd_main_init) =
     193             : {
     194             :     .runs_after = VLIB_INITS("bfd_main_init"),
     195             : };
     196             : /* *INDENT-ON* */

Generated by: LCOV version 1.14