2 * bgp_bfd.c: BGP BFD handling routines
4 * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
6 * This file is part of GNU Zebra.
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
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.
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
37 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_bfd.h"
40 #include "bgpd/bgp_debug.h"
41 #include "bgpd/bgp_vty.h"
43 extern struct zclient
*zclient
;
46 * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group
50 void bgp_bfd_peer_group2peer_copy(struct peer
*conf
, struct peer
*peer
)
52 struct bfd_info
*bfd_info
;
53 struct bfd_info
*conf_bfd_info
;
58 conf_bfd_info
= (struct bfd_info
*)conf
->bfd_info
;
60 peer
->bfd_info
= bfd_info_create();
62 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
64 /* Copy BFD parameter values */
65 bfd_info
->required_min_rx
= conf_bfd_info
->required_min_rx
;
66 bfd_info
->desired_min_tx
= conf_bfd_info
->desired_min_tx
;
67 bfd_info
->detect_mult
= conf_bfd_info
->detect_mult
;
68 bfd_info
->type
= conf_bfd_info
->type
;
72 * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single
75 bool bgp_bfd_is_peer_multihop(struct peer
*peer
)
77 struct bfd_info
*bfd_info
;
79 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
84 if ((bfd_info
->type
== BFD_TYPE_MULTIHOP
)
85 || ((peer
->sort
== BGP_PEER_IBGP
) && !peer
->shared_network
)
86 || is_ebgp_multihop_configured(peer
))
93 * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
94 * command to Zebra to be forwarded to BFD
96 static void bgp_bfd_peer_sendmsg(struct peer
*peer
, int command
)
98 struct bfd_session_arg arg
= {};
99 struct bfd_info
*bfd_info
;
105 * XXX: some pointers are dangling during shutdown, so instead of
106 * trying to send a message during signal handlers lets just wait BGP
107 * to terminate zebra's connection and BFD will automatically find
108 * out that we are no longer expecting notifications.
110 * The pointer that is causing a crash here is `peer->nexthop.ifp`.
111 * That happens because at this point of the shutdown all interfaces are
117 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
119 vrf_id
= peer
->bgp
->vrf_id
;
121 if (command
== ZEBRA_BFD_DEST_DEREGISTER
) {
123 CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_TYPE_MULTIHOP
);
124 UNSET_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_TYPE_MULTIHOP
);
126 multihop
= bgp_bfd_is_peer_multihop(peer
);
127 if ((command
== ZEBRA_BFD_DEST_REGISTER
) && multihop
)
128 SET_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_TYPE_MULTIHOP
);
130 /* while graceful restart with fwd path preserved
131 * and bfd controlplane check not configured is not kept
132 * keep bfd independent controlplane bit set to 1
134 if (!CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_GRACEFUL_RESTART
)
135 && !CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_GR_PRESERVE_FWD
)
136 && !CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
))
137 SET_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CBIT_ON
);
139 /* Set all message arguments. */
140 arg
.family
= peer
->su
.sa
.sa_family
;
141 addrlen
= arg
.family
== AF_INET
? sizeof(struct in_addr
)
142 : sizeof(struct in6_addr
);
144 if (arg
.family
== AF_INET
)
145 memcpy(&arg
.dst
, &peer
->su
.sin
.sin_addr
, addrlen
);
147 memcpy(&arg
.dst
, &peer
->su
.sin6
.sin6_addr
, addrlen
);
149 if (peer
->su_local
) {
150 if (arg
.family
== AF_INET
)
151 memcpy(&arg
.src
, &peer
->su_local
->sin
.sin_addr
,
154 memcpy(&arg
.src
, &peer
->su_local
->sin6
.sin6_addr
,
158 if (peer
->nexthop
.ifp
) {
159 arg
.ifnamelen
= strlen(peer
->nexthop
.ifp
->name
);
160 strlcpy(arg
.ifname
, peer
->nexthop
.ifp
->name
,
164 if (bfd_info
->profile
[0]) {
165 arg
.profilelen
= strlen(bfd_info
->profile
);
166 strlcpy(arg
.profile
, bfd_info
->profile
, sizeof(arg
.profile
));
173 arg
.command
= command
;
174 arg
.bfd_info
= bfd_info
;
175 arg
.min_tx
= bfd_info
->desired_min_tx
;
176 arg
.min_rx
= bfd_info
->required_min_rx
;
177 arg
.detection_multiplier
= bfd_info
->detect_mult
;
178 arg
.cbit
= CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CBIT_ON
);
181 zclient_bfd_command(zclient
, &arg
);
185 * bgp_bfd_register_peer - register a peer with BFD through zebra
186 * for monitoring the peer rechahability.
188 void bgp_bfd_register_peer(struct peer
*peer
)
190 struct bfd_info
*bfd_info
;
194 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
196 /* Check if BFD is enabled and peer has already been registered with BFD
198 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
201 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
205 * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra
206 * for stopping the monitoring of the peer
209 void bgp_bfd_deregister_peer(struct peer
*peer
)
211 struct bfd_info
*bfd_info
;
215 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
217 /* Check if BFD is eanbled and peer has not been registered */
218 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
221 bfd_info
->status
= BFD_STATUS_DOWN
;
222 bfd_info
->last_update
= bgp_clock();
224 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_DEREGISTER
);
228 * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
231 static void bgp_bfd_update_peer(struct peer
*peer
)
233 struct bfd_info
*bfd_info
;
237 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
239 /* Check if the peer has been registered with BFD*/
240 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
243 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_UPDATE
);
247 * bgp_bfd_reset_peer - reinitialise bfd
248 * ensures that bfd state machine is restarted
249 * to be synced with remote bfd
251 void bgp_bfd_reset_peer(struct peer
*peer
)
256 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
260 * bgp_bfd_update_type - update session type with BFD through zebra.
262 static void bgp_bfd_update_type(struct peer
*peer
)
264 struct bfd_info
*bfd_info
;
269 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
271 /* Check if the peer has been registered with BFD*/
272 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
275 if (bfd_info
->type
== BFD_TYPE_NOT_CONFIGURED
) {
276 multihop
= bgp_bfd_is_peer_multihop(peer
);
278 && !CHECK_FLAG(bfd_info
->flags
,
279 BFD_FLAG_BFD_TYPE_MULTIHOP
))
280 || (!multihop
&& CHECK_FLAG(bfd_info
->flags
,
281 BFD_FLAG_BFD_TYPE_MULTIHOP
))) {
282 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_DEREGISTER
);
283 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
286 if ((bfd_info
->type
== BFD_TYPE_MULTIHOP
287 && !CHECK_FLAG(bfd_info
->flags
,
288 BFD_FLAG_BFD_TYPE_MULTIHOP
))
289 || (bfd_info
->type
== BFD_TYPE_SINGLEHOP
290 && CHECK_FLAG(bfd_info
->flags
,
291 BFD_FLAG_BFD_TYPE_MULTIHOP
))) {
292 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_DEREGISTER
);
293 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
299 * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
302 static int bgp_bfd_dest_replay(ZAPI_CALLBACK_ARGS
)
304 struct listnode
*mnode
, *node
, *nnode
;
308 if (BGP_DEBUG(zebra
, ZEBRA
))
309 zlog_debug("Zebra: BFD Dest replay request");
311 /* Send the client registration */
312 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, vrf_id
);
314 /* Replay the peer, if BFD is enabled in BGP */
316 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, mnode
, bgp
))
317 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
318 bgp_bfd_update_peer(peer
);
325 * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
326 * down the peer if the BFD session went down from
329 static void bgp_bfd_peer_status_update(struct peer
*peer
, int status
,
332 struct bfd_info
*bfd_info
;
335 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
337 if (bfd_info
->status
== status
)
340 old_status
= bfd_info
->status
;
341 BFD_SET_CLIENT_STATUS(bfd_info
->status
, status
);
343 bfd_info
->last_update
= bgp_clock();
345 if (status
!= old_status
) {
346 if (BGP_DEBUG(neighbor_events
, NEIGHBOR_EVENTS
))
347 zlog_debug("[%s]: BFD %s", peer
->host
,
348 bfd_get_status_str(status
));
350 if ((status
== BFD_STATUS_DOWN
) && (old_status
== BFD_STATUS_UP
)) {
351 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_MODE
) &&
352 CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
) &&
354 zlog_info("%s BFD DOWN message ignored in the process of graceful restart when C bit is cleared",
358 peer
->last_reset
= PEER_DOWN_BFD_DOWN
;
359 BGP_EVENT_ADD(peer
, BGP_Stop
);
361 if ((status
== BFD_STATUS_UP
) && (old_status
== BFD_STATUS_DOWN
)
362 && peer
->status
!= Established
) {
363 if (!BGP_PEER_START_SUPPRESSED(peer
)) {
364 bgp_fsm_nht_update(peer
, true);
365 BGP_EVENT_ADD(peer
, BGP_Start
);
371 * bgp_bfd_dest_update - Find the peer for which the BFD status
372 * has changed and bring down the peer
373 * connectivity if the BFD session went down.
375 static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS
)
377 struct interface
*ifp
;
383 ifp
= bfd_get_peer_info(zclient
->ibuf
, &dp
, &sp
, &status
,
384 &remote_cbit
, vrf_id
);
386 if (BGP_DEBUG(zebra
, ZEBRA
)) {
389 vrf
= vrf_lookup_by_id(vrf_id
);
393 "Zebra: vrf %s(%u) interface %s bfd destination %pFX %s %s",
394 VRF_LOGNAME(vrf
), vrf_id
, ifp
->name
, &dp
,
395 bfd_get_status_str(status
),
396 remote_cbit
? "(cbit on)" : "");
399 "Zebra: vrf %s(%u) source %pFX bfd destination %pFX %s %s",
400 VRF_LOGNAME(vrf
), vrf_id
, &sp
, &dp
,
401 bfd_get_status_str(status
),
402 remote_cbit
? "(cbit on)" : "");
405 /* Bring the peer down if BFD is enabled in BGP */
407 struct listnode
*mnode
, *node
, *nnode
;
411 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, mnode
, bgp
))
412 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
416 if ((dp
.family
== AF_INET
)
417 && (peer
->su
.sa
.sa_family
== AF_INET
)) {
418 if (dp
.u
.prefix4
.s_addr
419 != peer
->su
.sin
.sin_addr
.s_addr
)
421 } else if ((dp
.family
== AF_INET6
)
422 && (peer
->su
.sa
.sa_family
424 if (memcmp(&dp
.u
.prefix6
,
425 &peer
->su
.sin6
.sin6_addr
,
426 sizeof(struct in6_addr
)))
431 if (ifp
&& (ifp
== peer
->nexthop
.ifp
)) {
432 bgp_bfd_peer_status_update(peer
,
439 if ((sp
.family
== AF_INET
)
440 && (peer
->su_local
->sa
.sa_family
442 if (sp
.u
.prefix4
.s_addr
443 != peer
->su_local
->sin
446 } else if ((sp
.family
== AF_INET6
)
447 && (peer
->su_local
->sa
450 if (memcmp(&sp
.u
.prefix6
,
451 &peer
->su_local
->sin6
459 if ((vrf_id
!= VRF_DEFAULT
)
460 && (peer
->bgp
->vrf_id
!= vrf_id
))
463 bgp_bfd_peer_status_update(peer
,
474 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
476 static int bgp_bfd_peer_param_set(struct peer
*peer
, uint32_t min_rx
,
477 uint32_t min_tx
, uint8_t detect_mult
,
481 struct peer_group
*group
;
482 struct listnode
*node
, *nnode
;
485 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
), min_rx
, min_tx
,
486 detect_mult
, NULL
, defaults
, &command
);
488 /* This command overrides profile if it was previously applied. */
492 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
494 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
)) {
496 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
),
497 min_rx
, min_tx
, detect_mult
, NULL
,
501 * This command overrides profile if it was previously
507 if ((peer
->status
== Established
)
508 && (command
== ZEBRA_BFD_DEST_REGISTER
))
509 bgp_bfd_register_peer(peer
);
510 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
511 bgp_bfd_update_peer(peer
);
514 if ((peer
->status
== Established
)
515 && (command
== ZEBRA_BFD_DEST_REGISTER
))
516 bgp_bfd_register_peer(peer
);
517 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
518 bgp_bfd_update_peer(peer
);
524 * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for
527 static int bgp_bfd_peer_param_unset(struct peer
*peer
)
529 struct peer_group
*group
;
530 struct listnode
*node
, *nnode
;
535 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
536 bfd_info_free(&(peer
->bfd_info
));
538 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
)) {
539 bgp_bfd_deregister_peer(peer
);
540 bfd_info_free(&(peer
->bfd_info
));
543 bgp_bfd_deregister_peer(peer
);
544 bfd_info_free(&(peer
->bfd_info
));
550 * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or
553 static int bgp_bfd_peer_param_type_set(struct peer
*peer
,
554 enum bfd_sess_type type
)
556 struct peer_group
*group
;
557 struct listnode
*node
, *nnode
;
559 struct bfd_info
*bfd_info
;
562 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
),
563 BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
564 BFD_DEF_DETECT_MULT
, NULL
, 1, &command
);
566 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
567 bfd_info
->type
= type
;
569 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
571 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
)) {
575 (struct bfd_info
**)&(peer
->bfd_info
),
576 BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
577 BFD_DEF_DETECT_MULT
, NULL
, 1, &command
);
579 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
580 bfd_info
->type
= type
;
582 if (peer
->status
== Established
) {
583 if (command
== ZEBRA_BFD_DEST_REGISTER
)
584 bgp_bfd_register_peer(peer
);
586 bgp_bfd_update_type(peer
);
590 if (peer
->status
== Established
) {
591 if (command
== ZEBRA_BFD_DEST_REGISTER
)
592 bgp_bfd_register_peer(peer
);
594 bgp_bfd_update_type(peer
);
603 * Set peer BFD profile configuration.
605 static int bgp_bfd_peer_set_profile(struct peer
*peer
, const char *profile
)
607 struct peer_group
*group
;
608 struct listnode
*node
, *nnode
;
610 struct bfd_info
*bfd_info
;
612 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
), BFD_DEF_MIN_RX
,
613 BFD_DEF_MIN_TX
, BFD_DEF_DETECT_MULT
, NULL
, 1, &command
);
615 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
617 /* If profile was specified, then copy string. */
619 strlcpy(bfd_info
->profile
, profile
, sizeof(bfd_info
->profile
));
620 else /* Otherwise just initialize it empty. */
621 bfd_info
->profile
[0] = 0;
623 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
625 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
)) {
627 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
),
628 BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
629 BFD_DEF_DETECT_MULT
, NULL
, 1, &command
);
631 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
633 /* If profile was specified, then copy string. */
635 strlcpy(bfd_info
->profile
, profile
,
636 sizeof(bfd_info
->profile
));
637 else /* Otherwise just initialize it empty. */
638 bfd_info
->profile
[0] = 0;
640 if (peer
->status
== Established
641 && command
== ZEBRA_BFD_DEST_REGISTER
)
642 bgp_bfd_register_peer(peer
);
643 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
644 bgp_bfd_update_peer(peer
);
647 if (peer
->status
== Established
648 && command
== ZEBRA_BFD_DEST_REGISTER
)
649 bgp_bfd_register_peer(peer
);
650 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
651 bgp_bfd_update_peer(peer
);
659 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
661 void bgp_bfd_peer_config_write(struct vty
*vty
, struct peer
*peer
, char *addr
)
663 struct bfd_info
*bfd_info
;
668 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
670 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
672 vty_out(vty
, " neighbor %s bfd\n", addr
);
674 vty_out(vty
, " neighbor %s bfd %d %d %d\n", addr
,
675 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
676 bfd_info
->desired_min_tx
);
677 #endif /* HAVE_BFDD */
679 if (bfd_info
->type
!= BFD_TYPE_NOT_CONFIGURED
)
680 vty_out(vty
, " neighbor %s bfd %s\n", addr
,
681 (bfd_info
->type
== BFD_TYPE_MULTIHOP
) ? "multihop"
684 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
)
685 && (bfd_info
->type
== BFD_TYPE_NOT_CONFIGURED
)) {
686 vty_out(vty
, " neighbor %s bfd", addr
);
687 if (bfd_info
->profile
[0])
688 vty_out(vty
, " profile %s", bfd_info
->profile
);
692 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
))
693 vty_out(vty
, " neighbor %s bfd check-control-plane-failure\n", addr
);
697 * bgp_bfd_show_info - Show the peer BFD information.
699 void bgp_bfd_show_info(struct vty
*vty
, struct peer
*peer
, bool use_json
,
700 json_object
*json_neigh
)
702 bfd_show_info(vty
, (struct bfd_info
*)peer
->bfd_info
,
703 bgp_bfd_is_peer_multihop(peer
), 0, use_json
, json_neigh
);
708 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
711 "Enables BFD support\n")
717 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
719 return CMD_WARNING_CONFIG_FAILED
;
721 ret
= bgp_bfd_peer_param_set(peer
, BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
722 BFD_DEF_DETECT_MULT
, 1);
724 return bgp_vty_return(vty
, ret
);
733 #endif /* HAVE_BFDD */
735 neighbor_bfd_param_cmd
,
736 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
739 "Enables BFD support\n"
740 "Detect Multiplier\n"
741 "Required min receive interval\n"
742 "Desired min transmit interval\n")
745 int idx_number_1
= 3;
746 int idx_number_2
= 4;
747 int idx_number_3
= 5;
754 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
756 return CMD_WARNING_CONFIG_FAILED
;
758 if ((ret
= bfd_validate_param(
759 vty
, argv
[idx_number_1
]->arg
, argv
[idx_number_2
]->arg
,
760 argv
[idx_number_3
]->arg
, &dm_val
, &rx_val
, &tx_val
))
764 ret
= bgp_bfd_peer_param_set(peer
, rx_val
, tx_val
, dm_val
, 0);
766 return bgp_vty_return(vty
, ret
);
771 DEFUN_HIDDEN (neighbor_bfd_type
,
772 neighbor_bfd_type_cmd
,
773 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>",
776 "Enables BFD support\n"
778 "Single hop session\n")
783 enum bfd_sess_type type
;
786 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
788 return CMD_WARNING_CONFIG_FAILED
;
790 if (strmatch(argv
[idx_hop
]->text
, "singlehop"))
791 type
= BFD_TYPE_SINGLEHOP
;
792 else if (strmatch(argv
[idx_hop
]->text
, "multihop"))
793 type
= BFD_TYPE_MULTIHOP
;
795 return CMD_WARNING_CONFIG_FAILED
;
797 ret
= bgp_bfd_peer_param_type_set(peer
, type
);
799 return bgp_vty_return(vty
, ret
);
804 static int bgp_bfd_set_check_controlplane_failure_peer(struct vty
*vty
, struct peer
*peer
,
807 struct bfd_info
*bfd_info
;
809 if (!peer
->bfd_info
) {
812 vty_out(vty
, "%% Specify bfd command first\n");
813 return CMD_WARNING_CONFIG_FAILED
;
815 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
817 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
)) {
818 SET_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
);
819 bgp_bfd_update_peer(peer
);
822 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
)) {
823 UNSET_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CHECK_CONTROLPLANE
);
824 bgp_bfd_update_peer(peer
);
831 DEFUN (neighbor_bfd_check_controlplane_failure
,
832 neighbor_bfd_check_controlplane_failure_cmd
,
833 "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure",
838 "Link dataplane status with BGP controlplane\n")
840 const char *no
= strmatch(argv
[0]->text
, "no") ? "no" : NULL
;
843 struct peer_group
*group
;
844 struct listnode
*node
, *nnode
;
845 int ret
= CMD_SUCCESS
;
851 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
853 vty_out(vty
, "%% Specify remote-as or peer-group commands first\n");
854 return CMD_WARNING_CONFIG_FAILED
;
856 if (!peer
->bfd_info
) {
859 vty_out(vty
, "%% Specify bfd command first\n");
860 return CMD_WARNING_CONFIG_FAILED
;
862 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_GROUP
)) {
864 for (ALL_LIST_ELEMENTS(group
->peer
, node
, nnode
, peer
))
865 ret
= bgp_bfd_set_check_controlplane_failure_peer(vty
, peer
, no
);
867 ret
= bgp_bfd_set_check_controlplane_failure_peer(vty
, peer
, no
);
871 DEFUN (no_neighbor_bfd
,
874 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
876 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
877 #endif /* HAVE_BFDD */
881 "Disables BFD support\n"
883 "Detect Multiplier\n"
884 "Required min receive interval\n"
885 "Desired min transmit interval\n"
886 #endif /* !HAVE_BFDD */
893 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
895 return CMD_WARNING_CONFIG_FAILED
;
897 ret
= bgp_bfd_peer_param_unset(peer
);
899 return bgp_vty_return(vty
, ret
);
905 DEFUN_HIDDEN (no_neighbor_bfd_type
,
906 no_neighbor_bfd_type_cmd
,
907 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>",
911 "Disables BFD support\n"
913 "Singlehop session\n")
919 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
921 return CMD_WARNING_CONFIG_FAILED
;
926 ret
= bgp_bfd_peer_param_type_set(peer
, BFD_TYPE_NOT_CONFIGURED
);
928 return bgp_vty_return(vty
, ret
);
934 DEFUN(neighbor_bfd_profile
, neighbor_bfd_profile_cmd
,
935 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF",
940 BFD_PROFILE_NAME_STR
)
942 int idx_peer
= 1, idx_prof
= 4;
946 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
948 return CMD_WARNING_CONFIG_FAILED
;
950 ret
= bgp_bfd_peer_set_profile(peer
, argv
[idx_prof
]->arg
);
952 return bgp_vty_return(vty
, ret
);
957 DEFUN(no_neighbor_bfd_profile
, no_neighbor_bfd_profile_cmd
,
958 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile [BFDPROF]",
964 BFD_PROFILE_NAME_STR
)
970 peer
= peer_and_group_lookup_vty(vty
, argv
[idx_peer
]->arg
);
972 return CMD_WARNING_CONFIG_FAILED
;
977 ret
= bgp_bfd_peer_set_profile(peer
, NULL
);
979 return bgp_vty_return(vty
, ret
);
983 #endif /* HAVE_BFDD */
985 void bgp_bfd_init(void)
989 /* Initialize BFD client functions */
990 zclient
->interface_bfd_dest_update
= bgp_bfd_dest_update
;
991 zclient
->bfd_dest_replay
= bgp_bfd_dest_replay
;
993 /* "neighbor bfd" commands. */
994 install_element(BGP_NODE
, &neighbor_bfd_cmd
);
995 install_element(BGP_NODE
, &neighbor_bfd_param_cmd
);
996 install_element(BGP_NODE
, &neighbor_bfd_type_cmd
);
997 install_element(BGP_NODE
, &neighbor_bfd_check_controlplane_failure_cmd
);
998 install_element(BGP_NODE
, &no_neighbor_bfd_cmd
);
999 install_element(BGP_NODE
, &no_neighbor_bfd_type_cmd
);
1002 install_element(BGP_NODE
, &neighbor_bfd_profile_cmd
);
1003 install_element(BGP_NODE
, &no_neighbor_bfd_profile_cmd
);
1004 #endif /* HAVE_BFDD */