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