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
->conf_if
== NULL
) && ((peer
->sort
== BGP_PEER_IBGP
) ||
77 is_ebgp_multihop_configured(peer
)))
84 * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
85 * command to Zebra to be forwarded to BFD
88 bgp_bfd_peer_sendmsg (struct peer
*peer
, int command
)
90 struct bfd_info
*bfd_info
;
91 vrf_id_t vrf_id
= VRF_DEFAULT
;
93 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
95 if (peer
->bgp
&& (peer
->bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
))
96 vrf_id
= peer
->bgp
->vrf_id
;
98 if (peer
->su
.sa
.sa_family
== AF_INET
)
99 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET
,
100 &peer
->su
.sin
.sin_addr
,
101 (peer
->su_local
) ? &peer
->su_local
->sin
.sin_addr
: NULL
,
102 (peer
->nexthop
.ifp
) ? peer
->nexthop
.ifp
->name
: NULL
,
103 peer
->ttl
, bgp_bfd_is_peer_multihop(peer
), command
, 1, vrf_id
);
104 else if (peer
->su
.sa
.sa_family
== AF_INET6
)
105 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET6
,
106 &peer
->su
.sin6
.sin6_addr
,
107 (peer
->su_local
) ? &peer
->su_local
->sin6
.sin6_addr
: NULL
,
108 (peer
->nexthop
.ifp
) ? peer
->nexthop
.ifp
->name
: NULL
,
109 peer
->ttl
, bgp_bfd_is_peer_multihop(peer
), command
, 1, vrf_id
);
113 * bgp_bfd_register_peer - register a peer with BFD through zebra
114 * for monitoring the peer rechahability.
117 bgp_bfd_register_peer (struct peer
*peer
)
119 struct bfd_info
*bfd_info
;
123 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
125 /* Check if BFD is enabled and peer has already been registered with BFD */
126 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
129 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_REGISTER
);
133 * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra
134 * for stopping the monitoring of the peer
138 bgp_bfd_deregister_peer (struct peer
*peer
)
140 struct bfd_info
*bfd_info
;
144 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
146 /* Check if BFD is eanbled and peer has not been registered */
147 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
150 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_DEREGISTER
);
154 * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
158 bgp_bfd_update_peer (struct peer
*peer
)
160 struct bfd_info
*bfd_info
;
164 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
166 /* Check if the peer has been registered with BFD*/
167 if (!CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_REG
))
170 bgp_bfd_peer_sendmsg(peer
, ZEBRA_BFD_DEST_UPDATE
);
174 * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
178 bgp_bfd_dest_replay (int command
, struct zclient
*client
, zebra_size_t length
,
181 struct listnode
*mnode
, *node
, *nnode
;
185 if (BGP_DEBUG (zebra
, ZEBRA
))
186 zlog_debug("Zebra: BFD Dest replay request");
188 /* Send the client registration */
189 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
191 /* Replay the peer, if BFD is enabled in BGP */
193 for (ALL_LIST_ELEMENTS_RO (bm
->bgp
, mnode
, bgp
))
194 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
196 bgp_bfd_update_peer(peer
);
203 * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
204 * down the peer if the BFD session went down from * up.
207 bgp_bfd_peer_status_update (struct peer
*peer
, int status
)
209 struct bfd_info
*bfd_info
;
212 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
214 if (bfd_info
->status
== status
)
217 old_status
= bfd_info
->status
;
218 bfd_info
->status
= status
;
219 bfd_info
->last_update
= bgp_clock();
221 if ((status
== BFD_STATUS_DOWN
) && (old_status
== BFD_STATUS_UP
))
223 peer
->last_reset
= PEER_DOWN_BFD_DOWN
;
224 BGP_EVENT_ADD (peer
, BGP_Stop
);
229 * bgp_bfd_dest_update - Find the peer for which the BFD status
230 * has changed and bring down the peer
231 * connectivity if the BFD session went down.
234 bgp_bfd_dest_update (int command
, struct zclient
*zclient
,
235 zebra_size_t length
, vrf_id_t vrf_id
)
237 struct interface
*ifp
;
242 ifp
= bfd_get_peer_info (zclient
->ibuf
, &dp
, &sp
, &status
, vrf_id
);
244 if (BGP_DEBUG (zebra
, ZEBRA
))
246 char buf
[2][PREFIX2STR_BUFFER
];
247 prefix2str(&dp
, buf
[0], sizeof(buf
[0]));
250 zlog_debug("Zebra: interface %s bfd destination %s %s",
251 ifp
->name
, buf
[0], bfd_get_status_str(status
));
255 prefix2str(&sp
, buf
[1], sizeof(buf
[1]));
256 zlog_debug("Zebra: source %s bfd destination %s %s",
257 buf
[1], buf
[0], bfd_get_status_str(status
));
261 /* Bring the peer down if BFD is enabled in BGP */
263 struct listnode
*mnode
, *node
, *nnode
;
267 for (ALL_LIST_ELEMENTS_RO (bm
->bgp
, mnode
, bgp
))
268 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
273 if ((dp
.family
== AF_INET
) && (peer
->su
.sa
.sa_family
== AF_INET
))
275 if (dp
.u
.prefix4
.s_addr
!= peer
->su
.sin
.sin_addr
.s_addr
)
279 else if ((dp
.family
== AF_INET6
) &&
280 (peer
->su
.sa
.sa_family
== AF_INET6
))
282 if (memcmp(&dp
.u
.prefix6
, &peer
->su
.sin6
.sin6_addr
,
283 sizeof (struct in6_addr
)))
290 if (ifp
&& (ifp
== peer
->nexthop
.ifp
))
292 bgp_bfd_peer_status_update(peer
, status
);
299 if ((sp
.family
== AF_INET
) &&
300 (peer
->su_local
->sa
.sa_family
== AF_INET
))
302 if (sp
.u
.prefix4
.s_addr
!= peer
->su_local
->sin
.sin_addr
.s_addr
)
306 else if ((sp
.family
== AF_INET6
) &&
307 (peer
->su_local
->sa
.sa_family
== AF_INET6
))
309 if (memcmp(&sp
.u
.prefix6
, &peer
->su_local
->sin6
.sin6_addr
,
310 sizeof (struct in6_addr
)))
317 if ((vrf_id
!= VRF_DEFAULT
) && (peer
->bgp
->vrf_id
!= vrf_id
))
320 bgp_bfd_peer_status_update(peer
, status
);
329 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
332 bgp_bfd_peer_param_set (struct peer
*peer
, u_int32_t min_rx
, u_int32_t min_tx
,
333 u_int8_t detect_mult
, int defaults
)
335 struct peer_group
*group
;
336 struct listnode
*node
, *nnode
;
339 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
), min_rx
, min_tx
,
340 detect_mult
, defaults
, &command
);
342 if (CHECK_FLAG (peer
->sflags
, PEER_STATUS_GROUP
))
345 for (ALL_LIST_ELEMENTS (group
->peer
, node
, nnode
, peer
))
348 bfd_set_param((struct bfd_info
**)&(peer
->bfd_info
), min_rx
, min_tx
,
349 detect_mult
, defaults
, &command
);
351 if ((peer
->status
== Established
) &&
352 (command
== ZEBRA_BFD_DEST_REGISTER
))
353 bgp_bfd_register_peer(peer
);
354 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
355 bgp_bfd_update_peer(peer
);
360 if ((peer
->status
== Established
) &&
361 (command
== ZEBRA_BFD_DEST_REGISTER
))
362 bgp_bfd_register_peer(peer
);
363 else if (command
== ZEBRA_BFD_DEST_UPDATE
)
364 bgp_bfd_update_peer(peer
);
370 * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
373 bgp_bfd_peer_param_unset (struct peer
*peer
)
375 struct peer_group
*group
;
376 struct listnode
*node
, *nnode
;
381 if (CHECK_FLAG (peer
->sflags
, PEER_STATUS_GROUP
))
383 bfd_info_free(&(peer
->bfd_info
));
385 for (ALL_LIST_ELEMENTS (group
->peer
, node
, nnode
, peer
))
387 bgp_bfd_deregister_peer(peer
);
388 bfd_info_free(&(peer
->bfd_info
));
393 bgp_bfd_deregister_peer(peer
);
394 bfd_info_free(&(peer
->bfd_info
));
400 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
403 bgp_bfd_peer_config_write(struct vty
*vty
, struct peer
*peer
, char *addr
)
405 struct bfd_info
*bfd_info
;
410 bfd_info
= (struct bfd_info
*)peer
->bfd_info
;
412 if (CHECK_FLAG (bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
413 vty_out (vty
, " neighbor %s bfd %d %d %d%s", addr
,
414 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
415 bfd_info
->desired_min_tx
, VTY_NEWLINE
);
417 vty_out (vty
, " neighbor %s bfd%s", addr
, VTY_NEWLINE
);
421 * bgp_bfd_show_info - Show the peer BFD information.
424 bgp_bfd_show_info(struct vty
*vty
, struct peer
*peer
, u_char use_json
, json_object
*json_neigh
)
426 bfd_show_info(vty
, (struct bfd_info
*)peer
->bfd_info
,
427 bgp_bfd_is_peer_multihop(peer
), 0, use_json
, json_neigh
);
435 "Enables BFD support\n")
440 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
444 ret
= bgp_bfd_peer_param_set (peer
, BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
445 BFD_DEF_DETECT_MULT
, 1);
447 return bgp_vty_return (vty
, ret
);
453 DEFUN (neighbor_bfd_param
,
454 neighbor_bfd_param_cmd
,
455 NEIGHBOR_CMD2
"bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE
,
458 "Enables BFD support\n"
459 "Detect Multiplier\n"
460 "Required min receive interval\n"
461 "Desired min transmit interval\n")
469 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
473 if ((ret
= bfd_validate_param (vty
, argv
[1], argv
[2], argv
[3], &dm_val
,
474 &rx_val
, &tx_val
)) != CMD_SUCCESS
)
477 ret
= bgp_bfd_peer_param_set (peer
, rx_val
, tx_val
, dm_val
, 0);
479 return bgp_vty_return (vty
, ret
);
485 DEFUN (no_neighbor_bfd
,
487 NO_NEIGHBOR_CMD2
"bfd",
491 "Disables BFD support\n")
496 peer
= peer_and_group_lookup_vty (vty
, argv
[0]);
500 ret
= bgp_bfd_peer_param_unset(peer
);
502 return bgp_vty_return (vty
, ret
);
507 ALIAS (no_neighbor_bfd
,
508 no_neighbor_bfd_val_cmd
,
509 NO_NEIGHBOR_CMD2
"bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE
,
513 "Disables BFD support\n"
514 "Detect Multiplier\n"
515 "Required min receive interval\n"
516 "Desired min transmit interval\n")
521 /* Initialize BFD client functions */
522 zclient
->interface_bfd_dest_update
= bgp_bfd_dest_update
;
523 zclient
->bfd_dest_replay
= bgp_bfd_dest_replay
;
525 /* "neighbor bfd" commands. */
526 install_element (BGP_NODE
, &neighbor_bfd_cmd
);
527 install_element (BGP_NODE
, &neighbor_bfd_param_cmd
);
528 install_element (BGP_NODE
, &no_neighbor_bfd_cmd
);
529 install_element (BGP_NODE
, &no_neighbor_bfd_val_cmd
);
531 /* Send the client registration */
532 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);