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_trigger_event - Neighbor is registered/deregistered with BFD when
49 * neighbor state is changed to/from 2way.
51 void ospf6_bfd_trigger_event(struct ospf6_neighbor
*on
, int old_state
,
55 struct in6_addr src
, dst
;
57 /* Skip sessions without BFD. */
58 if (on
->bfd_session
== NULL
)
61 if (old_state
< OSPF6_NEIGHBOR_TWOWAY
62 && state
>= OSPF6_NEIGHBOR_TWOWAY
) {
64 * Check if neighbor address changed.
66 * When the neighbor is configured BFD before having an existing
67 * connection, then the destination address will be set to `::`
68 * which will cause session installation failure. This piece of
69 * code updates the address in that case.
71 bfd_sess_addresses(on
->bfd_session
, &family
, &src
, &dst
);
72 if (memcmp(&on
->linklocal_addr
, &dst
, sizeof(dst
))) {
73 bfd_sess_set_ipv6_addrs(on
->bfd_session
, &src
,
77 bfd_sess_install(on
->bfd_session
);
78 } else if (old_state
>= OSPF6_NEIGHBOR_TWOWAY
79 && state
< OSPF6_NEIGHBOR_TWOWAY
)
80 bfd_sess_uninstall(on
->bfd_session
);
84 * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
85 * with a interface with BFD through
86 * zebra for starting/stopping the monitoring of
87 * the neighbor rechahability.
89 static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface
*oi
,
92 struct ospf6_neighbor
*on
;
93 struct listnode
*node
;
95 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, node
, on
)) {
96 /* Remove all sessions. */
98 bfd_sess_free(&on
->bfd_session
);
102 /* Always allocate session data even if not enabled. */
103 ospf6_bfd_info_nbr_create(oi
, on
);
106 * If not connected yet, don't create any session but defer it
107 * for later. See function `ospf6_bfd_trigger_event`.
109 if (on
->state
< OSPF6_NEIGHBOR_TWOWAY
)
112 bfd_sess_install(on
->bfd_session
);
116 static void ospf6_bfd_callback(struct bfd_session_params
*bsp
,
117 const struct bfd_session_status
*bss
, void *arg
)
119 struct ospf6_neighbor
*on
= arg
;
121 if (bss
->state
== BFD_STATUS_DOWN
122 && bss
->previous_state
== BFD_STATUS_UP
) {
123 THREAD_OFF(on
->inactivity_timer
);
124 thread_add_event(master
, inactivity_timer
, on
, 0, NULL
);
129 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
131 void ospf6_bfd_info_nbr_create(struct ospf6_interface
*oi
,
132 struct ospf6_neighbor
*on
)
134 if (!oi
->bfd_config
.enabled
)
137 if (on
->bfd_session
== NULL
)
138 on
->bfd_session
= bfd_sess_new(ospf6_bfd_callback
, on
);
140 bfd_sess_set_timers(on
->bfd_session
,
141 oi
->bfd_config
.detection_multiplier
,
142 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
143 bfd_sess_set_ipv6_addrs(on
->bfd_session
, on
->ospf6_if
->linklocal_addr
,
144 &on
->linklocal_addr
);
145 bfd_sess_set_interface(on
->bfd_session
, oi
->interface
->name
);
146 bfd_sess_set_vrf(on
->bfd_session
, oi
->interface
->vrf
->vrf_id
);
147 bfd_sess_set_profile(on
->bfd_session
, oi
->bfd_config
.profile
);
151 * ospf6_bfd_write_config - Write the interface BFD configuration.
153 void ospf6_bfd_write_config(struct vty
*vty
, struct ospf6_interface
*oi
)
155 if (!oi
->bfd_config
.enabled
)
159 if (oi
->bfd_config
.detection_multiplier
!= BFD_DEF_DETECT_MULT
160 || oi
->bfd_config
.min_rx
!= BFD_DEF_MIN_RX
161 || oi
->bfd_config
.min_tx
!= BFD_DEF_MIN_TX
)
162 vty_out(vty
, " ipv6 ospf6 bfd %d %d %d\n",
163 oi
->bfd_config
.detection_multiplier
,
164 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
166 #endif /* ! HAVE_BFDD */
167 vty_out(vty
, " ipv6 ospf6 bfd\n");
169 if (oi
->bfd_config
.profile
)
170 vty_out(vty
, " ipv6 ospf6 bfd profile %s\n",
171 oi
->bfd_config
.profile
);
174 DEFUN(ipv6_ospf6_bfd
, ipv6_ospf6_bfd_cmd
,
175 "ipv6 ospf6 bfd [profile BFDPROF]",
177 "Enables BFD support\n"
178 "BFD Profile selection\n"
179 "BFD Profile name\n")
181 VTY_DECLVAR_CONTEXT(interface
, ifp
);
182 struct ospf6_interface
*oi
;
186 oi
= (struct ospf6_interface
*)ifp
->info
;
188 oi
= ospf6_interface_create(ifp
);
191 oi
->bfd_config
.detection_multiplier
= BFD_DEF_DETECT_MULT
;
192 oi
->bfd_config
.min_rx
= BFD_DEF_MIN_RX
;
193 oi
->bfd_config
.min_tx
= BFD_DEF_MIN_TX
;
194 oi
->bfd_config
.enabled
= true;
195 if (argc
> prof_idx
) {
196 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
197 oi
->bfd_config
.profile
=
198 XSTRDUP(MTYPE_TMP
, argv
[prof_idx
]->arg
);
201 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
206 DEFUN(no_ipv6_ospf6_bfd_profile
, no_ipv6_ospf6_bfd_profile_cmd
,
207 "no ipv6 ospf6 bfd profile [BFDPROF]",
208 NO_STR IP6_STR OSPF6_STR
210 "BFD Profile selection\n"
211 "BFD Profile name\n")
213 VTY_DECLVAR_CONTEXT(interface
, ifp
);
214 struct ospf6_interface
*oi
;
217 oi
= (struct ospf6_interface
*)ifp
->info
;
219 oi
= ospf6_interface_create(ifp
);
222 /* BFD not enabled, nothing to do. */
223 if (!oi
->bfd_config
.enabled
)
226 /* Remove profile and apply new configuration. */
227 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
228 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
237 #endif /* HAVE_BFDD */
238 ipv6_ospf6_bfd_param
,
239 ipv6_ospf6_bfd_param_cmd
,
240 "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
243 "Enables BFD support\n"
244 "Detect Multiplier\n"
245 "Required min receive interval\n"
246 "Desired min transmit interval\n")
248 VTY_DECLVAR_CONTEXT(interface
, ifp
);
250 int idx_number_2
= 4;
251 int idx_number_3
= 5;
252 struct ospf6_interface
*oi
;
256 oi
= (struct ospf6_interface
*)ifp
->info
;
258 oi
= ospf6_interface_create(ifp
);
261 oi
->bfd_config
.detection_multiplier
=
262 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
263 oi
->bfd_config
.min_rx
= strtoul(argv
[idx_number_2
]->arg
, NULL
, 10);
264 oi
->bfd_config
.min_tx
= strtoul(argv
[idx_number_3
]->arg
, NULL
, 10);
265 oi
->bfd_config
.enabled
= true;
267 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
272 DEFUN (no_ipv6_ospf6_bfd
,
273 no_ipv6_ospf6_bfd_cmd
,
278 "Disables BFD support\n"
281 VTY_DECLVAR_CONTEXT(interface
, ifp
);
282 struct ospf6_interface
*oi
;
285 oi
= (struct ospf6_interface
*)ifp
->info
;
287 oi
= ospf6_interface_create(ifp
);
290 oi
->bfd_config
.enabled
= false;
291 ospf6_bfd_reg_dereg_all_nbr(oi
, false);
296 void ospf6_bfd_init(void)
298 bfd_protocol_integration_init(zclient
, master
);
300 /* Install BFD command */
301 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_cmd
);
302 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_param_cmd
);
303 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_profile_cmd
);
304 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_cmd
);