2 * ospf6_bfd.c: IPv6 OSPF 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
39 #include "ospf6_message.h"
40 #include "ospf6_neighbor.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_route.h"
43 #include "ospf6_zebra.h"
44 #include "ospf6_bfd.h"
46 extern struct zclient
*zclient
;
49 * ospf6_bfd_info_free - Free BFD info structure
52 ospf6_bfd_info_free(void **bfd_info
)
54 bfd_info_free((struct bfd_info
**) bfd_info
);
58 * ospf6_bfd_show_info - Show BFD info structure
61 ospf6_bfd_show_info(struct vty
*vty
, void *bfd_info
, int param_only
)
64 bfd_show_param(vty
, bfd_info
, 1, 0, 0, NULL
);
66 bfd_show_info(vty
, bfd_info
, 0, 1, 0, NULL
);
70 * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
71 * zebra for starting/stopping the monitoring of
72 * the neighbor rechahability.
75 ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor
*on
, int command
)
77 struct ospf6_interface
*oi
= on
->ospf6_if
;
78 struct interface
*ifp
= oi
->interface
;
79 struct bfd_info
*bfd_info
;
84 bfd_info
= (struct bfd_info
*)oi
->bfd_info
;
86 if (IS_OSPF6_DEBUG_ZEBRA(SEND
))
88 inet_ntop (AF_INET6
, &on
->linklocal_addr
, src
, sizeof (src
));
89 zlog_debug ("%s nbr (%s) with BFD",
90 bfd_get_command_dbg_str(command
), src
);
93 bfd_peer_sendmsg (zclient
, bfd_info
, AF_INET6
, &on
->linklocal_addr
,
94 on
->ospf6_if
->linklocal_addr
, ifp
->name
,
99 * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
100 * neighbor state is changed to/from 2way.
103 ospf6_bfd_trigger_event(struct ospf6_neighbor
*on
, int old_state
, int state
)
105 if ((old_state
< OSPF6_NEIGHBOR_TWOWAY
) && (state
>= OSPF6_NEIGHBOR_TWOWAY
))
106 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_REGISTER
);
107 else if ((old_state
>= OSPF6_NEIGHBOR_TWOWAY
) &&
108 (state
< OSPF6_NEIGHBOR_TWOWAY
))
109 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_DEREGISTER
);
113 * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
114 * with a interface with BFD through
115 * zebra for starting/stopping the monitoring of
116 * the neighbor rechahability.
119 ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface
*oi
, int command
)
121 struct ospf6_neighbor
*on
;
122 struct listnode
*node
;
124 for (ALL_LIST_ELEMENTS_RO (oi
->neighbor_list
, node
, on
))
126 if (command
!= ZEBRA_BFD_DEST_DEREGISTER
)
127 ospf6_bfd_info_nbr_create(oi
, on
);
129 bfd_info_free((struct bfd_info
**)&on
->bfd_info
);
131 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
134 ospf6_bfd_reg_dereg_nbr(on
, command
);
139 * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
143 ospf6_bfd_nbr_replay (int command
, struct zclient
*client
, zebra_size_t length
)
145 struct listnode
*inode
, *nnode
;
146 struct interface
*ifp
;
147 struct ospf6_interface
*oi
;
148 struct ospf6_neighbor
*on
;
151 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
152 zlog_debug("Zebra: BFD Dest replay request");
154 /* Replay the neighbor, if BFD is enabled on the interface*/
155 for (ALL_LIST_ELEMENTS_RO (iflist
, inode
, ifp
))
157 oi
= (struct ospf6_interface
*) ifp
->info
;
159 if (!oi
|| !oi
->bfd_info
)
162 for (ALL_LIST_ELEMENTS_RO (oi
->neighbor_list
, nnode
, on
))
164 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
167 if (IS_OSPF6_DEBUG_ZEBRA(SEND
))
169 inet_ntop (AF_INET6
, &on
->linklocal_addr
, dst
, sizeof (dst
));
170 zlog_debug ("Replaying nbr (%s) to BFD", dst
);
173 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_UPDATE
);
180 * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
181 * has changed and bring down the neighbor
182 * connectivity if BFD down is received.
185 ospf6_bfd_interface_dest_update (int command
, struct zclient
*zclient
,
188 struct interface
*ifp
;
189 struct ospf6_interface
*oi
;
190 struct ospf6_neighbor
*on
;
193 struct listnode
*node
, *nnode
;
197 struct bfd_info
*bfd_info
;
200 ifp
= bfd_get_peer_info(zclient
->ibuf
, &dp
, &sp
, &status
);
202 if ((ifp
== NULL
) || (dp
.family
!= AF_INET6
))
205 if (IS_OSPF6_DEBUG_ZEBRA (RECV
))
208 prefix2str(&dp
, buf
, sizeof(buf
));
209 zlog_debug("Zebra: interface %s bfd destination %s %s", ifp
->name
, buf
,
210 bfd_get_status_str(status
));
214 oi
= (struct ospf6_interface
*) ifp
->info
;
215 if (!oi
|| !oi
->bfd_info
)
218 for (ALL_LIST_ELEMENTS (oi
->neighbor_list
, node
, nnode
, on
))
220 if (memcmp(&(on
->linklocal_addr
), &dp
.u
.prefix6
, sizeof(struct in6_addr
)))
223 if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT
))
225 inet_ntop (AF_INET6
, &on
->linklocal_addr
, dst
, sizeof (dst
));
226 zlog_debug ("[%s:%s]: BFD %s", ifp
->name
, dst
,
227 bfd_get_status_str(status
));
233 bfd_info
= (struct bfd_info
*)on
->bfd_info
;
234 if (bfd_info
->status
== status
)
237 old_status
= bfd_info
->status
;
238 bfd_info
->status
= status
;
239 quagga_gettime (QUAGGA_CLK_MONOTONIC
, &tv
);
240 bfd_info
->last_update
= tv
.tv_sec
;
242 if ((status
== BFD_STATUS_DOWN
) && (old_status
== BFD_STATUS_UP
))
244 THREAD_OFF (on
->inactivity_timer
);
245 thread_add_event (master
, inactivity_timer
, on
, 0);
253 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
256 ospf6_bfd_info_nbr_create (struct ospf6_interface
*oi
,
257 struct ospf6_neighbor
*on
)
259 struct bfd_info
*oi_bfd_info
;
260 struct bfd_info
*on_bfd_info
;
265 oi_bfd_info
= (struct bfd_info
*)oi
->bfd_info
;
268 on
->bfd_info
= bfd_info_create();
270 on_bfd_info
= (struct bfd_info
*)on
->bfd_info
;
271 on_bfd_info
->detect_mult
= oi_bfd_info
->detect_mult
;
272 on_bfd_info
->desired_min_tx
= oi_bfd_info
->desired_min_tx
;
273 on_bfd_info
->required_min_rx
= oi_bfd_info
->required_min_rx
;
277 * ospf6_bfd_write_config - Write the interface BFD configuration.
280 ospf6_bfd_write_config(struct vty
*vty
, struct ospf6_interface
*oi
)
282 struct bfd_info
*bfd_info
;
287 bfd_info
= (struct bfd_info
*)oi
->bfd_info
;
289 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
290 vty_out (vty
, " ipv6 ospf6 bfd %d %d %d%s",
291 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
292 bfd_info
->desired_min_tx
, VTY_NEWLINE
);
294 vty_out (vty
, " ipv6 ospf6 bfd%s", VTY_NEWLINE
);
298 * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
302 ospf6_bfd_if_param_set (struct ospf6_interface
*oi
, u_int32_t min_rx
,
303 u_int32_t min_tx
, u_int8_t detect_mult
,
308 bfd_set_param((struct bfd_info
**)&(oi
->bfd_info
), min_rx
, min_tx
, detect_mult
,
311 ospf6_bfd_reg_dereg_all_nbr(oi
, command
);
314 DEFUN (ipv6_ospf6_bfd
,
319 "Enables BFD support\n"
322 struct ospf6_interface
*oi
;
323 struct interface
*ifp
;
325 ifp
= (struct interface
*) vty
->index
;
328 oi
= (struct ospf6_interface
*) ifp
->info
;
330 oi
= ospf6_interface_create (ifp
);
333 ospf6_bfd_if_param_set (oi
, BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
334 BFD_DEF_DETECT_MULT
, 1);
338 DEFUN (ipv6_ospf6_bfd_param
,
339 ipv6_ospf6_bfd_param_cmd
,
340 "ipv6 ospf6 bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE
,
343 "Enables BFD support\n"
344 "Detect Multiplier\n"
345 "Required min receive interval\n"
346 "Desired min transmit interval\n")
348 struct ospf6_interface
*oi
;
349 struct interface
*ifp
;
355 ifp
= (struct interface
*) vty
->index
;
358 oi
= (struct ospf6_interface
*) ifp
->info
;
360 oi
= ospf6_interface_create (ifp
);
363 if ((ret
= bfd_validate_param (vty
, argv
[0], argv
[1], argv
[2], &dm_val
,
364 &rx_val
, &tx_val
)) != CMD_SUCCESS
)
367 ospf6_bfd_if_param_set (oi
, rx_val
, tx_val
, dm_val
, 0);
372 DEFUN (no_ipv6_ospf6_bfd
,
373 no_ipv6_ospf6_bfd_cmd
,
378 "Disables BFD support\n"
381 struct ospf6_interface
*oi
;
382 struct interface
*ifp
;
384 ifp
= (struct interface
*) vty
->index
;
387 oi
= (struct ospf6_interface
*) ifp
->info
;
389 oi
= ospf6_interface_create (ifp
);
394 ospf6_bfd_reg_dereg_all_nbr(oi
, ZEBRA_BFD_DEST_DEREGISTER
);
395 bfd_info_free((struct bfd_info
**)&(oi
->bfd_info
));
404 /* Initialize BFD client functions */
405 zclient
->interface_bfd_dest_update
= ospf6_bfd_interface_dest_update
;
406 zclient
->bfd_dest_replay
= ospf6_bfd_nbr_replay
;
408 /* Install BFD command */
409 install_element (INTERFACE_NODE
, &ipv6_ospf6_bfd_cmd
);
410 install_element (INTERFACE_NODE
, &ipv6_ospf6_bfd_param_cmd
);
411 install_element (INTERFACE_NODE
, &no_ipv6_ospf6_bfd_cmd
);