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 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
38 #include "ospf6_message.h"
39 #include "ospf6_neighbor.h"
40 #include "ospf6_interface.h"
41 #include "ospf6_route.h"
42 #include "ospf6_zebra.h"
43 #include "ospf6_bfd.h"
45 extern struct zclient
*zclient
;
48 * ospf6_bfd_info_free - Free BFD info structure
50 void ospf6_bfd_info_free(void **bfd_info
)
52 bfd_info_free((struct bfd_info
**)bfd_info
);
56 * ospf6_bfd_show_info - Show BFD info structure
58 void ospf6_bfd_show_info(struct vty
*vty
, void *bfd_info
, int param_only
)
61 bfd_show_param(vty
, bfd_info
, 1, 0, 0, NULL
);
63 bfd_show_info(vty
, bfd_info
, 0, 1, 0, NULL
);
67 * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
68 * zebra for starting/stopping the monitoring of
69 * the neighbor rechahability.
71 void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor
*on
, int command
)
73 struct ospf6_interface
*oi
= on
->ospf6_if
;
74 struct interface
*ifp
= oi
->interface
;
75 struct bfd_info
*bfd_info
;
79 if (!oi
->bfd_info
|| !on
->bfd_info
)
81 bfd_info
= (struct bfd_info
*)oi
->bfd_info
;
83 if (IS_OSPF6_DEBUG_ZEBRA(SEND
)) {
84 inet_ntop(AF_INET6
, &on
->linklocal_addr
, src
, sizeof(src
));
85 zlog_debug("%s nbr (%s) with BFD",
86 bfd_get_command_dbg_str(command
), src
);
89 cbit
= CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CBIT_ON
);
91 bfd_peer_sendmsg(zclient
, bfd_info
, AF_INET6
, &on
->linklocal_addr
,
92 on
->ospf6_if
->linklocal_addr
, ifp
->name
, 0, 0,
93 cbit
, command
, 0, VRF_DEFAULT
);
95 if (command
== ZEBRA_BFD_DEST_DEREGISTER
)
96 bfd_info_free((struct bfd_info
**)&on
->bfd_info
);
100 * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
101 * neighbor state is changed to/from 2way.
103 void ospf6_bfd_trigger_event(struct ospf6_neighbor
*on
, int old_state
,
106 if ((old_state
< OSPF6_NEIGHBOR_TWOWAY
)
107 && (state
>= OSPF6_NEIGHBOR_TWOWAY
))
108 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_REGISTER
);
109 else if ((old_state
>= OSPF6_NEIGHBOR_TWOWAY
)
110 && (state
< OSPF6_NEIGHBOR_TWOWAY
))
111 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_DEREGISTER
);
115 * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
116 * with a interface with BFD through
117 * zebra for starting/stopping the monitoring of
118 * the neighbor rechahability.
120 static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface
*oi
, int command
)
122 struct ospf6_neighbor
*on
;
123 struct listnode
*node
;
125 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
126 if (command
== ZEBRA_BFD_DEST_REGISTER
)
127 ospf6_bfd_info_nbr_create(oi
, on
);
129 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
) {
130 if (command
== ZEBRA_BFD_DEST_DEREGISTER
)
132 (struct bfd_info
**)&on
->bfd_info
);
136 ospf6_bfd_reg_dereg_nbr(on
, command
);
141 * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
144 static int ospf6_bfd_nbr_replay(ZAPI_CALLBACK_ARGS
)
146 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
147 struct listnode
*node
;
148 struct interface
*ifp
;
149 struct ospf6_interface
*oi
;
150 struct ospf6_neighbor
*on
;
153 if (IS_OSPF6_DEBUG_ZEBRA(RECV
))
154 zlog_debug("Zebra: BFD Dest replay request");
156 /* Send the client registration */
157 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, vrf_id
);
159 /* Replay the neighbor, if BFD is enabled on the interface*/
160 FOR_ALL_INTERFACES (vrf
, ifp
) {
161 oi
= (struct ospf6_interface
*)ifp
->info
;
163 if (!oi
|| !oi
->bfd_info
)
166 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
167 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
170 if (IS_OSPF6_DEBUG_ZEBRA(SEND
)) {
171 inet_ntop(AF_INET6
, &on
->linklocal_addr
, dst
,
173 zlog_debug("Replaying nbr (%s) to BFD", dst
);
176 ospf6_bfd_reg_dereg_nbr(on
, ZEBRA_BFD_DEST_UPDATE
);
183 * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
184 * has changed and bring down the neighbor
185 * connectivity if BFD down is received.
187 static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS
)
189 struct interface
*ifp
;
190 struct ospf6_interface
*oi
;
191 struct ospf6_neighbor
*on
;
194 struct listnode
*node
, *nnode
;
198 struct bfd_info
*bfd_info
;
201 ifp
= bfd_get_peer_info(zclient
->ibuf
, &dp
, &sp
, &status
,
204 if ((ifp
== NULL
) || (dp
.family
!= AF_INET6
))
207 if (IS_OSPF6_DEBUG_ZEBRA(RECV
)) {
208 char buf
[PREFIX2STR_BUFFER
];
209 prefix2str(&dp
, buf
, sizeof(buf
));
210 zlog_debug("Zebra: interface %s bfd destination %s %s",
211 ifp
->name
, buf
, bfd_get_status_str(status
));
215 oi
= (struct ospf6_interface
*)ifp
->info
;
216 if (!oi
|| !oi
->bfd_info
)
219 for (ALL_LIST_ELEMENTS(oi
->neighbor_list
, node
, nnode
, on
)) {
220 if (memcmp(&(on
->linklocal_addr
), &dp
.u
.prefix6
,
221 sizeof(struct in6_addr
)))
224 if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT
)) {
225 inet_ntop(AF_INET6
, &on
->linklocal_addr
, dst
,
227 zlog_debug("[%s:%s]: BFD %s", ifp
->name
, dst
,
228 bfd_get_status_str(status
));
234 bfd_info
= (struct bfd_info
*)on
->bfd_info
;
235 if (bfd_info
->status
== status
)
238 old_status
= bfd_info
->status
;
239 BFD_SET_CLIENT_STATUS(bfd_info
->status
, status
);
241 bfd_info
->last_update
= tv
.tv_sec
;
243 if ((status
== BFD_STATUS_DOWN
)
244 && (old_status
== BFD_STATUS_UP
)) {
245 THREAD_OFF(on
->inactivity_timer
);
246 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
254 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
256 void 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.
279 void ospf6_bfd_write_config(struct vty
*vty
, struct ospf6_interface
*oi
)
282 struct bfd_info
*bfd_info
;
283 #endif /* ! HAVE_BFDD */
289 bfd_info
= (struct bfd_info
*)oi
->bfd_info
;
291 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
292 vty_out(vty
, " ipv6 ospf6 bfd %d %d %d\n",
293 bfd_info
->detect_mult
, bfd_info
->required_min_rx
,
294 bfd_info
->desired_min_tx
);
296 #endif /* ! HAVE_BFDD */
297 vty_out(vty
, " ipv6 ospf6 bfd\n");
301 * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
304 static void ospf6_bfd_if_param_set(struct ospf6_interface
*oi
, uint32_t min_rx
,
305 uint32_t min_tx
, uint8_t detect_mult
,
310 bfd_set_param((struct bfd_info
**)&(oi
->bfd_info
), min_rx
, min_tx
,
311 detect_mult
, defaults
, &command
);
313 ospf6_bfd_reg_dereg_all_nbr(oi
, command
);
316 DEFUN (ipv6_ospf6_bfd
,
321 "Enables BFD support\n"
324 VTY_DECLVAR_CONTEXT(interface
, ifp
);
325 struct ospf6_interface
*oi
;
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);
342 #endif /* HAVE_BFDD */
343 ipv6_ospf6_bfd_param
,
344 ipv6_ospf6_bfd_param_cmd
,
345 "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
348 "Enables BFD support\n"
349 "Detect Multiplier\n"
350 "Required min receive interval\n"
351 "Desired min transmit interval\n")
353 VTY_DECLVAR_CONTEXT(interface
, ifp
);
355 int idx_number_2
= 4;
356 int idx_number_3
= 5;
357 struct ospf6_interface
*oi
;
365 oi
= (struct ospf6_interface
*)ifp
->info
;
367 oi
= ospf6_interface_create(ifp
);
370 if ((ret
= bfd_validate_param(
371 vty
, argv
[idx_number
]->arg
, argv
[idx_number_2
]->arg
,
372 argv
[idx_number_3
]->arg
, &dm_val
, &rx_val
, &tx_val
))
376 ospf6_bfd_if_param_set(oi
, rx_val
, tx_val
, dm_val
, 0);
381 DEFUN (no_ipv6_ospf6_bfd
,
382 no_ipv6_ospf6_bfd_cmd
,
387 "Disables BFD support\n"
390 VTY_DECLVAR_CONTEXT(interface
, ifp
);
391 struct ospf6_interface
*oi
;
394 oi
= (struct ospf6_interface
*)ifp
->info
;
396 oi
= ospf6_interface_create(ifp
);
400 ospf6_bfd_reg_dereg_all_nbr(oi
, ZEBRA_BFD_DEST_DEREGISTER
);
401 bfd_info_free((struct bfd_info
**)&(oi
->bfd_info
));
407 void ospf6_bfd_init(void)
411 /* Initialize BFD client functions */
412 zclient
->interface_bfd_dest_update
= ospf6_bfd_interface_dest_update
;
413 zclient
->bfd_dest_replay
= ospf6_bfd_nbr_replay
;
415 /* Install BFD command */
416 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_cmd
);
417 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_param_cmd
);
418 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_cmd
);