Coverage Report

Created: 2025-10-08 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_bfd.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/**
3
 * bgp_bfd.c: BGP 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 "linklist.h"
12
#include "memory.h"
13
#include "prefix.h"
14
#include "frrevent.h"
15
#include "buffer.h"
16
#include "stream.h"
17
#include "vrf.h"
18
#include "zclient.h"
19
#include "bfd.h"
20
#include "lib/json.h"
21
#include "filter.h"
22
23
#include "bgpd/bgpd.h"
24
#include "bgp_fsm.h"
25
#include "bgpd/bgp_bfd.h"
26
#include "bgpd/bgp_debug.h"
27
#include "bgpd/bgp_vty.h"
28
#include "bgpd/bgp_packet.h"
29
30
2
DEFINE_MTYPE_STATIC(BGPD, BFD_CONFIG, "BFD configuration data");
31
2
32
2
extern struct zclient *zclient;
33
2
34
2
static void bfd_session_status_update(struct bfd_session_params *bsp,
35
2
              const struct bfd_session_status *bss,
36
2
              void *arg)
37
2
{
38
0
  struct peer *peer = arg;
39
40
0
  if (BGP_DEBUG(bfd, BFD_LIB))
41
0
    zlog_debug("%s: neighbor %s vrf %s(%u) bfd state %s -> %s",
42
0
         __func__, peer->conf_if ? peer->conf_if : peer->host,
43
0
         bfd_sess_vrf(bsp), bfd_sess_vrf_id(bsp),
44
0
         bfd_get_status_str(bss->previous_state),
45
0
         bfd_get_status_str(bss->state));
46
47
0
  if (bss->state == BSS_DOWN && bss->previous_state == BSS_UP) {
48
0
    if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)
49
0
        && bfd_sess_cbit(bsp) && !bss->remote_cbit) {
50
0
      if (BGP_DEBUG(bfd, BFD_LIB))
51
0
        zlog_debug(
52
0
          "%s BFD DOWN message ignored in the process of graceful restart when C bit is cleared",
53
0
          peer->host);
54
0
      return;
55
0
    }
56
0
    peer->last_reset = PEER_DOWN_BFD_DOWN;
57
58
    /* rfc9384 */
59
0
    if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
60
0
      bgp_notify_send(peer, BGP_NOTIFY_CEASE,
61
0
          BGP_NOTIFY_CEASE_BFD_DOWN);
62
63
0
    BGP_EVENT_ADD(peer, BGP_Stop);
64
0
  }
65
66
0
  if (bss->state == BSS_UP && bss->previous_state != BSS_UP
67
0
      && !peer_established(peer)) {
68
0
    if (!BGP_PEER_START_SUPPRESSED(peer)) {
69
0
      bgp_fsm_nht_update(peer, true);
70
0
      BGP_EVENT_ADD(peer, BGP_Start);
71
0
    }
72
0
  }
73
0
}
74
75
void bgp_peer_config_apply(struct peer *p, struct peer_group *pg)
76
0
{
77
0
  struct listnode *n;
78
0
  struct peer *pn;
79
0
  struct peer *gconfig;
80
81
  /* When called on a group, apply to all peers. */
82
0
  if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP)) {
83
0
    for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
84
0
      bgp_peer_config_apply(pn, pg);
85
0
    return;
86
0
  }
87
88
  /* No group, just use current configuration. */
89
0
  if (pg == NULL || pg->conf->bfd_config == NULL) {
90
0
    bfd_sess_set_timers(p->bfd_config->session,
91
0
            p->bfd_config->detection_multiplier,
92
0
            p->bfd_config->min_rx,
93
0
            p->bfd_config->min_tx);
94
0
    bfd_sess_set_cbit(p->bfd_config->session, p->bfd_config->cbit);
95
0
    bfd_sess_set_profile(p->bfd_config->session,
96
0
             p->bfd_config->profile);
97
0
    bfd_sess_install(p->bfd_config->session);
98
0
    return;
99
0
  }
100
101
  /*
102
   * Check if the group configuration was overwritten or apply group
103
   * configuration.
104
   */
105
0
  gconfig = pg->conf;
106
107
  /*
108
   * If using default control plane independent configuration,
109
   * then prefer group's (e.g. it means it wasn't manually configured).
110
   */
111
0
  if (!p->bfd_config->cbit)
112
0
    bfd_sess_set_cbit(p->bfd_config->session,
113
0
          gconfig->bfd_config->cbit);
114
0
  else
115
0
    bfd_sess_set_cbit(p->bfd_config->session, p->bfd_config->cbit);
116
117
  /* If no profile was specified in peer, then use the group profile. */
118
0
  if (p->bfd_config->profile[0] == 0)
119
0
    bfd_sess_set_profile(p->bfd_config->session,
120
0
             gconfig->bfd_config->profile);
121
0
  else
122
0
    bfd_sess_set_profile(p->bfd_config->session,
123
0
             p->bfd_config->profile);
124
125
  /* If no specific timers were configured, then use the group timers. */
126
0
  if (p->bfd_config->detection_multiplier == BFD_DEF_DETECT_MULT
127
0
      || p->bfd_config->min_rx == BFD_DEF_MIN_RX
128
0
      || p->bfd_config->min_tx == BFD_DEF_MIN_TX)
129
0
    bfd_sess_set_timers(p->bfd_config->session,
130
0
            gconfig->bfd_config->detection_multiplier,
131
0
            gconfig->bfd_config->min_rx,
132
0
            gconfig->bfd_config->min_tx);
133
0
  else
134
0
    bfd_sess_set_timers(p->bfd_config->session,
135
0
            p->bfd_config->detection_multiplier,
136
0
            p->bfd_config->min_rx,
137
0
            p->bfd_config->min_tx);
138
139
0
  bfd_sess_install(p->bfd_config->session);
140
0
}
141
142
void bgp_peer_bfd_update_source(struct peer *p)
143
0
{
144
0
  struct bfd_session_params *session = p->bfd_config->session;
145
0
  const union sockunion *source;
146
0
  bool changed = false;
147
0
  int family;
148
0
  union {
149
0
    struct in_addr v4;
150
0
    struct in6_addr v6;
151
0
  } src, dst;
152
153
  /* Nothing to do for groups. */
154
0
  if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
155
0
    return;
156
157
  /* Figure out the correct source to use. */
158
0
  if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
159
0
    source = p->update_source;
160
0
  else
161
0
    source = p->su_local;
162
163
  /* Update peer's source/destination addresses. */
164
0
  bfd_sess_addresses(session, &family, &src.v6, &dst.v6);
165
0
  if (family == AF_INET) {
166
0
    if ((source && source->sin.sin_addr.s_addr != src.v4.s_addr)
167
0
        || p->su.sin.sin_addr.s_addr != dst.v4.s_addr) {
168
0
      if (BGP_DEBUG(bfd, BFD_LIB))
169
0
        zlog_debug(
170
0
          "%s: address [%pI4->%pI4] to [%pI4->%pI4]",
171
0
          __func__, &src.v4, &dst.v4,
172
0
          source ? &source->sin.sin_addr
173
0
                 : &src.v4,
174
0
          &p->su.sin.sin_addr);
175
176
0
      bfd_sess_set_ipv4_addrs(
177
0
        session, source ? &source->sin.sin_addr : NULL,
178
0
        &p->su.sin.sin_addr);
179
0
      changed = true;
180
0
    }
181
0
  } else {
182
0
    if ((source && memcmp(&source->sin6, &src.v6, sizeof(src.v6)))
183
0
        || memcmp(&p->su.sin6, &dst.v6, sizeof(dst.v6))) {
184
0
      if (BGP_DEBUG(bfd, BFD_LIB))
185
0
        zlog_debug(
186
0
          "%s: address [%pI6->%pI6] to [%pI6->%pI6]",
187
0
          __func__, &src.v6, &dst.v6,
188
0
          source ? &source->sin6.sin6_addr
189
0
                 : &src.v6,
190
0
          &p->su.sin6.sin6_addr);
191
192
0
      bfd_sess_set_ipv6_addrs(session,
193
0
            source ? &source->sin6.sin6_addr
194
0
                   : NULL,
195
0
            &p->su.sin6.sin6_addr);
196
0
      changed = true;
197
0
    }
198
0
  }
199
200
  /* Update interface. */
201
0
  if (p->nexthop.ifp && bfd_sess_interface(session) == NULL) {
202
0
    if (BGP_DEBUG(bfd, BFD_LIB))
203
0
      zlog_debug("%s: interface none to %s", __func__,
204
0
           p->nexthop.ifp->name);
205
206
0
    bfd_sess_set_interface(session, p->nexthop.ifp->name);
207
0
    changed = true;
208
0
  }
209
210
  /*
211
   * Update TTL.
212
   *
213
   * Two cases:
214
   * - We detected that the peer is a hop away from us (remove multi hop).
215
   *   (this happens when `p->shared_network` is set to `true`)
216
   * - eBGP multi hop / TTL security changed.
217
   */
218
0
  if (!PEER_IS_MULTIHOP(p) && bfd_sess_hop_count(session) > 1) {
219
0
    if (BGP_DEBUG(bfd, BFD_LIB))
220
0
      zlog_debug("%s: TTL %d to 1", __func__,
221
0
           bfd_sess_hop_count(session));
222
223
0
    bfd_sess_set_hop_count(session, 1);
224
0
    changed = true;
225
0
  }
226
0
  if (PEER_IS_MULTIHOP(p) && p->ttl != bfd_sess_hop_count(session)) {
227
0
    if (BGP_DEBUG(bfd, BFD_LIB))
228
0
      zlog_debug("%s: TTL %d to %d", __func__,
229
0
           bfd_sess_hop_count(session), p->ttl);
230
231
0
    bfd_sess_set_hop_count(session, p->ttl);
232
0
    changed = true;
233
0
  }
234
235
  /* Update VRF. */
236
0
  if (bfd_sess_vrf_id(session) != p->bgp->vrf_id) {
237
0
    if (BGP_DEBUG(bfd, BFD_LIB))
238
0
      zlog_debug(
239
0
        "%s: VRF %s(%d) to %s(%d)", __func__,
240
0
        bfd_sess_vrf(session), bfd_sess_vrf_id(session),
241
0
        vrf_id_to_name(p->bgp->vrf_id), p->bgp->vrf_id);
242
243
0
    bfd_sess_set_vrf(session, p->bgp->vrf_id);
244
0
    changed = true;
245
0
  }
246
247
0
  if (changed)
248
0
    bfd_sess_install(session);
249
0
}
250
251
/**
252
 * Reset BFD configuration data structure to its defaults settings.
253
 */
254
static void bgp_peer_bfd_reset(struct peer *p)
255
0
{
256
  /* Set defaults. */
257
0
  p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
258
0
  p->bfd_config->min_rx = BFD_DEF_MIN_RX;
259
0
  p->bfd_config->min_tx = BFD_DEF_MIN_TX;
260
0
  p->bfd_config->cbit = false;
261
0
  p->bfd_config->profile[0] = 0;
262
0
}
263
264
void bgp_peer_configure_bfd(struct peer *p, bool manual)
265
0
{
266
  /* Groups should not call this. */
267
0
  assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
268
269
  /* Already configured, skip it. */
270
0
  if (p->bfd_config) {
271
    /* If manually active update flag. */
272
0
    if (!p->bfd_config->manual)
273
0
      p->bfd_config->manual = manual;
274
275
0
    return;
276
0
  }
277
278
  /* Allocate memory for configuration overrides. */
279
0
  p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
280
0
  p->bfd_config->manual = manual;
281
282
  /* Create new session and assign callback. */
283
0
  p->bfd_config->session = bfd_sess_new(bfd_session_status_update, p);
284
0
  bgp_peer_bfd_reset(p);
285
286
  /* Configure session with basic BGP peer data. */
287
0
  if (p->su.sa.sa_family == AF_INET)
288
0
    bfd_sess_set_ipv4_addrs(p->bfd_config->session,
289
0
          p->su_local ? &p->su_local->sin.sin_addr
290
0
                : NULL,
291
0
          &p->su.sin.sin_addr);
292
0
  else
293
0
    bfd_sess_set_ipv6_addrs(
294
0
      p->bfd_config->session,
295
0
      p->su_local ? &p->su_local->sin6.sin6_addr : NULL,
296
0
      &p->su.sin6.sin6_addr);
297
298
0
  bfd_sess_set_vrf(p->bfd_config->session, p->bgp->vrf_id);
299
0
  bfd_sess_set_hop_count(p->bfd_config->session,
300
0
             PEER_IS_MULTIHOP(p) ? p->ttl : 1);
301
302
0
  if (p->nexthop.ifp)
303
0
    bfd_sess_set_interface(p->bfd_config->session,
304
0
               p->nexthop.ifp->name);
305
0
}
306
307
static void bgp_peer_remove_bfd(struct peer *p)
308
0
{
309
  /* Groups should not call this. */
310
0
  assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
311
312
  /*
313
   * Peer configuration was removed, however we must check if there
314
   * is still a group configuration to keep this running.
315
   */
316
0
  if (p->group && p->group->conf->bfd_config) {
317
0
    p->bfd_config->manual = false;
318
0
    bgp_peer_bfd_reset(p);
319
0
    bgp_peer_config_apply(p, p->group);
320
0
    return;
321
0
  }
322
323
0
  if (p->bfd_config)
324
0
    bfd_sess_free(&p->bfd_config->session);
325
326
0
  XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
327
0
}
328
329
static void bgp_group_configure_bfd(struct peer *p)
330
0
{
331
0
  struct listnode *n;
332
0
  struct peer *pn;
333
334
  /* Peers should not call this. */
335
0
  assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
336
337
  /* Already allocated: do nothing. */
338
0
  if (p->bfd_config)
339
0
    return;
340
341
0
  p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
342
343
  /* Set defaults. */
344
0
  p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
345
0
  p->bfd_config->min_rx = BFD_DEF_MIN_RX;
346
0
  p->bfd_config->min_tx = BFD_DEF_MIN_TX;
347
348
0
  for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
349
0
    bgp_peer_configure_bfd(pn, false);
350
0
}
351
352
static void bgp_group_remove_bfd(struct peer *p)
353
0
{
354
0
  struct listnode *n;
355
0
  struct peer *pn;
356
357
  /* Peers should not call this. */
358
0
  assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
359
360
  /* Already freed: do nothing. */
361
0
  if (p->bfd_config == NULL)
362
0
    return;
363
364
  /* Free configuration and point to `NULL`. */
365
0
  XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
366
367
  /* Now that it is `NULL` recalculate configuration for all peers. */
368
0
  for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn)) {
369
0
    if (pn->bfd_config->manual)
370
0
      bgp_peer_config_apply(pn, NULL);
371
0
    else
372
0
      bgp_peer_remove_bfd(pn);
373
0
  }
374
0
}
375
376
void bgp_peer_remove_bfd_config(struct peer *p)
377
0
{
378
0
  if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
379
0
    bgp_group_remove_bfd(p);
380
0
  else
381
0
    bgp_peer_remove_bfd(p);
382
0
}
383
384
/*
385
 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
386
 */
387
void bgp_bfd_peer_config_write(struct vty *vty, const struct peer *peer,
388
             const char *addr)
389
0
{
390
  /*
391
   * Always show group BFD configuration, but peer only when explicitly
392
   * configured.
393
   */
394
0
  if ((!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
395
0
       && peer->bfd_config->manual)
396
0
      || CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
397
0
#if HAVE_BFDD > 0
398
0
    vty_out(vty, " neighbor %s bfd\n", addr);
399
#else
400
    vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
401
      peer->bfd_config->detection_multiplier,
402
      peer->bfd_config->min_rx, peer->bfd_config->min_tx);
403
#endif /* HAVE_BFDD */
404
0
  }
405
406
0
  if (peer->bfd_config->profile[0])
407
0
    vty_out(vty, " neighbor %s bfd profile %s\n", addr,
408
0
      peer->bfd_config->profile);
409
410
0
  if (peer->bfd_config->cbit)
411
0
    vty_out(vty, " neighbor %s bfd check-control-plane-failure\n",
412
0
      addr);
413
0
}
414
415
/*
416
 * bgp_bfd_show_info - Show the peer BFD information.
417
 */
418
void bgp_bfd_show_info(struct vty *vty, const struct peer *peer,
419
           json_object *json_neigh)
420
0
{
421
0
  bfd_sess_show(vty, json_neigh, peer->bfd_config->session);
422
0
}
423
424
DEFUN (neighbor_bfd,
425
       neighbor_bfd_cmd,
426
       "neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
427
       NEIGHBOR_STR
428
       NEIGHBOR_ADDR_STR2
429
       "Enables BFD support\n")
430
0
{
431
0
  int idx_peer = 1;
432
0
  struct peer *peer;
433
434
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
435
0
  if (!peer)
436
0
    return CMD_WARNING_CONFIG_FAILED;
437
438
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
439
0
    bgp_group_configure_bfd(peer);
440
0
  else
441
0
    bgp_peer_configure_bfd(peer, true);
442
443
0
  bgp_peer_config_apply(peer, peer->group);
444
445
0
  return CMD_SUCCESS;
446
0
}
447
448
#if HAVE_BFDD > 0
449
DEFUN_HIDDEN(
450
#else
451
DEFUN(
452
#endif /* HAVE_BFDD */
453
       neighbor_bfd_param,
454
       neighbor_bfd_param_cmd,
455
       "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
456
       NEIGHBOR_STR
457
       NEIGHBOR_ADDR_STR2
458
       "Enables BFD support\n"
459
       "Detect Multiplier\n"
460
       "Required min receive interval\n"
461
       "Desired min transmit interval\n")
462
0
{
463
0
  int idx_peer = 1;
464
0
  int idx_number_1 = 3;
465
0
  int idx_number_2 = 4;
466
0
  int idx_number_3 = 5;
467
0
  long detection_multiplier, min_rx, min_tx;
468
0
  struct peer *peer;
469
470
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
471
0
  if (!peer)
472
0
    return CMD_WARNING_CONFIG_FAILED;
473
474
0
  detection_multiplier = strtol(argv[idx_number_1]->arg, NULL, 10);
475
0
  min_rx = strtol(argv[idx_number_2]->arg, NULL, 10);
476
0
  min_tx = strtol(argv[idx_number_3]->arg, NULL, 10);
477
478
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
479
0
    bgp_group_configure_bfd(peer);
480
0
  else
481
0
    bgp_peer_configure_bfd(peer, true);
482
483
0
  peer->bfd_config->detection_multiplier = detection_multiplier;
484
0
  peer->bfd_config->min_rx = min_rx;
485
0
  peer->bfd_config->min_tx = min_tx;
486
0
  bgp_peer_config_apply(peer, peer->group);
487
488
0
  return CMD_SUCCESS;
489
0
}
490
491
DEFUN (neighbor_bfd_check_controlplane_failure,
492
       neighbor_bfd_check_controlplane_failure_cmd,
493
       "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
494
       NO_STR
495
       NEIGHBOR_STR
496
       NEIGHBOR_ADDR_STR2
497
       "BFD support\n"
498
       "Link dataplane status with BGP controlplane\n")
499
0
{
500
0
  const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
501
0
  int idx_peer = 0;
502
0
  struct peer *peer;
503
504
0
  if (no)
505
0
    idx_peer = 2;
506
0
  else
507
0
    idx_peer = 1;
508
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
509
0
  if (!peer)
510
0
    return CMD_WARNING_CONFIG_FAILED;
511
512
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
513
0
    bgp_group_configure_bfd(peer);
514
0
  else
515
0
    bgp_peer_configure_bfd(peer, true);
516
517
0
  peer->bfd_config->cbit = no == NULL;
518
0
  bgp_peer_config_apply(peer, peer->group);
519
520
0
  return CMD_SUCCESS;
521
0
 }
522
523
DEFUN (no_neighbor_bfd,
524
       no_neighbor_bfd_cmd,
525
#if HAVE_BFDD > 0
526
       "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
527
#else
528
       "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
529
#endif /* HAVE_BFDD */
530
       NO_STR
531
       NEIGHBOR_STR
532
       NEIGHBOR_ADDR_STR2
533
       "Disables BFD support\n"
534
#if HAVE_BFDD == 0
535
       "Detect Multiplier\n"
536
       "Required min receive interval\n"
537
       "Desired min transmit interval\n"
538
#endif /* !HAVE_BFDD */
539
)
540
0
{
541
0
  int idx_peer = 2;
542
0
  struct peer *peer;
543
544
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
545
0
  if (!peer)
546
0
    return CMD_WARNING_CONFIG_FAILED;
547
548
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
549
0
    bgp_group_remove_bfd(peer);
550
0
  else
551
0
    bgp_peer_remove_bfd(peer);
552
553
0
  return CMD_SUCCESS;
554
0
}
555
556
#if HAVE_BFDD > 0
557
DEFUN(neighbor_bfd_profile, neighbor_bfd_profile_cmd,
558
      "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF",
559
      NEIGHBOR_STR
560
      NEIGHBOR_ADDR_STR2
561
      "BFD integration\n"
562
      BFD_PROFILE_STR
563
      BFD_PROFILE_NAME_STR)
564
0
{
565
0
  int idx_peer = 1, idx_prof = 4;
566
0
  struct peer *peer;
567
568
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
569
0
  if (!peer)
570
0
    return CMD_WARNING_CONFIG_FAILED;
571
572
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
573
0
    bgp_group_configure_bfd(peer);
574
0
  else
575
0
    bgp_peer_configure_bfd(peer, true);
576
577
0
  strlcpy(peer->bfd_config->profile, argv[idx_prof]->arg,
578
0
    sizeof(peer->bfd_config->profile));
579
0
  bgp_peer_config_apply(peer, peer->group);
580
581
0
  return CMD_SUCCESS;
582
0
}
583
584
DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
585
      "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]",
586
      NO_STR
587
      NEIGHBOR_STR
588
      NEIGHBOR_ADDR_STR2
589
      "BFD integration\n"
590
      BFD_PROFILE_STR
591
      BFD_PROFILE_NAME_STR)
592
0
{
593
0
  int idx_peer = 2;
594
0
  struct peer *peer;
595
596
0
  peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
597
0
  if (!peer)
598
0
    return CMD_WARNING_CONFIG_FAILED;
599
600
0
  if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
601
0
    bgp_group_configure_bfd(peer);
602
0
  else
603
0
    bgp_peer_configure_bfd(peer, true);
604
605
0
  peer->bfd_config->profile[0] = 0;
606
0
  bgp_peer_config_apply(peer, peer->group);
607
608
0
  return CMD_SUCCESS;
609
0
}
610
#endif /* HAVE_BFDD */
611
612
void bgp_bfd_init(struct event_loop *tm)
613
0
{
614
  /* Initialize BFD client functions */
615
0
  bfd_protocol_integration_init(zclient, tm);
616
617
  /* "neighbor bfd" commands. */
618
0
  install_element(BGP_NODE, &neighbor_bfd_cmd);
619
0
  install_element(BGP_NODE, &neighbor_bfd_param_cmd);
620
0
  install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
621
0
  install_element(BGP_NODE, &no_neighbor_bfd_cmd);
622
623
0
#if HAVE_BFDD > 0
624
0
  install_element(BGP_NODE, &neighbor_bfd_profile_cmd);
625
0
  install_element(BGP_NODE, &no_neighbor_bfd_profile_cmd);
626
0
#endif /* HAVE_BFDD */
627
0
}