2 * ospf_bfd.c: 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
37 #include "ospf_asbr.h"
39 #include "ospf_lsdb.h"
40 #include "ospf_neighbor.h"
41 #include "ospf_interface.h"
44 #include "ospf_dump.h"
47 extern struct zclient
*zclient
;
50 * ospf_bfd_info_free - Free BFD info structure
52 void ospf_bfd_info_free(void **bfd_info
)
54 bfd_info_free((struct bfd_info
**)bfd_info
);
58 * ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
59 * zebra for starting/stopping the monitoring of
60 * the neighbor rechahability.
62 static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor
*nbr
, int command
)
64 struct ospf_interface
*oi
= nbr
->oi
;
65 struct interface
*ifp
= oi
->ifp
;
66 struct ospf_if_params
*params
;
67 struct bfd_info
*bfd_info
;
70 /* Check if BFD is enabled */
71 params
= IF_DEF_PARAMS(ifp
);
73 /* Check if BFD is enabled */
74 if (!params
->bfd_info
)
76 bfd_info
= (struct bfd_info
*)params
->bfd_info
;
78 if (IS_DEBUG_OSPF(zebra
, ZEBRA_INTERFACE
))
79 zlog_debug("%s nbr (%s) with BFD. OSPF vrf %s",
80 bfd_get_command_dbg_str(command
),
82 ospf_vrf_id_to_name(oi
->ospf
->vrf_id
));
84 cbit
= CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_BFD_CBIT_ON
);
86 bfd_peer_sendmsg(zclient
, bfd_info
, AF_INET
, &nbr
->src
, NULL
, ifp
->name
,
87 0, 0, cbit
, command
, 0, oi
->ospf
->vrf_id
);
91 * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
92 * neighbor state is changed to/from 2way.
94 void ospf_bfd_trigger_event(struct ospf_neighbor
*nbr
, int old_state
, int state
)
96 if ((old_state
< NSM_TwoWay
) && (state
>= NSM_TwoWay
))
97 ospf_bfd_reg_dereg_nbr(nbr
, ZEBRA_BFD_DEST_REGISTER
);
98 else if ((old_state
>= NSM_TwoWay
) && (state
< NSM_TwoWay
))
99 ospf_bfd_reg_dereg_nbr(nbr
, ZEBRA_BFD_DEST_DEREGISTER
);
103 * ospf_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
104 * with a interface with BFD through
105 * zebra for starting/stopping the monitoring of
106 * the neighbor rechahability.
108 static int ospf_bfd_reg_dereg_all_nbr(struct interface
*ifp
, int command
)
110 struct ospf_interface
*oi
;
111 struct route_table
*nbrs
;
112 struct ospf_neighbor
*nbr
;
113 struct route_node
*irn
;
114 struct route_node
*nrn
;
116 for (irn
= route_top(IF_OIFS(ifp
)); irn
; irn
= route_next(irn
)) {
117 if ((oi
= irn
->info
) == NULL
)
120 if ((nbrs
= oi
->nbrs
) == NULL
)
123 for (nrn
= route_top(nbrs
); nrn
; nrn
= route_next(nrn
)) {
124 if ((nbr
= nrn
->info
) == NULL
|| nbr
== oi
->nbr_self
)
127 if (command
!= ZEBRA_BFD_DEST_DEREGISTER
)
128 ospf_bfd_info_nbr_create(oi
, nbr
);
131 (struct bfd_info
**)&nbr
->bfd_info
);
133 if (nbr
->state
< NSM_TwoWay
)
136 ospf_bfd_reg_dereg_nbr(nbr
, command
);
144 * ospf_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
147 static int ospf_bfd_nbr_replay(ZAPI_CALLBACK_ARGS
)
149 struct listnode
*inode
, *node
, *onode
;
151 struct ospf_interface
*oi
;
152 struct route_table
*nbrs
;
153 struct route_node
*rn
;
154 struct ospf_neighbor
*nbr
;
155 struct ospf_if_params
*params
;
157 if (IS_DEBUG_OSPF(zebra
, ZEBRA_INTERFACE
)) {
158 zlog_debug("Zebra: BFD Dest replay request");
161 /* Send the client registration */
162 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, vrf_id
);
164 /* Replay the neighbor, if BFD is enabled in OSPF */
165 for (ALL_LIST_ELEMENTS(om
->ospf
, node
, onode
, ospf
)) {
166 for (ALL_LIST_ELEMENTS_RO(ospf
->oiflist
, inode
, oi
)) {
167 if ((nbrs
= oi
->nbrs
) == NULL
)
170 params
= IF_DEF_PARAMS(oi
->ifp
);
171 if (!params
->bfd_info
)
174 for (rn
= route_top(nbrs
); rn
; rn
= route_next(rn
)) {
175 if ((nbr
= rn
->info
) == NULL
176 || nbr
== oi
->nbr_self
)
179 if (nbr
->state
< NSM_TwoWay
)
182 if (IS_DEBUG_OSPF(zebra
, ZEBRA_INTERFACE
))
183 zlog_debug("Replaying nbr (%s) to BFD",
184 inet_ntoa(nbr
->src
));
186 ospf_bfd_reg_dereg_nbr(nbr
,
187 ZEBRA_BFD_DEST_UPDATE
);
195 * ospf_bfd_interface_dest_update - Find the neighbor for which the BFD status
196 * has changed and bring down the neighbor
197 * connectivity if the BFD status changed to
200 static int ospf_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS
)
202 struct interface
*ifp
;
203 struct ospf_interface
*oi
;
204 struct ospf_if_params
*params
;
205 struct ospf_neighbor
*nbr
;
206 struct route_node
*node
;
210 struct bfd_info
*bfd_info
;
213 ifp
= bfd_get_peer_info(zclient
->ibuf
, &p
, NULL
, &status
,
216 if ((ifp
== NULL
) || (p
.family
!= AF_INET
))
219 if (IS_DEBUG_OSPF(zebra
, ZEBRA_INTERFACE
)) {
220 char buf
[PREFIX2STR_BUFFER
];
221 prefix2str(&p
, buf
, sizeof(buf
));
222 zlog_debug("Zebra: interface %s bfd destination %s %s",
223 ifp
->name
, buf
, bfd_get_status_str(status
));
226 params
= IF_DEF_PARAMS(ifp
);
227 if (!params
->bfd_info
)
230 for (node
= route_top(IF_OIFS(ifp
)); node
; node
= route_next(node
)) {
231 if ((oi
= node
->info
) == NULL
)
234 nbr
= ospf_nbr_lookup_by_addr(oi
->nbrs
, &p
.u
.prefix4
);
235 if (!nbr
|| !nbr
->bfd_info
)
238 bfd_info
= (struct bfd_info
*)nbr
->bfd_info
;
239 if (bfd_info
->status
== status
)
242 old_status
= bfd_info
->status
;
243 bfd_info
->status
= status
;
245 bfd_info
->last_update
= tv
.tv_sec
;
247 if ((status
== BFD_STATUS_DOWN
)
248 && (old_status
== BFD_STATUS_UP
)) {
249 if (IS_DEBUG_OSPF(nsm
, NSM_EVENTS
))
250 zlog_debug("NSM[%s:%s]: BFD Down",
252 inet_ntoa(nbr
->address
.u
.prefix4
));
254 OSPF_NSM_EVENT_SCHEDULE(nbr
, NSM_InactivityTimer
);
256 if ((status
== BFD_STATUS_UP
)
257 && (old_status
== BFD_STATUS_DOWN
)) {
258 if (IS_DEBUG_OSPF(nsm
, NSM_EVENTS
))
259 zlog_debug("NSM[%s:%s]: BFD Up",
261 inet_ntoa(nbr
->address
.u
.prefix4
));
269 * ospf_bfd_info_nbr_create - Create/update BFD information for a neighbor.
271 void ospf_bfd_info_nbr_create(struct ospf_interface
*oi
,
272 struct ospf_neighbor
*nbr
)
274 struct bfd_info
*oi_bfd_info
;
275 struct bfd_info
*nbr_bfd_info
;
276 struct interface
*ifp
= oi
->ifp
;
277 struct ospf_if_params
*params
;
279 /* Check if BFD is enabled */
280 params
= IF_DEF_PARAMS(ifp
);
282 /* Check if BFD is enabled */
283 if (!params
->bfd_info
)
286 oi_bfd_info
= (struct bfd_info
*)params
->bfd_info
;
288 nbr
->bfd_info
= bfd_info_create();
290 nbr_bfd_info
= (struct bfd_info
*)nbr
->bfd_info
;
291 nbr_bfd_info
->detect_mult
= oi_bfd_info
->detect_mult
;
292 nbr_bfd_info
->desired_min_tx
= oi_bfd_info
->desired_min_tx
;
293 nbr_bfd_info
->required_min_rx
= oi_bfd_info
->required_min_rx
;
297 * ospf_bfd_write_config - Write the interface BFD configuration.
299 void ospf_bfd_write_config(struct vty
*vty
, struct ospf_if_params
*params
)
303 struct bfd_info
*bfd_info
;
304 #endif /* ! HAVE_BFDD */
306 if (!params
->bfd_info
)
310 bfd_info
= (struct bfd_info
*)params
->bfd_info
;
312 if (CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
313 vty_out(vty
, " ip ospf bfd %d %d %d\n", bfd_info
->detect_mult
,
314 bfd_info
->required_min_rx
, bfd_info
->desired_min_tx
);
316 #endif /* ! HAVE_BFDD */
317 vty_out(vty
, " ip ospf bfd\n");
321 * ospf_bfd_show_info - Show BFD info structure
323 void ospf_bfd_show_info(struct vty
*vty
, void *bfd_info
, json_object
*json_obj
,
324 bool use_json
, int param_only
)
327 bfd_show_param(vty
, (struct bfd_info
*)bfd_info
, 1, 0, use_json
,
330 bfd_show_info(vty
, (struct bfd_info
*)bfd_info
, 0, 1, use_json
,
335 * ospf_bfd_interface_show - Show the interface BFD configuration.
337 void ospf_bfd_interface_show(struct vty
*vty
, struct interface
*ifp
,
338 json_object
*json_interface_sub
, bool use_json
)
340 struct ospf_if_params
*params
;
342 params
= IF_DEF_PARAMS(ifp
);
344 ospf_bfd_show_info(vty
, params
->bfd_info
, json_interface_sub
, use_json
,
349 * ospf_bfd_if_param_set - Set the configured BFD paramter values for
352 static void ospf_bfd_if_param_set(struct interface
*ifp
, uint32_t min_rx
,
353 uint32_t min_tx
, uint8_t detect_mult
,
356 struct ospf_if_params
*params
;
359 params
= IF_DEF_PARAMS(ifp
);
361 bfd_set_param((struct bfd_info
**)&(params
->bfd_info
), min_rx
, min_tx
,
362 detect_mult
, defaults
, &command
);
364 ospf_bfd_reg_dereg_all_nbr(ifp
, command
);
371 "OSPF interface commands\n"
372 "Enables BFD support\n")
374 VTY_DECLVAR_CONTEXT(interface
, ifp
);
375 struct ospf_if_params
*params
;
376 struct bfd_info
*bfd_info
;
379 params
= IF_DEF_PARAMS(ifp
);
380 bfd_info
= params
->bfd_info
;
382 if (!bfd_info
|| !CHECK_FLAG(bfd_info
->flags
, BFD_FLAG_PARAM_CFG
))
383 ospf_bfd_if_param_set(ifp
, BFD_DEF_MIN_RX
, BFD_DEF_MIN_TX
,
384 BFD_DEF_DETECT_MULT
, 1);
393 #endif /* HAVE_BFDD */
395 ip_ospf_bfd_param_cmd
,
396 "ip ospf bfd (2-255) (50-60000) (50-60000)",
398 "OSPF interface commands\n"
399 "Enables BFD support\n"
400 "Detect Multiplier\n"
401 "Required min receive interval\n"
402 "Desired min transmit interval\n")
404 VTY_DECLVAR_CONTEXT(interface
, ifp
);
406 int idx_number_2
= 4;
407 int idx_number_3
= 5;
415 if ((ret
= bfd_validate_param(
416 vty
, argv
[idx_number
]->arg
, argv
[idx_number_2
]->arg
,
417 argv
[idx_number_3
]->arg
, &dm_val
, &rx_val
, &tx_val
))
421 ospf_bfd_if_param_set(ifp
, rx_val
, tx_val
, dm_val
, 0);
426 DEFUN (no_ip_ospf_bfd
,
431 "no ip ospf bfd [(2-255) (50-60000) (50-60000)]",
432 #endif /* HAVE_BFDD */
435 "OSPF interface commands\n"
436 "Disables BFD support\n"
438 "Detect Multiplier\n"
439 "Required min receive interval\n"
440 "Desired min transmit interval\n"
441 #endif /* !HAVE_BFDD */
444 VTY_DECLVAR_CONTEXT(interface
, ifp
);
445 struct ospf_if_params
*params
;
449 params
= IF_DEF_PARAMS(ifp
);
450 if (params
->bfd_info
) {
451 ospf_bfd_reg_dereg_all_nbr(ifp
, ZEBRA_BFD_DEST_DEREGISTER
);
452 bfd_info_free(&(params
->bfd_info
));
458 void ospf_bfd_init(void)
462 /* Initialize BFD client functions */
463 zclient
->interface_bfd_dest_update
= ospf_bfd_interface_dest_update
;
464 zclient
->bfd_dest_replay
= ospf_bfd_nbr_replay
;
466 /* Install BFD command */
467 install_element(INTERFACE_NODE
, &ip_ospf_bfd_cmd
);
468 install_element(INTERFACE_NODE
, &ip_ospf_bfd_param_cmd
);
469 install_element(INTERFACE_NODE
, &no_ip_ospf_bfd_cmd
);