1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ospf6_bfd.c: IPv6 OSPF BFD handling routines
5 * @copyright Copyright (C) 2015 Cumulus Networks, Inc.
23 #include "ospf6_message.h"
24 #include "ospf6_neighbor.h"
25 #include "ospf6_interface.h"
26 #include "ospf6_route.h"
27 #include "ospf6_zebra.h"
28 #include "ospf6_bfd.h"
30 extern struct zclient
*zclient
;
33 * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
34 * neighbor state is changed to/from 2way.
36 void ospf6_bfd_trigger_event(struct ospf6_neighbor
*on
, int old_state
,
40 struct in6_addr src
, dst
;
42 /* Skip sessions without BFD. */
43 if (on
->bfd_session
== NULL
)
46 if (old_state
< OSPF6_NEIGHBOR_TWOWAY
47 && state
>= OSPF6_NEIGHBOR_TWOWAY
) {
49 * Check if neighbor address changed.
51 * When the neighbor is configured BFD before having an existing
52 * connection, then the destination address will be set to `::`
53 * which will cause session installation failure. This piece of
54 * code updates the address in that case.
56 bfd_sess_addresses(on
->bfd_session
, &family
, &src
, &dst
);
57 if (memcmp(&on
->linklocal_addr
, &dst
, sizeof(dst
))) {
58 bfd_sess_set_ipv6_addrs(on
->bfd_session
, &src
,
62 bfd_sess_install(on
->bfd_session
);
63 } else if (old_state
>= OSPF6_NEIGHBOR_TWOWAY
64 && state
< OSPF6_NEIGHBOR_TWOWAY
)
65 bfd_sess_uninstall(on
->bfd_session
);
69 * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
70 * with a interface with BFD through
71 * zebra for starting/stopping the monitoring of
72 * the neighbor rechahability.
74 static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface
*oi
,
77 struct ospf6_neighbor
*on
;
78 struct listnode
*node
;
80 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
81 /* Remove all sessions. */
83 bfd_sess_free(&on
->bfd_session
);
87 /* Always allocate session data even if not enabled. */
88 ospf6_bfd_info_nbr_create(oi
, on
);
91 * If not connected yet, don't create any session but defer it
92 * for later. See function `ospf6_bfd_trigger_event`.
94 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
97 bfd_sess_install(on
->bfd_session
);
101 static void ospf6_bfd_callback(struct bfd_session_params
*bsp
,
102 const struct bfd_session_status
*bss
, void *arg
)
104 struct ospf6_neighbor
*on
= arg
;
106 if (bss
->state
== BFD_STATUS_DOWN
107 && bss
->previous_state
== BFD_STATUS_UP
) {
108 THREAD_OFF(on
->inactivity_timer
);
109 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
114 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
116 void ospf6_bfd_info_nbr_create(struct ospf6_interface
*oi
,
117 struct ospf6_neighbor
*on
)
119 if (!oi
->bfd_config
.enabled
)
122 if (on
->bfd_session
== NULL
)
123 on
->bfd_session
= bfd_sess_new(ospf6_bfd_callback
, on
);
125 bfd_sess_set_timers(on
->bfd_session
,
126 oi
->bfd_config
.detection_multiplier
,
127 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
128 bfd_sess_set_ipv6_addrs(on
->bfd_session
, on
->ospf6_if
->linklocal_addr
,
129 &on
->linklocal_addr
);
130 bfd_sess_set_interface(on
->bfd_session
, oi
->interface
->name
);
131 bfd_sess_set_vrf(on
->bfd_session
, oi
->interface
->vrf
->vrf_id
);
132 bfd_sess_set_profile(on
->bfd_session
, oi
->bfd_config
.profile
);
136 * ospf6_bfd_write_config - Write the interface BFD configuration.
138 void ospf6_bfd_write_config(struct vty
*vty
, struct ospf6_interface
*oi
)
140 if (!oi
->bfd_config
.enabled
)
144 if (oi
->bfd_config
.detection_multiplier
!= BFD_DEF_DETECT_MULT
145 || oi
->bfd_config
.min_rx
!= BFD_DEF_MIN_RX
146 || oi
->bfd_config
.min_tx
!= BFD_DEF_MIN_TX
)
147 vty_out(vty
, " ipv6 ospf6 bfd %d %d %d\n",
148 oi
->bfd_config
.detection_multiplier
,
149 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
151 #endif /* ! HAVE_BFDD */
152 vty_out(vty
, " ipv6 ospf6 bfd\n");
154 if (oi
->bfd_config
.profile
)
155 vty_out(vty
, " ipv6 ospf6 bfd profile %s\n",
156 oi
->bfd_config
.profile
);
159 DEFUN(ipv6_ospf6_bfd
, ipv6_ospf6_bfd_cmd
,
160 "ipv6 ospf6 bfd [profile BFDPROF]",
162 "Enables BFD support\n"
163 "BFD Profile selection\n"
164 "BFD Profile name\n")
166 VTY_DECLVAR_CONTEXT(interface
, ifp
);
167 struct ospf6_interface
*oi
;
171 oi
= (struct ospf6_interface
*)ifp
->info
;
173 oi
= ospf6_interface_create(ifp
);
176 oi
->bfd_config
.detection_multiplier
= BFD_DEF_DETECT_MULT
;
177 oi
->bfd_config
.min_rx
= BFD_DEF_MIN_RX
;
178 oi
->bfd_config
.min_tx
= BFD_DEF_MIN_TX
;
179 oi
->bfd_config
.enabled
= true;
180 if (argc
> prof_idx
) {
181 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
182 oi
->bfd_config
.profile
=
183 XSTRDUP(MTYPE_TMP
, argv
[prof_idx
]->arg
);
186 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
191 DEFUN(no_ipv6_ospf6_bfd_profile
, no_ipv6_ospf6_bfd_profile_cmd
,
192 "no ipv6 ospf6 bfd profile [BFDPROF]",
193 NO_STR IP6_STR OSPF6_STR
195 "BFD Profile selection\n"
196 "BFD Profile name\n")
198 VTY_DECLVAR_CONTEXT(interface
, ifp
);
199 struct ospf6_interface
*oi
;
202 oi
= (struct ospf6_interface
*)ifp
->info
;
204 oi
= ospf6_interface_create(ifp
);
207 /* BFD not enabled, nothing to do. */
208 if (!oi
->bfd_config
.enabled
)
211 /* Remove profile and apply new configuration. */
212 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
213 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
222 #endif /* HAVE_BFDD */
223 ipv6_ospf6_bfd_param
,
224 ipv6_ospf6_bfd_param_cmd
,
225 "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
228 "Enables BFD support\n"
229 "Detect Multiplier\n"
230 "Required min receive interval\n"
231 "Desired min transmit interval\n")
233 VTY_DECLVAR_CONTEXT(interface
, ifp
);
235 int idx_number_2
= 4;
236 int idx_number_3
= 5;
237 struct ospf6_interface
*oi
;
241 oi
= (struct ospf6_interface
*)ifp
->info
;
243 oi
= ospf6_interface_create(ifp
);
246 oi
->bfd_config
.detection_multiplier
=
247 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
248 oi
->bfd_config
.min_rx
= strtoul(argv
[idx_number_2
]->arg
, NULL
, 10);
249 oi
->bfd_config
.min_tx
= strtoul(argv
[idx_number_3
]->arg
, NULL
, 10);
250 oi
->bfd_config
.enabled
= true;
252 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
257 DEFUN (no_ipv6_ospf6_bfd
,
258 no_ipv6_ospf6_bfd_cmd
,
263 "Disables BFD support\n"
266 VTY_DECLVAR_CONTEXT(interface
, ifp
);
267 struct ospf6_interface
*oi
;
270 oi
= (struct ospf6_interface
*)ifp
->info
;
272 oi
= ospf6_interface_create(ifp
);
275 oi
->bfd_config
.enabled
= false;
276 ospf6_bfd_reg_dereg_all_nbr(oi
, false);
281 void ospf6_bfd_init(void)
283 bfd_protocol_integration_init(zclient
, master
);
285 /* Install BFD command */
286 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_cmd
);
287 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_param_cmd
);
288 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_profile_cmd
);
289 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_cmd
);