back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_bfd.c (source / functions) Hit Total Coverage
Test: test_ospf6_vlink.py::VirtualLinkBasic Lines: 14 116 12.1 %
Date: 2023-02-16 02:06:43 Functions: 3 10 30.0 %

          Line data    Source code
       1             : /**
       2             :  * ospf6_bfd.c: IPv6 OSPF BFD handling routines
       3             :  *
       4             :  * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
       5             :  *
       6             :  * This file is part of GNU Zebra.
       7             :  *
       8             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       9             :  * under the terms of the GNU General Public License as published by the
      10             :  * Free Software Foundation; either version 2, or (at your option) any
      11             :  * later version.
      12             :  *
      13             :  * GNU Zebra is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License along
      19             :  * with this program; see the file COPYING; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #include "command.h"
      26             : #include "linklist.h"
      27             : #include "memory.h"
      28             : #include "prefix.h"
      29             : #include "thread.h"
      30             : #include "buffer.h"
      31             : #include "stream.h"
      32             : #include "zclient.h"
      33             : #include "vty.h"
      34             : #include "table.h"
      35             : #include "bfd.h"
      36             : #include "if.h"
      37             : #include "ospf6d.h"
      38             : #include "ospf6_message.h"
      39             : #include "ospf6_neighbor.h"
      40             : #include "ospf6_interface.h"
      41             : #include "ospf6_route.h"
      42             : #include "ospf6_zebra.h"
      43             : #include "ospf6_bfd.h"
      44             : 
      45             : extern struct zclient *zclient;
      46             : 
      47             : /*
      48             :  * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
      49             :  *                           neighbor state is changed to/from 2way.
      50             :  */
      51          98 : void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state,
      52             :                              int state)
      53             : {
      54          98 :         int family;
      55          98 :         struct in6_addr src, dst;
      56             : 
      57             :         /* Skip sessions without BFD. */
      58          98 :         if (on->bfd_session == NULL)
      59          98 :                 return;
      60             : 
      61           0 :         if (old_state < OSPF6_NEIGHBOR_TWOWAY
      62           0 :             && state >= OSPF6_NEIGHBOR_TWOWAY) {
      63             :                 /*
      64             :                  * Check if neighbor address changed.
      65             :                  *
      66             :                  * When the neighbor is configured BFD before having an existing
      67             :                  * connection, then the destination address will be set to `::`
      68             :                  * which will cause session installation failure. This piece of
      69             :                  * code updates the address in that case.
      70             :                  */
      71           0 :                 bfd_sess_addresses(on->bfd_session, &family, &src, &dst);
      72           0 :                 if (memcmp(&on->linklocal_addr, &dst, sizeof(dst))) {
      73           0 :                         bfd_sess_set_ipv6_addrs(on->bfd_session, &src,
      74             :                                                 &on->linklocal_addr);
      75             :                 }
      76             : 
      77           0 :                 bfd_sess_install(on->bfd_session);
      78           0 :         } else if (old_state >= OSPF6_NEIGHBOR_TWOWAY
      79           0 :                    && state < OSPF6_NEIGHBOR_TWOWAY)
      80           0 :                 bfd_sess_uninstall(on->bfd_session);
      81             : }
      82             : 
      83             : /*
      84             :  * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
      85             :  *                               with a interface with BFD through
      86             :  *                               zebra for starting/stopping the monitoring of
      87             :  *                               the neighbor rechahability.
      88             :  */
      89           0 : static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi,
      90             :                                         bool install)
      91             : {
      92           0 :         struct ospf6_neighbor *on;
      93           0 :         struct listnode *node;
      94             : 
      95           0 :         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
      96             :                 /* Remove all sessions. */
      97           0 :                 if (!install) {
      98           0 :                         bfd_sess_free(&on->bfd_session);
      99           0 :                         continue;
     100             :                 }
     101             : 
     102             :                 /* Always allocate session data even if not enabled. */
     103           0 :                 ospf6_bfd_info_nbr_create(oi, on);
     104             : 
     105             :                 /*
     106             :                  * If not connected yet, don't create any session but defer it
     107             :                  * for later. See function `ospf6_bfd_trigger_event`.
     108             :                  */
     109           0 :                 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
     110           0 :                         continue;
     111             : 
     112           0 :                 bfd_sess_install(on->bfd_session);
     113             :         }
     114           0 : }
     115             : 
     116           0 : static void ospf6_bfd_callback(struct bfd_session_params *bsp,
     117             :                                const struct bfd_session_status *bss, void *arg)
     118             : {
     119           0 :         struct ospf6_neighbor *on = arg;
     120             : 
     121           0 :         if (bss->state == BFD_STATUS_DOWN
     122           0 :             && bss->previous_state == BFD_STATUS_UP) {
     123           0 :                 THREAD_OFF(on->inactivity_timer);
     124           0 :                 thread_add_event(master, inactivity_timer, on, 0, NULL);
     125             :         }
     126           0 : }
     127             : 
     128             : /*
     129             :  * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
     130             :  */
     131          18 : void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
     132             :                                struct ospf6_neighbor *on)
     133             : {
     134          18 :         if (!oi->bfd_config.enabled)
     135             :                 return;
     136             : 
     137           0 :         if (on->bfd_session == NULL)
     138           0 :                 on->bfd_session = bfd_sess_new(ospf6_bfd_callback, on);
     139             : 
     140           0 :         bfd_sess_set_timers(on->bfd_session,
     141           0 :                             oi->bfd_config.detection_multiplier,
     142             :                             oi->bfd_config.min_rx, oi->bfd_config.min_tx);
     143           0 :         bfd_sess_set_ipv6_addrs(on->bfd_session, on->ospf6_if->linklocal_addr,
     144           0 :                                 &on->linklocal_addr);
     145           0 :         bfd_sess_set_interface(on->bfd_session, oi->interface->name);
     146           0 :         bfd_sess_set_vrf(on->bfd_session, oi->interface->vrf->vrf_id);
     147           0 :         bfd_sess_set_profile(on->bfd_session, oi->bfd_config.profile);
     148             : }
     149             : 
     150             : /*
     151             :  * ospf6_bfd_write_config - Write the interface BFD configuration.
     152             :  */
     153           0 : void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi)
     154             : {
     155           0 :         if (!oi->bfd_config.enabled)
     156             :                 return;
     157             : 
     158             : #if HAVE_BFDD == 0
     159             :         if (oi->bfd_config.detection_multiplier != BFD_DEF_DETECT_MULT
     160             :             || oi->bfd_config.min_rx != BFD_DEF_MIN_RX
     161             :             || oi->bfd_config.min_tx != BFD_DEF_MIN_TX)
     162             :                 vty_out(vty, " ipv6 ospf6 bfd %d %d %d\n",
     163             :                         oi->bfd_config.detection_multiplier,
     164             :                         oi->bfd_config.min_rx, oi->bfd_config.min_tx);
     165             :         else
     166             : #endif /* ! HAVE_BFDD */
     167           0 :                 vty_out(vty, " ipv6 ospf6 bfd\n");
     168             : 
     169           0 :         if (oi->bfd_config.profile)
     170           0 :                 vty_out(vty, " ipv6 ospf6 bfd profile %s\n",
     171             :                         oi->bfd_config.profile);
     172             : }
     173             : 
     174           0 : DEFUN(ipv6_ospf6_bfd, ipv6_ospf6_bfd_cmd,
     175             :       "ipv6 ospf6 bfd [profile BFDPROF]",
     176             :       IP6_STR OSPF6_STR
     177             :       "Enables BFD support\n"
     178             :       "BFD Profile selection\n"
     179             :       "BFD Profile name\n")
     180             : {
     181           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
     182           0 :         struct ospf6_interface *oi;
     183           0 :         int prof_idx = 4;
     184           0 :         assert(ifp);
     185             : 
     186           0 :         oi = (struct ospf6_interface *)ifp->info;
     187           0 :         if (oi == NULL)
     188           0 :                 oi = ospf6_interface_create(ifp);
     189           0 :         assert(oi);
     190             : 
     191           0 :         oi->bfd_config.detection_multiplier = BFD_DEF_DETECT_MULT;
     192           0 :         oi->bfd_config.min_rx = BFD_DEF_MIN_RX;
     193           0 :         oi->bfd_config.min_tx = BFD_DEF_MIN_TX;
     194           0 :         oi->bfd_config.enabled = true;
     195           0 :         if (argc > prof_idx) {
     196           0 :                 XFREE(MTYPE_TMP, oi->bfd_config.profile);
     197           0 :                 oi->bfd_config.profile =
     198           0 :                         XSTRDUP(MTYPE_TMP, argv[prof_idx]->arg);
     199             :         }
     200             : 
     201           0 :         ospf6_bfd_reg_dereg_all_nbr(oi, true);
     202             : 
     203           0 :         return CMD_SUCCESS;
     204             : }
     205             : 
     206           0 : DEFUN(no_ipv6_ospf6_bfd_profile, no_ipv6_ospf6_bfd_profile_cmd,
     207             :       "no ipv6 ospf6 bfd profile [BFDPROF]",
     208             :       NO_STR IP6_STR OSPF6_STR
     209             :       "BFD support\n"
     210             :       "BFD Profile selection\n"
     211             :       "BFD Profile name\n")
     212             : {
     213           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
     214           0 :         struct ospf6_interface *oi;
     215           0 :         assert(ifp);
     216             : 
     217           0 :         oi = (struct ospf6_interface *)ifp->info;
     218           0 :         if (oi == NULL)
     219           0 :                 oi = ospf6_interface_create(ifp);
     220           0 :         assert(oi);
     221             : 
     222             :         /* BFD not enabled, nothing to do. */
     223           0 :         if (!oi->bfd_config.enabled)
     224             :                 return CMD_SUCCESS;
     225             : 
     226             :         /* Remove profile and apply new configuration. */
     227           0 :         XFREE(MTYPE_TMP, oi->bfd_config.profile);
     228           0 :         ospf6_bfd_reg_dereg_all_nbr(oi, true);
     229             : 
     230           0 :         return CMD_SUCCESS;
     231             : }
     232             : 
     233             : #if HAVE_BFDD > 0
     234           0 : DEFUN_HIDDEN(
     235             : #else
     236             : DEFUN(
     237             : #endif /* HAVE_BFDD */
     238             :        ipv6_ospf6_bfd_param,
     239             :        ipv6_ospf6_bfd_param_cmd,
     240             :        "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
     241             :        IP6_STR
     242             :        OSPF6_STR
     243             :        "Enables BFD support\n"
     244             :        "Detect Multiplier\n"
     245             :        "Required min receive interval\n"
     246             :        "Desired min transmit interval\n")
     247             : {
     248           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
     249           0 :         int idx_number = 3;
     250           0 :         int idx_number_2 = 4;
     251           0 :         int idx_number_3 = 5;
     252           0 :         struct ospf6_interface *oi;
     253             : 
     254           0 :         assert(ifp);
     255             : 
     256           0 :         oi = (struct ospf6_interface *)ifp->info;
     257           0 :         if (oi == NULL)
     258           0 :                 oi = ospf6_interface_create(ifp);
     259           0 :         assert(oi);
     260             : 
     261           0 :         oi->bfd_config.detection_multiplier =
     262           0 :                 strtoul(argv[idx_number]->arg, NULL, 10);
     263           0 :         oi->bfd_config.min_rx = strtoul(argv[idx_number_2]->arg, NULL, 10);
     264           0 :         oi->bfd_config.min_tx = strtoul(argv[idx_number_3]->arg, NULL, 10);
     265           0 :         oi->bfd_config.enabled = true;
     266             : 
     267           0 :         ospf6_bfd_reg_dereg_all_nbr(oi, true);
     268             : 
     269           0 :         return CMD_SUCCESS;
     270             : }
     271             : 
     272           0 : DEFUN (no_ipv6_ospf6_bfd,
     273             :        no_ipv6_ospf6_bfd_cmd,
     274             :        "no ipv6 ospf6 bfd",
     275             :        NO_STR
     276             :        IP6_STR
     277             :        OSPF6_STR
     278             :        "Disables BFD support\n"
     279             :        )
     280             : {
     281           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
     282           0 :         struct ospf6_interface *oi;
     283           0 :         assert(ifp);
     284             : 
     285           0 :         oi = (struct ospf6_interface *)ifp->info;
     286           0 :         if (oi == NULL)
     287           0 :                 oi = ospf6_interface_create(ifp);
     288           0 :         assert(oi);
     289             : 
     290           0 :         oi->bfd_config.enabled = false;
     291           0 :         ospf6_bfd_reg_dereg_all_nbr(oi, false);
     292             : 
     293           0 :         return CMD_SUCCESS;
     294             : }
     295             : 
     296           8 : void ospf6_bfd_init(void)
     297             : {
     298           8 :         bfd_protocol_integration_init(zclient, master);
     299             : 
     300             :         /* Install BFD command */
     301           8 :         install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
     302           8 :         install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
     303           8 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_profile_cmd);
     304           8 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
     305           8 : }

Generated by: LCOV version v1.16-topotato