]>
Commit | Line | Data |
---|---|---|
7f342629 DS |
1 | /** |
2 | * ospf6_bfd.c: IPv6 OSPF BFD handling routines | |
3 | * | |
4 | * @copyright Copyright (C) 2015 Cumulus Networks, Inc. | |
5 | * | |
6 | * This file is part of GNU Zebra. | |
7 | * | |
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 | |
11 | * later version. | |
12 | * | |
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. | |
17 | * | |
896014f4 DL |
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 | |
7f342629 DS |
21 | */ |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "command.h" | |
26 | #include "linklist.h" | |
27 | #include "memory.h" | |
28 | #include "prefix.h" | |
29 | #include "thread.h" | |
30 | #include "buffer.h" | |
31 | #include "stream.h" | |
32 | #include "zclient.h" | |
33 | #include "vty.h" | |
34 | #include "table.h" | |
35 | #include "bfd.h" | |
36 | #include "if.h" | |
37 | #include "ospf6d.h" | |
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" | |
44 | ||
45 | extern struct zclient *zclient; | |
46 | ||
7f342629 DS |
47 | /* |
48 | * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when | |
49 | * neighbor state is changed to/from 2way. | |
50 | */ | |
d62a17ae | 51 | void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, |
52 | int state) | |
7f342629 | 53 | { |
d06cc416 RZ |
54 | int family; |
55 | struct in6_addr src, dst; | |
56 | ||
57 | /* Skip sessions without BFD. */ | |
58 | if (on->bfd_session == NULL) | |
59 | return; | |
60 | ||
61 | if (old_state < OSPF6_NEIGHBOR_TWOWAY | |
62 | && state >= OSPF6_NEIGHBOR_TWOWAY) { | |
63 | /* | |
64 | * Check if neighbor address changed. | |
65 | * | |
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. | |
70 | */ | |
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, | |
74 | &on->linklocal_addr); | |
75 | } | |
76 | ||
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); | |
7f342629 DS |
81 | } |
82 | ||
83 | /* | |
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. | |
88 | */ | |
d06cc416 RZ |
89 | static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi, |
90 | bool install) | |
7f342629 | 91 | { |
d62a17ae | 92 | struct ospf6_neighbor *on; |
93 | struct listnode *node; | |
94 | ||
95 | for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) { | |
d06cc416 RZ |
96 | /* Remove all sessions. */ |
97 | if (!install) { | |
98 | bfd_sess_free(&on->bfd_session); | |
d62a17ae | 99 | continue; |
100 | } | |
101 | ||
d06cc416 RZ |
102 | /* Always allocate session data even if not enabled. */ |
103 | ospf6_bfd_info_nbr_create(oi, on); | |
d62a17ae | 104 | |
d06cc416 RZ |
105 | /* |
106 | * If not connected yet, don't create any session but defer it | |
107 | * for later. See function `ospf6_bfd_trigger_event`. | |
108 | */ | |
109 | if (on->state < OSPF6_NEIGHBOR_TWOWAY) | |
d62a17ae | 110 | continue; |
111 | ||
d06cc416 | 112 | bfd_sess_install(on->bfd_session); |
d62a17ae | 113 | } |
7f342629 DS |
114 | } |
115 | ||
d06cc416 RZ |
116 | static void ospf6_bfd_callback(struct bfd_session_params *bsp, |
117 | const struct bfd_session_status *bss, void *arg) | |
7f342629 | 118 | { |
d06cc416 | 119 | struct ospf6_neighbor *on = arg; |
d62a17ae | 120 | |
d06cc416 RZ |
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); | |
d62a17ae | 125 | } |
7f342629 DS |
126 | } |
127 | ||
68fe91d6 | 128 | /* |
129 | * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor. | |
130 | */ | |
d62a17ae | 131 | void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi, |
132 | struct ospf6_neighbor *on) | |
68fe91d6 | 133 | { |
d06cc416 | 134 | if (!oi->bfd_config.enabled) |
d62a17ae | 135 | return; |
68fe91d6 | 136 | |
d06cc416 RZ |
137 | if (on->bfd_session == NULL) |
138 | on->bfd_session = bfd_sess_new(ospf6_bfd_callback, on); | |
68fe91d6 | 139 | |
d06cc416 RZ |
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); | |
63262607 | 146 | bfd_sess_set_vrf(on->bfd_session, oi->interface->vrf_id); |
d06cc416 | 147 | bfd_sess_set_profile(on->bfd_session, oi->bfd_config.profile); |
68fe91d6 | 148 | } |
149 | ||
7f342629 DS |
150 | /* |
151 | * ospf6_bfd_write_config - Write the interface BFD configuration. | |
152 | */ | |
d62a17ae | 153 | void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi) |
7f342629 | 154 | { |
d06cc416 | 155 | if (!oi->bfd_config.enabled) |
d62a17ae | 156 | return; |
7f342629 | 157 | |
a0841732 | 158 | #if HAVE_BFDD == 0 |
d06cc416 RZ |
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) | |
d62a17ae | 162 | vty_out(vty, " ipv6 ospf6 bfd %d %d %d\n", |
d06cc416 RZ |
163 | oi->bfd_config.detection_multiplier, |
164 | oi->bfd_config.min_rx, oi->bfd_config.min_tx); | |
d62a17ae | 165 | else |
a0841732 | 166 | #endif /* ! HAVE_BFDD */ |
d62a17ae | 167 | vty_out(vty, " ipv6 ospf6 bfd\n"); |
1f7be0d2 RZ |
168 | |
169 | if (oi->bfd_config.profile) | |
170 | vty_out(vty, " ipv6 ospf6 bfd profile %s\n", | |
171 | oi->bfd_config.profile); | |
7f342629 DS |
172 | } |
173 | ||
1f7be0d2 RZ |
174 | DEFUN(ipv6_ospf6_bfd, ipv6_ospf6_bfd_cmd, |
175 | "ipv6 ospf6 bfd [profile BFDPROF]", | |
176 | IP6_STR OSPF6_STR | |
177 | "Enables BFD support\n" | |
178 | "BFD Profile selection\n" | |
179 | "BFD Profile name\n") | |
7f342629 | 180 | { |
d62a17ae | 181 | VTY_DECLVAR_CONTEXT(interface, ifp); |
182 | struct ospf6_interface *oi; | |
1f7be0d2 | 183 | int prof_idx = 4; |
d62a17ae | 184 | assert(ifp); |
185 | ||
186 | oi = (struct ospf6_interface *)ifp->info; | |
187 | if (oi == NULL) | |
188 | oi = ospf6_interface_create(ifp); | |
189 | assert(oi); | |
190 | ||
d06cc416 RZ |
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; | |
1f7be0d2 RZ |
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); | |
199 | } | |
200 | ||
201 | ospf6_bfd_reg_dereg_all_nbr(oi, true); | |
202 | ||
203 | return CMD_SUCCESS; | |
204 | } | |
205 | ||
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 | |
209 | "BFD support\n" | |
210 | "BFD Profile selection\n" | |
211 | "BFD Profile name\n") | |
212 | { | |
213 | VTY_DECLVAR_CONTEXT(interface, ifp); | |
214 | struct ospf6_interface *oi; | |
215 | assert(ifp); | |
216 | ||
217 | oi = (struct ospf6_interface *)ifp->info; | |
218 | if (oi == NULL) | |
219 | oi = ospf6_interface_create(ifp); | |
220 | assert(oi); | |
221 | ||
222 | /* BFD not enabled, nothing to do. */ | |
223 | if (!oi->bfd_config.enabled) | |
224 | return CMD_SUCCESS; | |
d06cc416 | 225 | |
1f7be0d2 RZ |
226 | /* Remove profile and apply new configuration. */ |
227 | XFREE(MTYPE_TMP, oi->bfd_config.profile); | |
d06cc416 RZ |
228 | ospf6_bfd_reg_dereg_all_nbr(oi, true); |
229 | ||
d62a17ae | 230 | return CMD_SUCCESS; |
7f342629 DS |
231 | } |
232 | ||
64dc4b2d RZ |
233 | #if HAVE_BFDD > 0 |
234 | DEFUN_HIDDEN( | |
235 | #else | |
236 | DEFUN( | |
237 | #endif /* HAVE_BFDD */ | |
238 | ipv6_ospf6_bfd_param, | |
7f342629 | 239 | ipv6_ospf6_bfd_param_cmd, |
9ccf14f7 | 240 | "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)", |
7f342629 DS |
241 | IP6_STR |
242 | OSPF6_STR | |
243 | "Enables BFD support\n" | |
244 | "Detect Multiplier\n" | |
245 | "Required min receive interval\n" | |
246 | "Desired min transmit interval\n") | |
247 | { | |
d62a17ae | 248 | VTY_DECLVAR_CONTEXT(interface, ifp); |
249 | int idx_number = 3; | |
250 | int idx_number_2 = 4; | |
251 | int idx_number_3 = 5; | |
252 | struct ospf6_interface *oi; | |
d62a17ae | 253 | |
254 | assert(ifp); | |
255 | ||
256 | oi = (struct ospf6_interface *)ifp->info; | |
257 | if (oi == NULL) | |
258 | oi = ospf6_interface_create(ifp); | |
259 | assert(oi); | |
260 | ||
d06cc416 RZ |
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; | |
d62a17ae | 266 | |
d06cc416 | 267 | ospf6_bfd_reg_dereg_all_nbr(oi, true); |
d62a17ae | 268 | |
269 | return CMD_SUCCESS; | |
7f342629 DS |
270 | } |
271 | ||
272 | DEFUN (no_ipv6_ospf6_bfd, | |
273 | no_ipv6_ospf6_bfd_cmd, | |
274 | "no ipv6 ospf6 bfd", | |
275 | NO_STR | |
276 | IP6_STR | |
277 | OSPF6_STR | |
278 | "Disables BFD support\n" | |
279 | ) | |
280 | { | |
d62a17ae | 281 | VTY_DECLVAR_CONTEXT(interface, ifp); |
282 | struct ospf6_interface *oi; | |
283 | assert(ifp); | |
284 | ||
285 | oi = (struct ospf6_interface *)ifp->info; | |
286 | if (oi == NULL) | |
287 | oi = ospf6_interface_create(ifp); | |
288 | assert(oi); | |
289 | ||
d06cc416 RZ |
290 | oi->bfd_config.enabled = false; |
291 | ospf6_bfd_reg_dereg_all_nbr(oi, false); | |
d62a17ae | 292 | |
293 | return CMD_SUCCESS; | |
7f342629 DS |
294 | } |
295 | ||
d62a17ae | 296 | void ospf6_bfd_init(void) |
7f342629 | 297 | { |
d06cc416 | 298 | bfd_protocol_integration_init(zclient, master); |
7f342629 | 299 | |
d62a17ae | 300 | /* Install BFD command */ |
301 | install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_cmd); | |
302 | install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd); | |
1f7be0d2 | 303 | install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_profile_cmd); |
d62a17ae | 304 | install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd); |
7f342629 | 305 | } |