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