]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bfd.c
bgpd: Fix continue/break change from old commit
[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 74 if (bss->state == BSS_UP && bss->previous_state != BSS_UP
feb17238 75 && !peer_established(peer)) {
21bfce98
RZ
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 152 struct bfd_session_params *session = p->bfd_config->session;
7196f56e 153 const union sockunion *source;
21bfce98
RZ
154 bool changed = false;
155 int family;
156 union {
157 struct in_addr v4;
158 struct in6_addr v6;
159 } src, dst;
160
161 /* Nothing to do for groups. */
162 if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
95a99382 163 return;
d62a17ae 164
7196f56e 165 /* Figure out the correct source to use. */
5b758690 166 if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
7196f56e
RZ
167 source = p->update_source;
168 else
169 source = p->su_local;
170
21bfce98
RZ
171 /* Update peer's source/destination addresses. */
172 bfd_sess_addresses(session, &family, &src.v6, &dst.v6);
173 if (family == AF_INET) {
7196f56e 174 if ((source && source->sin.sin_addr.s_addr != src.v4.s_addr)
21bfce98 175 || p->su.sin.sin_addr.s_addr != dst.v4.s_addr) {
259f4236 176 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
177 zlog_debug(
178 "%s: address [%pI4->%pI4] to [%pI4->%pI4]",
179 __func__, &src.v4, &dst.v4,
7196f56e
RZ
180 source ? &source->sin.sin_addr
181 : &src.v4,
21bfce98
RZ
182 &p->su.sin.sin_addr);
183
184 bfd_sess_set_ipv4_addrs(
7196f56e 185 session, source ? &source->sin.sin_addr : NULL,
21bfce98
RZ
186 &p->su.sin.sin_addr);
187 changed = true;
188 }
189 } else {
7196f56e 190 if ((source && memcmp(&source->sin6, &src.v6, sizeof(src.v6)))
21bfce98 191 || memcmp(&p->su.sin6, &dst.v6, sizeof(dst.v6))) {
259f4236 192 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
193 zlog_debug(
194 "%s: address [%pI6->%pI6] to [%pI6->%pI6]",
195 __func__, &src.v6, &dst.v6,
7196f56e
RZ
196 source ? &source->sin6.sin6_addr
197 : &src.v6,
21bfce98
RZ
198 &p->su.sin6.sin6_addr);
199
7196f56e
RZ
200 bfd_sess_set_ipv6_addrs(session,
201 source ? &source->sin6.sin6_addr
202 : NULL,
203 &p->su.sin6.sin6_addr);
21bfce98
RZ
204 changed = true;
205 }
206 }
d62a17ae 207
21bfce98
RZ
208 /* Update interface. */
209 if (p->nexthop.ifp && bfd_sess_interface(session) == NULL) {
259f4236 210 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
211 zlog_debug("%s: interface none to %s", __func__,
212 p->nexthop.ifp->name);
d62a17ae 213
21bfce98
RZ
214 bfd_sess_set_interface(session, p->nexthop.ifp->name);
215 changed = true;
d62a17ae 216 }
21bfce98
RZ
217
218 /*
219 * Update TTL.
220 *
221 * Two cases:
222 * - We detected that the peer is a hop away from us (remove multi hop).
223 * (this happens when `p->shared_network` is set to `true`)
224 * - eBGP multi hop / TTL security changed.
9beff0bd 225 */
21bfce98 226 if (!PEER_IS_MULTIHOP(p) && bfd_sess_hop_count(session) > 1) {
259f4236 227 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
228 zlog_debug("%s: TTL %d to 1", __func__,
229 bfd_sess_hop_count(session));
02012bef 230
21bfce98
RZ
231 bfd_sess_set_hop_count(session, 1);
232 changed = true;
02012bef 233 }
21bfce98 234 if (PEER_IS_MULTIHOP(p) && p->ttl != bfd_sess_hop_count(session)) {
259f4236 235 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
236 zlog_debug("%s: TTL %d to %d", __func__,
237 bfd_sess_hop_count(session), p->ttl);
02012bef 238
21bfce98
RZ
239 bfd_sess_set_hop_count(session, p->ttl);
240 changed = true;
02012bef
RZ
241 }
242
21bfce98
RZ
243 /* Update VRF. */
244 if (bfd_sess_vrf_id(session) != p->bgp->vrf_id) {
259f4236 245 if (BGP_DEBUG(bfd, BFD_LIB))
21bfce98
RZ
246 zlog_debug(
247 "%s: VRF %s(%d) to %s(%d)", __func__,
248 bfd_sess_vrf(session), bfd_sess_vrf_id(session),
249 vrf_id_to_name(p->bgp->vrf_id), p->bgp->vrf_id);
250
251 bfd_sess_set_vrf(session, p->bgp->vrf_id);
252 changed = true;
02012bef
RZ
253 }
254
21bfce98
RZ
255 if (changed)
256 bfd_sess_install(session);
c43ed2e4
DS
257}
258
21bfce98
RZ
259/**
260 * Reset BFD configuration data structure to its defaults settings.
c43ed2e4 261 */
21bfce98 262static void bgp_peer_bfd_reset(struct peer *p)
c43ed2e4 263{
21bfce98
RZ
264 /* Set defaults. */
265 p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
266 p->bfd_config->min_rx = BFD_DEF_MIN_RX;
267 p->bfd_config->min_tx = BFD_DEF_MIN_TX;
268 p->bfd_config->cbit = false;
269 p->bfd_config->profile[0] = 0;
c43ed2e4
DS
270}
271
21bfce98 272void bgp_peer_configure_bfd(struct peer *p, bool manual)
c43ed2e4 273{
21bfce98
RZ
274 /* Groups should not call this. */
275 assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
c43ed2e4 276
21bfce98
RZ
277 /* Already configured, skip it. */
278 if (p->bfd_config) {
279 /* If manually active update flag. */
280 if (!p->bfd_config->manual)
281 p->bfd_config->manual = manual;
c43ed2e4 282
d62a17ae 283 return;
21bfce98 284 }
c43ed2e4 285
21bfce98
RZ
286 /* Allocate memory for configuration overrides. */
287 p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
288 p->bfd_config->manual = manual;
c43ed2e4 289
21bfce98
RZ
290 /* Create new session and assign callback. */
291 p->bfd_config->session = bfd_sess_new(bfd_session_status_update, p);
292 bgp_peer_bfd_reset(p);
c43ed2e4 293
21bfce98
RZ
294 /* Configure session with basic BGP peer data. */
295 if (p->su.sa.sa_family == AF_INET)
296 bfd_sess_set_ipv4_addrs(p->bfd_config->session,
297 p->su_local ? &p->su_local->sin.sin_addr
298 : NULL,
299 &p->su.sin.sin_addr);
300 else
301 bfd_sess_set_ipv6_addrs(
302 p->bfd_config->session,
303 p->su_local ? &p->su_local->sin6.sin6_addr : NULL,
304 &p->su.sin6.sin6_addr);
c43ed2e4 305
21bfce98
RZ
306 bfd_sess_set_vrf(p->bfd_config->session, p->bgp->vrf_id);
307 bfd_sess_set_hop_count(p->bfd_config->session,
308 PEER_IS_MULTIHOP(p) ? p->ttl : 1);
c43ed2e4 309
21bfce98
RZ
310 if (p->nexthop.ifp)
311 bfd_sess_set_interface(p->bfd_config->session,
312 p->nexthop.ifp->name);
fe0c4ed7
PG
313}
314
21bfce98 315static void bgp_peer_remove_bfd(struct peer *p)
986aa00f 316{
21bfce98
RZ
317 /* Groups should not call this. */
318 assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
d62a17ae 319
21bfce98
RZ
320 /*
321 * Peer configuration was removed, however we must check if there
322 * is still a group configuration to keep this running.
323 */
324 if (p->group && p->group->conf->bfd_config) {
325 p->bfd_config->manual = false;
326 bgp_peer_bfd_reset(p);
327 bgp_peer_config_apply(p, p->group);
d62a17ae 328 return;
d62a17ae 329 }
c43ed2e4 330
373de4b5
RZ
331 if (p->bfd_config)
332 bfd_sess_free(&p->bfd_config->session);
333
21bfce98 334 XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
c43ed2e4
DS
335}
336
21bfce98 337static void bgp_group_configure_bfd(struct peer *p)
68fe91d6 338{
21bfce98
RZ
339 struct listnode *n;
340 struct peer *pn;
68fe91d6 341
21bfce98
RZ
342 /* Peers should not call this. */
343 assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
68fe91d6 344
21bfce98
RZ
345 /* Already allocated: do nothing. */
346 if (p->bfd_config)
d62a17ae 347 return;
68fe91d6 348
21bfce98 349 p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
7555dc61 350
21bfce98
RZ
351 /* Set defaults. */
352 p->bfd_config->detection_multiplier = BFD_DEF_DETECT_MULT;
353 p->bfd_config->min_rx = BFD_DEF_MIN_RX;
354 p->bfd_config->min_tx = BFD_DEF_MIN_TX;
68fe91d6 355
21bfce98
RZ
356 for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
357 bgp_peer_configure_bfd(pn, false);
68fe91d6 358}
359
21bfce98 360static void bgp_group_remove_bfd(struct peer *p)
c43ed2e4 361{
21bfce98
RZ
362 struct listnode *n;
363 struct peer *pn;
d62a17ae 364
21bfce98
RZ
365 /* Peers should not call this. */
366 assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
d62a17ae 367
21bfce98
RZ
368 /* Already freed: do nothing. */
369 if (p->bfd_config == NULL)
370 return;
137147c6 371
21bfce98
RZ
372 /* Free configuration and point to `NULL`. */
373 XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
2dbe669b 374
21bfce98
RZ
375 /* Now that it is `NULL` recalculate configuration for all peers. */
376 for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn)) {
377 if (pn->bfd_config->manual)
378 bgp_peer_config_apply(pn, NULL);
2dbe669b 379 else
21bfce98 380 bgp_peer_remove_bfd(pn);
d62a17ae 381 }
c43ed2e4
DS
382}
383
21bfce98 384void bgp_peer_remove_bfd_config(struct peer *p)
986aa00f 385{
21bfce98
RZ
386 if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
387 bgp_group_remove_bfd(p);
388 else
389 bgp_peer_remove_bfd(p);
02012bef
RZ
390}
391
c43ed2e4
DS
392/*
393 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
394 */
21bfce98
RZ
395void bgp_bfd_peer_config_write(struct vty *vty, const struct peer *peer,
396 const char *addr)
c43ed2e4 397{
21bfce98
RZ
398 /*
399 * Always show group BFD configuration, but peer only when explicitly
400 * configured.
401 */
402 if ((!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
403 && peer->bfd_config->manual)
404 || CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a0841732
RZ
405#if HAVE_BFDD > 0
406 vty_out(vty, " neighbor %s bfd\n", addr);
407#else
d62a17ae 408 vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
21bfce98
RZ
409 peer->bfd_config->detection_multiplier,
410 peer->bfd_config->min_rx, peer->bfd_config->min_tx);
a0841732 411#endif /* HAVE_BFDD */
02012bef 412 }
dcffea69 413
21bfce98
RZ
414 if (peer->bfd_config->profile[0])
415 vty_out(vty, " neighbor %s bfd profile %s\n", addr,
416 peer->bfd_config->profile);
417
418 if (peer->bfd_config->cbit)
419 vty_out(vty, " neighbor %s bfd check-control-plane-failure\n",
420 addr);
c43ed2e4
DS
421}
422
423/*
424 * bgp_bfd_show_info - Show the peer BFD information.
425 */
21bfce98 426void bgp_bfd_show_info(struct vty *vty, const struct peer *peer,
d62a17ae 427 json_object *json_neigh)
c43ed2e4 428{
83c44422 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
4a0872fc
RZ
451 bgp_peer_config_apply(peer, peer->group);
452
d62a17ae 453 return CMD_SUCCESS;
c43ed2e4
DS
454}
455
64dc4b2d
RZ
456#if HAVE_BFDD > 0
457DEFUN_HIDDEN(
458#else
459DEFUN(
460#endif /* HAVE_BFDD */
461 neighbor_bfd_param,
c43ed2e4 462 neighbor_bfd_param_cmd,
9ccf14f7 463 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
c43ed2e4
DS
464 NEIGHBOR_STR
465 NEIGHBOR_ADDR_STR2
466 "Enables BFD support\n"
467 "Detect Multiplier\n"
468 "Required min receive interval\n"
469 "Desired min transmit interval\n")
470{
d62a17ae 471 int idx_peer = 1;
472 int idx_number_1 = 3;
473 int idx_number_2 = 4;
474 int idx_number_3 = 5;
21bfce98 475 long detection_multiplier, min_rx, min_tx;
d62a17ae 476 struct peer *peer;
d62a17ae 477
478 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
479 if (!peer)
480 return CMD_WARNING_CONFIG_FAILED;
481
21bfce98
RZ
482 detection_multiplier = strtol(argv[idx_number_1]->arg, NULL, 10);
483 min_rx = strtol(argv[idx_number_2]->arg, NULL, 10);
484 min_tx = strtol(argv[idx_number_3]->arg, NULL, 10);
d62a17ae 485
21bfce98
RZ
486 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
487 bgp_group_configure_bfd(peer);
d62a17ae 488 else
21bfce98 489 bgp_peer_configure_bfd(peer, true);
d62a17ae 490
21bfce98
RZ
491 peer->bfd_config->detection_multiplier = detection_multiplier;
492 peer->bfd_config->min_rx = min_rx;
493 peer->bfd_config->min_tx = min_tx;
494 bgp_peer_config_apply(peer, peer->group);
dcffea69 495
dcffea69
PG
496 return CMD_SUCCESS;
497}
498
dcffea69
PG
499DEFUN (neighbor_bfd_check_controlplane_failure,
500 neighbor_bfd_check_controlplane_failure_cmd,
501 "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
502 NO_STR
503 NEIGHBOR_STR
504 NEIGHBOR_ADDR_STR2
505 "BFD support\n"
506 "Link dataplane status with BGP controlplane\n")
507{
508 const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
509 int idx_peer = 0;
510 struct peer *peer;
dcffea69
PG
511
512 if (no)
513 idx_peer = 2;
514 else
515 idx_peer = 1;
516 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
517 if (!peer) {
518 vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
519 return CMD_WARNING_CONFIG_FAILED;
520 }
21bfce98
RZ
521
522 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
523 bgp_group_configure_bfd(peer);
524 else
525 bgp_peer_configure_bfd(peer, true);
526
527 peer->bfd_config->cbit = no == NULL;
528 bgp_peer_config_apply(peer, peer->group);
529
530 return CMD_SUCCESS;
dcffea69
PG
531 }
532
c43ed2e4
DS
533DEFUN (no_neighbor_bfd,
534 no_neighbor_bfd_cmd,
64dc4b2d
RZ
535#if HAVE_BFDD > 0
536 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
537#else
5bf15956 538 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
64dc4b2d 539#endif /* HAVE_BFDD */
c43ed2e4
DS
540 NO_STR
541 NEIGHBOR_STR
542 NEIGHBOR_ADDR_STR2
5bf15956 543 "Disables BFD support\n"
64dc4b2d 544#if HAVE_BFDD == 0
5bf15956
DW
545 "Detect Multiplier\n"
546 "Required min receive interval\n"
64dc4b2d
RZ
547 "Desired min transmit interval\n"
548#endif /* !HAVE_BFDD */
549)
c43ed2e4 550{
d62a17ae 551 int idx_peer = 2;
552 struct peer *peer;
c43ed2e4 553
d62a17ae 554 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
555 if (!peer)
556 return CMD_WARNING_CONFIG_FAILED;
c43ed2e4 557
21bfce98
RZ
558 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
559 bgp_group_remove_bfd(peer);
560 else
561 bgp_peer_remove_bfd(peer);
986aa00f 562
d62a17ae 563 return CMD_SUCCESS;
986aa00f 564}
565
02012bef
RZ
566#if HAVE_BFDD > 0
567DEFUN(neighbor_bfd_profile, neighbor_bfd_profile_cmd,
568 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF",
569 NEIGHBOR_STR
570 NEIGHBOR_ADDR_STR2
571 "BFD integration\n"
572 BFD_PROFILE_STR
573 BFD_PROFILE_NAME_STR)
574{
575 int idx_peer = 1, idx_prof = 4;
576 struct peer *peer;
02012bef
RZ
577
578 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
579 if (!peer)
580 return CMD_WARNING_CONFIG_FAILED;
581
21bfce98
RZ
582 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
583 bgp_group_configure_bfd(peer);
584 else
585 bgp_peer_configure_bfd(peer, true);
586
587 strlcpy(peer->bfd_config->profile, argv[idx_prof]->arg,
588 sizeof(peer->bfd_config->profile));
589 bgp_peer_config_apply(peer, peer->group);
02012bef
RZ
590
591 return CMD_SUCCESS;
592}
593
594DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
595 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]",
596 NO_STR
597 NEIGHBOR_STR
598 NEIGHBOR_ADDR_STR2
599 "BFD integration\n"
600 BFD_PROFILE_STR
601 BFD_PROFILE_NAME_STR)
602{
603 int idx_peer = 2;
604 struct peer *peer;
02012bef
RZ
605
606 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
607 if (!peer)
608 return CMD_WARNING_CONFIG_FAILED;
609
21bfce98
RZ
610 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
611 bgp_group_configure_bfd(peer);
612 else
613 bgp_peer_configure_bfd(peer, true);
02012bef 614
21bfce98
RZ
615 peer->bfd_config->profile[0] = 0;
616 bgp_peer_config_apply(peer, peer->group);
02012bef
RZ
617
618 return CMD_SUCCESS;
619}
620#endif /* HAVE_BFDD */
621
21bfce98 622void bgp_bfd_init(struct thread_master *tm)
c43ed2e4 623{
d62a17ae 624 /* Initialize BFD client functions */
21bfce98 625 bfd_protocol_integration_init(zclient, tm);
d62a17ae 626
627 /* "neighbor bfd" commands. */
628 install_element(BGP_NODE, &neighbor_bfd_cmd);
629 install_element(BGP_NODE, &neighbor_bfd_param_cmd);
dcffea69 630 install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
d62a17ae 631 install_element(BGP_NODE, &no_neighbor_bfd_cmd);
02012bef
RZ
632
633#if HAVE_BFDD > 0
634 install_element(BGP_NODE, &neighbor_bfd_profile_cmd);
635 install_element(BGP_NODE, &no_neighbor_bfd_profile_cmd);
636#endif /* HAVE_BFDD */
c43ed2e4 637}