Coverage Report

Created: 2025-07-14 06:48

/src/frr/ospfd/ospf_bfd.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/**
3
 * ospf_bfd.c: OSPF BFD handling routines
4
 *
5
 * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
6
 */
7
8
#include <zebra.h>
9
10
#include "command.h"
11
#include "json.h"
12
#include "linklist.h"
13
#include "memory.h"
14
#include "prefix.h"
15
#include "frrevent.h"
16
#include "buffer.h"
17
#include "stream.h"
18
#include "zclient.h"
19
#include "vty.h"
20
#include "table.h"
21
#include "bfd.h"
22
#include "ospfd.h"
23
#include "ospf_asbr.h"
24
#include "ospf_lsa.h"
25
#include "ospf_lsdb.h"
26
#include "ospf_neighbor.h"
27
#include "ospf_interface.h"
28
#include "ospf_nsm.h"
29
#include "ospf_bfd.h"
30
#include "ospf_dump.h"
31
#include "ospf_vty.h"
32
33
DEFINE_MTYPE_STATIC(OSPFD, BFD_CONFIG, "BFD configuration data");
34
35
/*
36
 * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
37
 *                          neighbor state is changed to/from 2way.
38
 */
39
void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state)
40
0
{
41
0
  if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay))
42
0
    bfd_sess_install(nbr->bfd_session);
43
0
  else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay))
44
0
    bfd_sess_uninstall(nbr->bfd_session);
45
0
}
46
47
static void ospf_bfd_session_change(struct bfd_session_params *bsp,
48
            const struct bfd_session_status *bss,
49
            void *arg)
50
0
{
51
0
  struct ospf_neighbor *nbr = arg;
52
53
  /* BFD peer went down. */
54
0
  if (bss->state == BFD_STATUS_DOWN
55
0
      && bss->previous_state == BFD_STATUS_UP) {
56
0
    if (IS_DEBUG_OSPF(bfd, BFD_LIB))
57
0
      zlog_debug("%s: NSM[%s:%pI4]: BFD Down", __func__,
58
0
           IF_NAME(nbr->oi), &nbr->address.u.prefix4);
59
60
0
    OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer);
61
0
  }
62
63
  /* BFD peer went up. */
64
0
  if (bss->state == BSS_UP && bss->previous_state == BSS_DOWN)
65
0
    if (IS_DEBUG_OSPF(bfd, BFD_LIB))
66
0
      zlog_debug("%s: NSM[%s:%pI4]: BFD Up", __func__,
67
0
           IF_NAME(nbr->oi), &nbr->address.u.prefix4);
68
0
}
69
70
void ospf_neighbor_bfd_apply(struct ospf_neighbor *nbr)
71
245
{
72
245
  struct ospf_interface *oi = nbr->oi;
73
245
  struct ospf_if_params *oip = IF_DEF_PARAMS(oi->ifp);
74
75
  /* BFD configuration was removed. */
76
245
  if (oip->bfd_config == NULL) {
77
245
    bfd_sess_free(&nbr->bfd_session);
78
245
    return;
79
245
  }
80
81
  /* New BFD session. */
82
0
  if (nbr->bfd_session == NULL) {
83
0
    nbr->bfd_session = bfd_sess_new(ospf_bfd_session_change, nbr);
84
0
    bfd_sess_set_ipv4_addrs(nbr->bfd_session, NULL, &nbr->src);
85
0
    bfd_sess_set_interface(nbr->bfd_session, oi->ifp->name);
86
0
    bfd_sess_set_vrf(nbr->bfd_session, oi->ospf->vrf_id);
87
0
  }
88
89
  /* Set new configuration. */
90
0
  bfd_sess_set_timers(nbr->bfd_session,
91
0
          oip->bfd_config->detection_multiplier,
92
0
          oip->bfd_config->min_rx, oip->bfd_config->min_tx);
93
0
  bfd_sess_set_profile(nbr->bfd_session, oip->bfd_config->profile);
94
95
  /* Don't start sessions on down OSPF sessions. */
96
0
  if (nbr->state < NSM_TwoWay)
97
0
    return;
98
99
0
  bfd_sess_install(nbr->bfd_session);
100
0
}
101
102
static void ospf_interface_bfd_apply(struct interface *ifp)
103
0
{
104
0
  struct ospf_interface *oi;
105
0
  struct route_table *nbrs;
106
0
  struct ospf_neighbor *nbr;
107
0
  struct route_node *irn;
108
0
  struct route_node *nrn;
109
110
  /* Iterate over all interfaces and set neighbors BFD session. */
111
0
  for (irn = route_top(IF_OIFS(ifp)); irn; irn = route_next(irn)) {
112
0
    if ((oi = irn->info) == NULL)
113
0
      continue;
114
0
    if ((nbrs = oi->nbrs) == NULL)
115
0
      continue;
116
0
    for (nrn = route_top(nbrs); nrn; nrn = route_next(nrn)) {
117
0
      if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self)
118
0
        continue;
119
120
0
      ospf_neighbor_bfd_apply(nbr);
121
0
    }
122
0
  }
123
0
}
124
125
static void ospf_interface_enable_bfd(struct interface *ifp)
126
0
{
127
0
  struct ospf_if_params *oip = IF_DEF_PARAMS(ifp);
128
129
0
  if (oip->bfd_config)
130
0
    return;
131
132
  /* Allocate memory for configurations and set defaults. */
133
0
  oip->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*oip->bfd_config));
134
0
  oip->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
135
0
  oip->bfd_config->min_rx = BFD_DEF_MIN_RX;
136
0
  oip->bfd_config->min_tx = BFD_DEF_MIN_TX;
137
0
}
138
139
void ospf_interface_disable_bfd(struct interface *ifp,
140
        struct ospf_if_params *oip)
141
0
{
142
0
  XFREE(MTYPE_BFD_CONFIG, oip->bfd_config);
143
0
  ospf_interface_bfd_apply(ifp);
144
0
}
145
146
/*
147
 * ospf_bfd_write_config - Write the interface BFD configuration.
148
 */
149
void ospf_bfd_write_config(struct vty *vty, const struct ospf_if_params *params
150
         __attribute__((unused)))
151
0
{
152
#if HAVE_BFDD == 0
153
  if (params->bfd_config->detection_multiplier != BFD_DEF_DETECT_MULT
154
      || params->bfd_config->min_rx != BFD_DEF_MIN_RX
155
      || params->bfd_config->min_tx != BFD_DEF_MIN_TX)
156
    vty_out(vty, " ip ospf bfd %d %d %d\n",
157
      params->bfd_config->detection_multiplier,
158
      params->bfd_config->min_rx, params->bfd_config->min_tx);
159
  else
160
#endif /* ! HAVE_BFDD */
161
0
    vty_out(vty, " ip ospf bfd\n");
162
163
0
  if (params->bfd_config->profile[0])
164
0
    vty_out(vty, " ip ospf bfd profile %s\n",
165
0
      params->bfd_config->profile);
166
0
}
167
168
void ospf_interface_bfd_show(struct vty *vty, const struct interface *ifp,
169
           struct json_object *json)
170
0
{
171
0
  struct ospf_if_params *params = IF_DEF_PARAMS(ifp);
172
0
  struct bfd_configuration *bfd_config = params->bfd_config;
173
0
  struct json_object *json_bfd;
174
175
0
  if (bfd_config == NULL)
176
0
    return;
177
178
0
  if (json) {
179
0
    json_bfd = json_object_new_object();
180
0
    json_object_int_add(json_bfd, "detectionMultiplier",
181
0
            bfd_config->detection_multiplier);
182
0
    json_object_int_add(json_bfd, "rxMinInterval",
183
0
            bfd_config->min_rx);
184
0
    json_object_int_add(json_bfd, "txMinInterval",
185
0
            bfd_config->min_tx);
186
0
    json_object_object_add(json, "peerBfdInfo", json_bfd);
187
0
  } else
188
0
    vty_out(vty,
189
0
      "  BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
190
0
      bfd_config->detection_multiplier, bfd_config->min_rx,
191
0
      bfd_config->min_tx);
192
0
}
193
194
DEFUN (ip_ospf_bfd,
195
       ip_ospf_bfd_cmd,
196
       "ip ospf bfd",
197
       "IP Information\n"
198
       "OSPF interface commands\n"
199
       "Enables BFD support\n")
200
0
{
201
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
202
0
  ospf_interface_enable_bfd(ifp);
203
0
  ospf_interface_bfd_apply(ifp);
204
0
  return CMD_SUCCESS;
205
0
}
206
207
#if HAVE_BFDD > 0
208
DEFUN_HIDDEN(
209
#else
210
DEFUN(
211
#endif /* HAVE_BFDD */
212
       ip_ospf_bfd_param,
213
       ip_ospf_bfd_param_cmd,
214
       "ip ospf bfd (2-255) (50-60000) (50-60000)",
215
       "IP Information\n"
216
       "OSPF interface commands\n"
217
       "Enables BFD support\n"
218
       "Detect Multiplier\n"
219
       "Required min receive interval\n"
220
       "Desired min transmit interval\n")
221
0
{
222
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
223
0
  struct ospf_if_params *params;
224
0
  int idx_number = 3;
225
0
  int idx_number_2 = 4;
226
0
  int idx_number_3 = 5;
227
228
0
  ospf_interface_enable_bfd(ifp);
229
230
0
  params = IF_DEF_PARAMS(ifp);
231
0
  params->bfd_config->detection_multiplier =
232
0
    strtol(argv[idx_number]->arg, NULL, 10);
233
0
  params->bfd_config->min_rx = strtol(argv[idx_number_2]->arg, NULL, 10);
234
0
  params->bfd_config->min_tx = strtol(argv[idx_number_3]->arg, NULL, 10);
235
236
0
  ospf_interface_bfd_apply(ifp);
237
238
0
  return CMD_SUCCESS;
239
0
}
240
241
DEFUN (ip_ospf_bfd_prof,
242
       ip_ospf_bfd_prof_cmd,
243
       "ip ospf bfd profile BFDPROF",
244
       "IP Information\n"
245
       "OSPF interface commands\n"
246
       "Enables BFD support\n"
247
       BFD_PROFILE_STR
248
       BFD_PROFILE_NAME_STR)
249
0
{
250
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
251
0
  struct ospf_if_params *params;
252
0
  int idx_prof = 4;
253
254
0
  params = IF_DEF_PARAMS(ifp);
255
0
  if (!params->bfd_config) {
256
0
    vty_out(vty, "ip ospf bfd has not been set\n");
257
0
    return CMD_WARNING;
258
0
  }
259
260
0
  strlcpy(params->bfd_config->profile, argv[idx_prof]->arg,
261
0
    sizeof(params->bfd_config->profile));
262
0
  ospf_interface_bfd_apply(ifp);
263
264
0
  return CMD_SUCCESS;
265
0
}
266
267
DEFUN (no_ip_ospf_bfd_prof,
268
       no_ip_ospf_bfd_prof_cmd,
269
       "no ip ospf bfd profile [BFDPROF]",
270
       NO_STR
271
       "IP Information\n"
272
       "OSPF interface commands\n"
273
       "Enables BFD support\n"
274
       BFD_PROFILE_STR
275
       BFD_PROFILE_NAME_STR)
276
0
{
277
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
278
0
  struct ospf_if_params *params;
279
280
0
  params = IF_DEF_PARAMS(ifp);
281
0
  if (!params->bfd_config)
282
0
    return CMD_SUCCESS;
283
284
0
  params->bfd_config->profile[0] = 0;
285
0
  ospf_interface_bfd_apply(ifp);
286
287
0
  return CMD_SUCCESS;
288
0
}
289
290
DEFUN (no_ip_ospf_bfd,
291
       no_ip_ospf_bfd_cmd,
292
#if HAVE_BFDD > 0
293
       "no ip ospf bfd",
294
#else
295
       "no ip ospf bfd [(2-255) (50-60000) (50-60000)]",
296
#endif /* HAVE_BFDD */
297
       NO_STR
298
       "IP Information\n"
299
       "OSPF interface commands\n"
300
       "Disables BFD support\n"
301
#if HAVE_BFDD == 0
302
       "Detect Multiplier\n"
303
       "Required min receive interval\n"
304
       "Desired min transmit interval\n"
305
#endif /* !HAVE_BFDD */
306
)
307
0
{
308
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
309
0
  ospf_interface_disable_bfd(ifp, IF_DEF_PARAMS(ifp));
310
0
  return CMD_SUCCESS;
311
0
}
312
313
void ospf_bfd_init(struct event_loop *tm)
314
1
{
315
1
  bfd_protocol_integration_init(zclient, tm);
316
317
  /* Install BFD command */
318
1
  install_element(INTERFACE_NODE, &ip_ospf_bfd_cmd);
319
1
  install_element(INTERFACE_NODE, &ip_ospf_bfd_param_cmd);
320
1
  install_element(INTERFACE_NODE, &ip_ospf_bfd_prof_cmd);
321
1
  install_element(INTERFACE_NODE, &no_ip_ospf_bfd_prof_cmd);
322
1
  install_element(INTERFACE_NODE, &no_ip_ospf_bfd_cmd);
323
1
}