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
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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 template
50 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
;
71 * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop.
74 bgp_bfd_is_peer_multihop(struct peer
*peer
)
76 if((peer
->sort
== BGP_PEER_IBGP
) || is_ebgp_multihop_configured(peer
))
83 * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
84 * command to Zebra to be forwarded to BFD
87 bgp_bfd_peer_sendmsg (struct peer
*peer
, int command
)
89 struct bfd_info
*bfd_info
;
91 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
93 if (peer
->su
.sa
.sa_family
== AF_INET
)
94 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET
,
95 &peer
->su
.sin
.sin_addr
,
96 (peer
->su_local
) ? &peer
->su_local
->sin
.sin_addr
: NULL
,
97 (peer
->nexthop
.ifp
) ? peer
->nexthop
.ifp
->name
: NULL
,
98 peer
->ttl
, bgp_bfd_is_peer_multihop(peer
), command
, 1);
99 else if (peer
->su
.sa
.sa_family
== AF_INET6
)
100 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET6
,
101 &peer
->su
.sin6
.sin6_addr
,
102 (peer
->su_local
) ? &peer
->su_local
->sin6
.sin6_addr
: NULL
,
103 (peer
->nexthop
.ifp
) ? peer
->nexthop
.ifp
->name
: NULL
,
104 peer
->ttl
, bgp_bfd_is_peer_multihop(peer
), command
, 1);
108 * bgp_bfd_register_peer - register a peer with BFD through zebra
109 * for monitoring the peer rechahability.
112 bgp_bfd_register_peer (struct peer
*peer
)
114 struct bfd_info
*bfd_info
;
118 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
120 /* Check if BFD is enabled and peer has already been registered with BFD */
121 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
124 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
128 * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra
129 * for stopping the monitoring of the peer
133 bgp_bfd_deregister_peer (struct peer
*peer
)
135 struct bfd_info
*bfd_info
;
139 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
141 /* Check if BFD is eanbled and peer has not been registered */
142 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
145 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_DEREGISTER
);
149 * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
153 bgp_bfd_update_peer (struct peer
*peer
)
155 struct bfd_info
*bfd_info
;
159 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
161 /* Check if the peer has been registered with BFD*/
162 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
165 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_UPDATE
);
169 * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
173 bgp_bfd_dest_replay (int command
, struct zclient
*client
, zebra_size_t length
)
175 struct listnode
*mnode
, *node
, *nnode
;
179 if (BGP_DEBUG (zebra
, ZEBRA
))
180 zlog_debug("Zebra: BFD Dest replay request");
182 /* Replay the peer, if BFD is enabled in BGP */
184 for (ALL_LIST_ELEMENTS_RO (bm
->bgp
, mnode
, bgp
))
185 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
187 bgp_bfd_update_peer(peer
);
194 * bgp_interface_bfd_dest_down - Find the peer for which the BFD status
195 * has changed and bring down the peer
199 bgp_interface_bfd_dest_down (int command
, struct zclient
*zclient
,
202 struct interface
*ifp
;
206 ifp
= bfd_get_peer_info (zclient
->ibuf
, &dp
, &sp
);
208 if (BGP_DEBUG (zebra
, ZEBRA
))
211 prefix2str(&dp
, buf
[0], sizeof(buf
[0]));
214 zlog_debug("Zebra: interface %s bfd destination %s down",
219 prefix2str(&sp
, buf
[1], sizeof(buf
[1]));
220 zlog_debug("Zebra: source %s bfd destination %s down",
225 /* Bring the peer down if BFD is enabled in BGP */
227 struct listnode
*mnode
, *node
, *nnode
;
231 for (ALL_LIST_ELEMENTS_RO (bm
->bgp
, mnode
, bgp
))
232 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
237 if ((dp
.family
== AF_INET
) && (peer
->su
.sa
.sa_family
== AF_INET
))
239 if (dp
.u
.prefix4
.s_addr
!= peer
->su
.sin
.sin_addr
.s_addr
)
243 else if ((dp
.family
== AF_INET6
) &&
244 (peer
->su
.sa
.sa_family
== AF_INET6
))
246 if (memcmp(&dp
.u
.prefix6
, &peer
->su
.sin6
.sin6_addr
,
247 sizeof (struct in6_addr
)))
254 if (ifp
&& (ifp
== peer
->nexthop
.ifp
))
256 peer
->last_reset
= PEER_DOWN_BFD_DOWN
;
257 BGP_EVENT_ADD (peer
, BGP_Stop
);
264 if ((sp
.family
== AF_INET
) &&
265 (peer
->su_local
->sa
.sa_family
== AF_INET
))
267 if (sp
.u
.prefix4
.s_addr
!= peer
->su_local
->sin
.sin_addr
.s_addr
)
271 else if ((sp
.family
== AF_INET6
) &&
272 (peer
->su_local
->sa
.sa_family
== AF_INET6
))
274 if (memcmp(&sp
.u
.prefix6
, &peer
->su_local
->sin6
.sin6_addr
,
275 sizeof (struct in6_addr
)))
282 peer
->last_reset
= PEER_DOWN_BFD_DOWN
;
283 BGP_EVENT_ADD (peer
, BGP_Stop
);
292 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
295 bgp_bfd_peer_param_set (struct peer
*peer
, u_int32_t min_rx
, u_int32_t min_tx
,
296 u_int8_t detect_mult
, int defaults
)
298 struct peer_group
*group
;
299 struct listnode
*node
, *nnode
;
302 bfd_set_param(&(peer
->bfd_info
), min_rx
, min_tx
, detect_mult
,
305 if (CHECK_FLAG (peer
->sflags
, PEER_STATUS_GROUP
))
308 for (ALL_LIST_ELEMENTS (group
->peer
, node
, nnode
, peer
))
311 bfd_set_param(&(peer
->bfd_info
), min_rx
, min_tx
, detect_mult
,
314 if ((peer
->status
== Established
) &&
315 (command
== ZEBRA_BFD_DEST_REGISTER
))
316 bgp_bfd_register_peer(peer
);
317 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
318 bgp_bfd_update_peer(peer
);
323 if ((peer
->status
== Established
) &&
324 (command
== ZEBRA_BFD_DEST_REGISTER
))
325 bgp_bfd_register_peer(peer
);
326 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
327 bgp_bfd_update_peer(peer
);
333 * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
336 bgp_bfd_peer_param_unset (struct peer
*peer
)
338 struct peer_group
*group
;
339 struct listnode
*node
, *nnode
;
344 if (CHECK_FLAG (peer
->sflags
, PEER_STATUS_GROUP
))
346 bfd_info_free(&(peer
->bfd_info
));
348 for (ALL_LIST_ELEMENTS (group
->peer
, node
, nnode
, peer
))
350 bgp_bfd_deregister_peer(peer
);
351 bfd_info_free(&(peer
->bfd_info
));
356 bgp_bfd_deregister_peer(peer
);
357 bfd_info_free(&(peer
->bfd_info
));
363 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
366 bgp_bfd_peer_config_write(struct vty
*vty
, struct peer
*peer
, char *addr
)
368 struct bfd_info
*bfd_info
;
373 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
375 if (CHECK_FLAG (bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
376 vty_out (vty
, " neighbor %s bfd %d %d %d%s", addr
,
377 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
378 bfd_info
->desired_min_tx
, VTY_NEWLINE
);
380 vty_out (vty
, " neighbor %s bfd%s", addr
, VTY_NEWLINE
);
384 * bgp_bfd_show_info - Show the peer BFD information.
387 bgp_bfd_show_info(struct vty
*vty
, struct peer
*peer
, u_char use_json
, json_object
*json_neigh
)
389 struct bfd_info
*bfd_info
;
390 json_object
*json_bfd
= NULL
;
396 json_bfd
= json_object_new_object();
398 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
402 if (bgp_bfd_is_peer_multihop(peer
))
403 json_object_string_add(json_bfd
, "bfdMultiHop", "yes");
405 json_object_string_add(json_bfd
, "bfdMultiHop", "no");
406 json_object_int_add(json_bfd
, "detectMultiplier", bfd_info
->detect_mult
);
407 json_object_int_add(json_bfd
, "rxMinInterval", bfd_info
->required_min_rx
);
408 json_object_int_add(json_bfd
, "txMinInterval", bfd_info
->desired_min_tx
);
409 json_object_object_add(json_neigh
, "peerBfdInfo", json_bfd
);
413 vty_out (vty
, " BFD: Multi-hop: %s%s",
414 (bgp_bfd_is_peer_multihop(peer
)) ? "yes" : "no", VTY_NEWLINE
);
415 vty_out (vty
, " Detect Mul: %d, Min Rx interval: %d,"
416 " Min Tx interval: %d%s",
417 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
418 bfd_info
->desired_min_tx
, VTY_NEWLINE
);
419 vty_out (vty
, "%s", VTY_NEWLINE
);
428 "Enables BFD support\n")
433 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
437 ret
= bgp_bfd_peer_param_set (peer
, BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
438 BFD_DEF_DETECT_MULT
, 1);
440 return bgp_vty_return (vty
, ret
);
446 DEFUN (neighbor_bfd_param
,
447 neighbor_bfd_param_cmd
,
448 NEIGHBOR_CMD2
"bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE
,
451 "Enables BFD support\n"
452 "Detect Multiplier\n"
453 "Required min receive interval\n"
454 "Desired min transmit interval\n")
462 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
466 if ((ret
= bfd_validate_param (vty
, argv
[1], argv
[2], argv
[3], &dm_val
,
467 &rx_val
, &tx_val
)) != CMD_SUCCESS
)
470 ret
= bgp_bfd_peer_param_set (peer
, rx_val
, tx_val
, dm_val
, 0);
472 return bgp_vty_return (vty
, ret
);
478 DEFUN (no_neighbor_bfd
,
480 NO_NEIGHBOR_CMD2
"bfd",
484 "Disables BFD support\n")
489 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
493 ret
= bgp_bfd_peer_param_unset(peer
);
495 return bgp_vty_return (vty
, ret
);
503 /* Initialize BFD client functions */
504 zclient
->interface_bfd_dest_down
= bgp_interface_bfd_dest_down
;
505 zclient
->bfd_dest_replay
= bgp_bfd_dest_replay
;
507 /* "neighbor bfd" commands. */
508 install_element (BGP_NODE
, &neighbor_bfd_cmd
);
509 install_element (BGP_NODE
, &neighbor_bfd_param_cmd
);
510 install_element (BGP_NODE
, &no_neighbor_bfd_cmd
);