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_profile(on
->bfd_session
, oi
->bfd_config
.profile
);
150 * ospf6_bfd_write_config - Write the interface BFD configuration.
152 void ospf6_bfd_write_config(struct vty
*vty
, struct ospf6_interface
*oi
)
154 if (!oi
->bfd_config
.enabled
)
158 if (oi
->bfd_config
.detection_multiplier
!= BFD_DEF_DETECT_MULT
159 || oi
->bfd_config
.min_rx
!= BFD_DEF_MIN_RX
160 || oi
->bfd_config
.min_tx
!= BFD_DEF_MIN_TX
)
161 vty_out(vty
, " ipv6 ospf6 bfd %d %d %d\n",
162 oi
->bfd_config
.detection_multiplier
,
163 oi
->bfd_config
.min_rx
, oi
->bfd_config
.min_tx
);
165 #endif /* ! HAVE_BFDD */
166 vty_out(vty
, " ipv6 ospf6 bfd\n");
168 if (oi
->bfd_config
.profile
)
169 vty_out(vty
, " ipv6 ospf6 bfd profile %s\n",
170 oi
->bfd_config
.profile
);
173 DEFUN(ipv6_ospf6_bfd
, ipv6_ospf6_bfd_cmd
,
174 "ipv6 ospf6 bfd [profile BFDPROF]",
176 "Enables BFD support\n"
177 "BFD Profile selection\n"
178 "BFD Profile name\n")
180 VTY_DECLVAR_CONTEXT(interface
, ifp
);
181 struct ospf6_interface
*oi
;
185 oi
= (struct ospf6_interface
*)ifp
->info
;
187 oi
= ospf6_interface_create(ifp
);
190 oi
->bfd_config
.detection_multiplier
= BFD_DEF_DETECT_MULT
;
191 oi
->bfd_config
.min_rx
= BFD_DEF_MIN_RX
;
192 oi
->bfd_config
.min_tx
= BFD_DEF_MIN_TX
;
193 oi
->bfd_config
.enabled
= true;
194 if (argc
> prof_idx
) {
195 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
196 oi
->bfd_config
.profile
=
197 XSTRDUP(MTYPE_TMP
, argv
[prof_idx
]->arg
);
200 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
205 DEFUN(no_ipv6_ospf6_bfd_profile
, no_ipv6_ospf6_bfd_profile_cmd
,
206 "no ipv6 ospf6 bfd profile [BFDPROF]",
207 NO_STR IP6_STR OSPF6_STR
209 "BFD Profile selection\n"
210 "BFD Profile name\n")
212 VTY_DECLVAR_CONTEXT(interface
, ifp
);
213 struct ospf6_interface
*oi
;
216 oi
= (struct ospf6_interface
*)ifp
->info
;
218 oi
= ospf6_interface_create(ifp
);
221 /* BFD not enabled, nothing to do. */
222 if (!oi
->bfd_config
.enabled
)
225 /* Remove profile and apply new configuration. */
226 XFREE(MTYPE_TMP
, oi
->bfd_config
.profile
);
227 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
236 #endif /* HAVE_BFDD */
237 ipv6_ospf6_bfd_param
,
238 ipv6_ospf6_bfd_param_cmd
,
239 "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
242 "Enables BFD support\n"
243 "Detect Multiplier\n"
244 "Required min receive interval\n"
245 "Desired min transmit interval\n")
247 VTY_DECLVAR_CONTEXT(interface
, ifp
);
249 int idx_number_2
= 4;
250 int idx_number_3
= 5;
251 struct ospf6_interface
*oi
;
255 oi
= (struct ospf6_interface
*)ifp
->info
;
257 oi
= ospf6_interface_create(ifp
);
260 oi
->bfd_config
.detection_multiplier
=
261 strtoul(argv
[idx_number
]->arg
, NULL
, 10);
262 oi
->bfd_config
.min_rx
= strtoul(argv
[idx_number_2
]->arg
, NULL
, 10);
263 oi
->bfd_config
.min_tx
= strtoul(argv
[idx_number_3
]->arg
, NULL
, 10);
264 oi
->bfd_config
.enabled
= true;
266 ospf6_bfd_reg_dereg_all_nbr(oi
, true);
271 DEFUN (no_ipv6_ospf6_bfd
,
272 no_ipv6_ospf6_bfd_cmd
,
277 "Disables BFD support\n"
280 VTY_DECLVAR_CONTEXT(interface
, ifp
);
281 struct ospf6_interface
*oi
;
284 oi
= (struct ospf6_interface
*)ifp
->info
;
286 oi
= ospf6_interface_create(ifp
);
289 oi
->bfd_config
.enabled
= false;
290 ospf6_bfd_reg_dereg_all_nbr(oi
, false);
295 void ospf6_bfd_init(void)
297 bfd_protocol_integration_init(zclient
, master
);
299 /* Install BFD command */
300 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_cmd
);
301 install_element(INTERFACE_NODE
, &ipv6_ospf6_bfd_param_cmd
);
302 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_profile_cmd
);
303 install_element(INTERFACE_NODE
, &no_ipv6_ospf6_bfd_cmd
);