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