]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_bfd.c
Merge pull request #11493 from patrasar/pim_reg_stop_fix
[mirror_frr.git] / bgpd / bgp_bfd.c
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 *
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
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"
32 #include "vrf.h"
33 #include "zclient.h"
34 #include "bfd.h"
35 #include "lib/json.h"
36 #include "filter.h"
37
38 #include "bgpd/bgpd.h"
39 #include "bgp_fsm.h"
40 #include "bgpd/bgp_bfd.h"
41 #include "bgpd/bgp_debug.h"
42 #include "bgpd/bgp_vty.h"
43 #include "bgpd/bgp_packet.h"
44
45 DEFINE_MTYPE_STATIC(BGPD, BFD_CONFIG, "BFD configuration data");
46
47 extern struct zclient *zclient;
48
49 static void bfd_session_status_update(struct bfd_session_params *bsp,
50 const struct bfd_session_status *bss,
51 void *arg)
52 {
53 struct peer *peer = arg;
54
55 if (BGP_DEBUG(bfd, BFD_LIB))
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) {
65 if (BGP_DEBUG(bfd, BFD_LIB))
66 zlog_debug(
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;
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
78 BGP_EVENT_ADD(peer, BGP_Stop);
79 }
80
81 if (bss->state == BSS_UP && bss->previous_state != BSS_UP
82 && !peer_established(peer)) {
83 if (!BGP_PEER_START_SUPPRESSED(peer)) {
84 bgp_fsm_nht_update(peer, true);
85 BGP_EVENT_ADD(peer, BGP_Start);
86 }
87 }
88 }
89
90 void bgp_peer_config_apply(struct peer *p, struct peer_group *pg)
91 {
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 }
102
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 }
115
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);
131
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);
136 else
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);
155 }
156
157 void bgp_peer_bfd_update_source(struct peer *p)
158 {
159 struct bfd_session_params *session = p->bfd_config->session;
160 const union sockunion *source;
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))
170 return;
171
172 /* Figure out the correct source to use. */
173 if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
174 source = p->update_source;
175 else
176 source = p->su_local;
177
178 /* Update peer's source/destination addresses. */
179 bfd_sess_addresses(session, &family, &src.v6, &dst.v6);
180 if (family == AF_INET) {
181 if ((source && source->sin.sin_addr.s_addr != src.v4.s_addr)
182 || p->su.sin.sin_addr.s_addr != dst.v4.s_addr) {
183 if (BGP_DEBUG(bfd, BFD_LIB))
184 zlog_debug(
185 "%s: address [%pI4->%pI4] to [%pI4->%pI4]",
186 __func__, &src.v4, &dst.v4,
187 source ? &source->sin.sin_addr
188 : &src.v4,
189 &p->su.sin.sin_addr);
190
191 bfd_sess_set_ipv4_addrs(
192 session, source ? &source->sin.sin_addr : NULL,
193 &p->su.sin.sin_addr);
194 changed = true;
195 }
196 } else {
197 if ((source && memcmp(&source->sin6, &src.v6, sizeof(src.v6)))
198 || memcmp(&p->su.sin6, &dst.v6, sizeof(dst.v6))) {
199 if (BGP_DEBUG(bfd, BFD_LIB))
200 zlog_debug(
201 "%s: address [%pI6->%pI6] to [%pI6->%pI6]",
202 __func__, &src.v6, &dst.v6,
203 source ? &source->sin6.sin6_addr
204 : &src.v6,
205 &p->su.sin6.sin6_addr);
206
207 bfd_sess_set_ipv6_addrs(session,
208 source ? &source->sin6.sin6_addr
209 : NULL,
210 &p->su.sin6.sin6_addr);
211 changed = true;
212 }
213 }
214
215 /* Update interface. */
216 if (p->nexthop.ifp && bfd_sess_interface(session) == NULL) {
217 if (BGP_DEBUG(bfd, BFD_LIB))
218 zlog_debug("%s: interface none to %s", __func__,
219 p->nexthop.ifp->name);
220
221 bfd_sess_set_interface(session, p->nexthop.ifp->name);
222 changed = true;
223 }
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.
232 */
233 if (!PEER_IS_MULTIHOP(p) && bfd_sess_hop_count(session) > 1) {
234 if (BGP_DEBUG(bfd, BFD_LIB))
235 zlog_debug("%s: TTL %d to 1", __func__,
236 bfd_sess_hop_count(session));
237
238 bfd_sess_set_hop_count(session, 1);
239 changed = true;
240 }
241 if (PEER_IS_MULTIHOP(p) && p->ttl != bfd_sess_hop_count(session)) {
242 if (BGP_DEBUG(bfd, BFD_LIB))
243 zlog_debug("%s: TTL %d to %d", __func__,
244 bfd_sess_hop_count(session), p->ttl);
245
246 bfd_sess_set_hop_count(session, p->ttl);
247 changed = true;
248 }
249
250 /* Update VRF. */
251 if (bfd_sess_vrf_id(session) != p->bgp->vrf_id) {
252 if (BGP_DEBUG(bfd, BFD_LIB))
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;
260 }
261
262 if (changed)
263 bfd_sess_install(session);
264 }
265
266 /**
267 * Reset BFD configuration data structure to its defaults settings.
268 */
269 static void bgp_peer_bfd_reset(struct peer *p)
270 {
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;
277 }
278
279 void bgp_peer_configure_bfd(struct peer *p, bool manual)
280 {
281 /* Groups should not call this. */
282 assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
283
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;
289
290 return;
291 }
292
293 /* Allocate memory for configuration overrides. */
294 p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
295 p->bfd_config->manual = manual;
296
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);
300
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);
312
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);
316
317 if (p->nexthop.ifp)
318 bfd_sess_set_interface(p->bfd_config->session,
319 p->nexthop.ifp->name);
320 }
321
322 static void bgp_peer_remove_bfd(struct peer *p)
323 {
324 /* Groups should not call this. */
325 assert(!CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
326
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);
335 return;
336 }
337
338 if (p->bfd_config)
339 bfd_sess_free(&p->bfd_config->session);
340
341 XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
342 }
343
344 static void bgp_group_configure_bfd(struct peer *p)
345 {
346 struct listnode *n;
347 struct peer *pn;
348
349 /* Peers should not call this. */
350 assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
351
352 /* Already allocated: do nothing. */
353 if (p->bfd_config)
354 return;
355
356 p->bfd_config = XCALLOC(MTYPE_BFD_CONFIG, sizeof(*p->bfd_config));
357
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;
362
363 for (ALL_LIST_ELEMENTS_RO(p->group->peer, n, pn))
364 bgp_peer_configure_bfd(pn, false);
365 }
366
367 static void bgp_group_remove_bfd(struct peer *p)
368 {
369 struct listnode *n;
370 struct peer *pn;
371
372 /* Peers should not call this. */
373 assert(CHECK_FLAG(p->sflags, PEER_STATUS_GROUP));
374
375 /* Already freed: do nothing. */
376 if (p->bfd_config == NULL)
377 return;
378
379 /* Free configuration and point to `NULL`. */
380 XFREE(MTYPE_BFD_CONFIG, p->bfd_config);
381
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);
386 else
387 bgp_peer_remove_bfd(pn);
388 }
389 }
390
391 void bgp_peer_remove_bfd_config(struct peer *p)
392 {
393 if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
394 bgp_group_remove_bfd(p);
395 else
396 bgp_peer_remove_bfd(p);
397 }
398
399 /*
400 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
401 */
402 void bgp_bfd_peer_config_write(struct vty *vty, const struct peer *peer,
403 const char *addr)
404 {
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)) {
412 #if HAVE_BFDD > 0
413 vty_out(vty, " neighbor %s bfd\n", addr);
414 #else
415 vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
416 peer->bfd_config->detection_multiplier,
417 peer->bfd_config->min_rx, peer->bfd_config->min_tx);
418 #endif /* HAVE_BFDD */
419 }
420
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);
428 }
429
430 /*
431 * bgp_bfd_show_info - Show the peer BFD information.
432 */
433 void bgp_bfd_show_info(struct vty *vty, const struct peer *peer,
434 json_object *json_neigh)
435 {
436 bfd_sess_show(vty, json_neigh, peer->bfd_config->session);
437 }
438
439 DEFUN (neighbor_bfd,
440 neighbor_bfd_cmd,
441 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
442 NEIGHBOR_STR
443 NEIGHBOR_ADDR_STR2
444 "Enables BFD support\n")
445 {
446 int idx_peer = 1;
447 struct peer *peer;
448
449 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
450 if (!peer)
451 return CMD_WARNING_CONFIG_FAILED;
452
453 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
454 bgp_group_configure_bfd(peer);
455 else
456 bgp_peer_configure_bfd(peer, true);
457
458 bgp_peer_config_apply(peer, peer->group);
459
460 return CMD_SUCCESS;
461 }
462
463 #if HAVE_BFDD > 0
464 DEFUN_HIDDEN(
465 #else
466 DEFUN(
467 #endif /* HAVE_BFDD */
468 neighbor_bfd_param,
469 neighbor_bfd_param_cmd,
470 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
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 {
478 int idx_peer = 1;
479 int idx_number_1 = 3;
480 int idx_number_2 = 4;
481 int idx_number_3 = 5;
482 long detection_multiplier, min_rx, min_tx;
483 struct peer *peer;
484
485 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
486 if (!peer)
487 return CMD_WARNING_CONFIG_FAILED;
488
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);
492
493 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
494 bgp_group_configure_bfd(peer);
495 else
496 bgp_peer_configure_bfd(peer, true);
497
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);
502
503 return CMD_SUCCESS;
504 }
505
506 DEFUN (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;
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 }
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;
538 }
539
540 DEFUN (no_neighbor_bfd,
541 no_neighbor_bfd_cmd,
542 #if HAVE_BFDD > 0
543 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
544 #else
545 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
546 #endif /* HAVE_BFDD */
547 NO_STR
548 NEIGHBOR_STR
549 NEIGHBOR_ADDR_STR2
550 "Disables BFD support\n"
551 #if HAVE_BFDD == 0
552 "Detect Multiplier\n"
553 "Required min receive interval\n"
554 "Desired min transmit interval\n"
555 #endif /* !HAVE_BFDD */
556 )
557 {
558 int idx_peer = 2;
559 struct peer *peer;
560
561 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
562 if (!peer)
563 return CMD_WARNING_CONFIG_FAILED;
564
565 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
566 bgp_group_remove_bfd(peer);
567 else
568 bgp_peer_remove_bfd(peer);
569
570 return CMD_SUCCESS;
571 }
572
573 #if HAVE_BFDD > 0
574 DEFUN(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;
584
585 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
586 if (!peer)
587 return CMD_WARNING_CONFIG_FAILED;
588
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);
597
598 return CMD_SUCCESS;
599 }
600
601 DEFUN(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;
612
613 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
614 if (!peer)
615 return CMD_WARNING_CONFIG_FAILED;
616
617 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
618 bgp_group_configure_bfd(peer);
619 else
620 bgp_peer_configure_bfd(peer, true);
621
622 peer->bfd_config->profile[0] = 0;
623 bgp_peer_config_apply(peer, peer->group);
624
625 return CMD_SUCCESS;
626 }
627 #endif /* HAVE_BFDD */
628
629 void bgp_bfd_init(struct thread_master *tm)
630 {
631 /* Initialize BFD client functions */
632 bfd_protocol_integration_init(zclient, tm);
633
634 /* "neighbor bfd" commands. */
635 install_element(BGP_NODE, &neighbor_bfd_cmd);
636 install_element(BGP_NODE, &neighbor_bfd_param_cmd);
637 install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd);
638 install_element(BGP_NODE, &no_neighbor_bfd_cmd);
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 */
644 }