]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_bfd.c
Merge remote-tracking branch 'origin/stable/2.0'
[mirror_frr.git] / ospf6d / ospf6_bfd.c
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 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 */
23
24 #include <zebra.h>
25
26 #include "command.h"
27 #include "linklist.h"
28 #include "memory.h"
29 #include "prefix.h"
30 #include "thread.h"
31 #include "buffer.h"
32 #include "stream.h"
33 #include "zclient.h"
34 #include "vty.h"
35 #include "table.h"
36 #include "bfd.h"
37 #include "if.h"
38 #include "ospf6d.h"
39 #include "ospf6_message.h"
40 #include "ospf6_neighbor.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_route.h"
43 #include "ospf6_zebra.h"
44 #include "ospf6_bfd.h"
45
46 extern struct zclient *zclient;
47
48 /*
49 * ospf6_bfd_info_free - Free BFD info structure
50 */
51 void
52 ospf6_bfd_info_free(void **bfd_info)
53 {
54 bfd_info_free((struct bfd_info **) bfd_info);
55 }
56
57 /*
58 * ospf6_bfd_show_info - Show BFD info structure
59 */
60 void
61 ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only)
62 {
63 if (param_only)
64 bfd_show_param(vty, bfd_info, 1, 0, 0, NULL);
65 else
66 bfd_show_info(vty, bfd_info, 0, 1, 0, NULL);
67 }
68
69 /*
70 * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
71 * zebra for starting/stopping the monitoring of
72 * the neighbor rechahability.
73 */
74 void
75 ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor *on, int command)
76 {
77 struct ospf6_interface *oi = on->ospf6_if;
78 struct interface *ifp = oi->interface;
79 struct bfd_info *bfd_info;
80 char src[64];
81
82 if (!oi->bfd_info || !on->bfd_info)
83 return;
84 bfd_info = (struct bfd_info *)oi->bfd_info;
85
86 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
87 {
88 inet_ntop (AF_INET6, &on->linklocal_addr, src, sizeof (src));
89 zlog_debug ("%s nbr (%s) with BFD",
90 bfd_get_command_dbg_str(command), src);
91 }
92
93 bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, &on->linklocal_addr,
94 on->ospf6_if->linklocal_addr, ifp->name,
95 0, 0, command, 0, VRF_DEFAULT);
96
97 if (command == ZEBRA_BFD_DEST_DEREGISTER)
98 bfd_info_free((struct bfd_info **)&on->bfd_info);
99 }
100
101 /*
102 * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
103 * neighbor state is changed to/from 2way.
104 */
105 void
106 ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, int state)
107 {
108 if ((old_state < OSPF6_NEIGHBOR_TWOWAY) && (state >= OSPF6_NEIGHBOR_TWOWAY))
109 ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER);
110 else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY) &&
111 (state < OSPF6_NEIGHBOR_TWOWAY))
112 ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER);
113 }
114
115 /*
116 * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated
117 * with a interface with BFD through
118 * zebra for starting/stopping the monitoring of
119 * the neighbor rechahability.
120 */
121 static void
122 ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command)
123 {
124 struct ospf6_neighbor *on;
125 struct listnode *node;
126
127 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on))
128 {
129 if (command == ZEBRA_BFD_DEST_REGISTER)
130 ospf6_bfd_info_nbr_create(oi, on);
131
132 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
133 {
134 if (command == ZEBRA_BFD_DEST_DEREGISTER)
135 bfd_info_free((struct bfd_info **)&on->bfd_info);
136 continue;
137 }
138
139 ospf6_bfd_reg_dereg_nbr(on, command);
140 }
141 }
142
143 /*
144 * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
145 * to zebra
146 */
147 static int
148 ospf6_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length,
149 vrf_id_t vrf_id)
150 {
151 struct listnode *inode, *nnode;
152 struct interface *ifp;
153 struct ospf6_interface *oi;
154 struct ospf6_neighbor *on;
155 char dst[64];
156
157 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
158 zlog_debug("Zebra: BFD Dest replay request");
159
160 /* Send the client registration */
161 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
162
163 /* Replay the neighbor, if BFD is enabled on the interface*/
164 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), inode, ifp))
165 {
166 oi = (struct ospf6_interface *) ifp->info;
167
168 if (!oi || !oi->bfd_info)
169 continue;
170
171 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, nnode, on))
172 {
173 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
174 continue;
175
176 if (IS_OSPF6_DEBUG_ZEBRA(SEND))
177 {
178 inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst));
179 zlog_debug ("Replaying nbr (%s) to BFD", dst);
180 }
181
182 ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE);
183 }
184 }
185 return 0;
186 }
187
188 /*
189 * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
190 * has changed and bring down the neighbor
191 * connectivity if BFD down is received.
192 */
193 static int
194 ospf6_bfd_interface_dest_update (int command, struct zclient *zclient,
195 zebra_size_t length, vrf_id_t vrf_id)
196 {
197 struct interface *ifp;
198 struct ospf6_interface *oi;
199 struct ospf6_neighbor *on;
200 struct prefix dp;
201 struct prefix sp;
202 struct listnode *node, *nnode;
203 char dst[64];
204 int status;
205 int old_status;
206 struct bfd_info *bfd_info;
207 struct timeval tv;
208
209 ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
210
211 if ((ifp == NULL) || (dp.family != AF_INET6))
212 return 0;
213
214 if (IS_OSPF6_DEBUG_ZEBRA (RECV))
215 {
216 char buf[PREFIX2STR_BUFFER];
217 prefix2str(&dp, buf, sizeof(buf));
218 zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
219 bfd_get_status_str(status));
220 }
221
222
223 oi = (struct ospf6_interface *) ifp->info;
224 if (!oi || !oi->bfd_info)
225 return 0;
226
227 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
228 {
229 if (memcmp(&(on->linklocal_addr), &dp.u.prefix6, sizeof(struct in6_addr)))
230 continue;
231
232 if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
233 {
234 inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst));
235 zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst,
236 bfd_get_status_str(status));
237 }
238
239 if (!on->bfd_info)
240 continue;
241
242 bfd_info = (struct bfd_info *)on->bfd_info;
243 if (bfd_info->status == status)
244 continue;
245
246 old_status = bfd_info->status;
247 bfd_info->status = status;
248 monotime(&tv);
249 bfd_info->last_update = tv.tv_sec;
250
251 if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
252 {
253 THREAD_OFF (on->inactivity_timer);
254 thread_add_event (master, inactivity_timer, on, 0);
255 }
256 }
257
258 return 0;
259 }
260
261 /*
262 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
263 */
264 void
265 ospf6_bfd_info_nbr_create (struct ospf6_interface *oi,
266 struct ospf6_neighbor *on)
267 {
268 struct bfd_info *oi_bfd_info;
269 struct bfd_info *on_bfd_info;
270
271 if (!oi->bfd_info)
272 return;
273
274 oi_bfd_info = (struct bfd_info *)oi->bfd_info;
275
276 if (!on->bfd_info)
277 on->bfd_info = bfd_info_create();
278
279 on_bfd_info = (struct bfd_info *)on->bfd_info;
280 on_bfd_info->detect_mult = oi_bfd_info->detect_mult;
281 on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
282 on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
283 }
284
285 /*
286 * ospf6_bfd_write_config - Write the interface BFD configuration.
287 */
288 void
289 ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi)
290 {
291 struct bfd_info *bfd_info;
292
293 if (!oi->bfd_info)
294 return;
295
296 bfd_info = (struct bfd_info *)oi->bfd_info;
297
298 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
299 vty_out (vty, " ipv6 ospf6 bfd %d %d %d%s",
300 bfd_info->detect_mult, bfd_info->required_min_rx,
301 bfd_info->desired_min_tx, VTY_NEWLINE);
302 else
303 vty_out (vty, " ipv6 ospf6 bfd%s", VTY_NEWLINE);
304 }
305
306 /*
307 * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
308 * interface.
309 */
310 static void
311 ospf6_bfd_if_param_set (struct ospf6_interface *oi, u_int32_t min_rx,
312 u_int32_t min_tx, u_int8_t detect_mult,
313 int defaults)
314 {
315 int command = 0;
316
317 bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, detect_mult,
318 defaults, &command);
319 if (command)
320 ospf6_bfd_reg_dereg_all_nbr(oi, command);
321 }
322
323 DEFUN (ipv6_ospf6_bfd,
324 ipv6_ospf6_bfd_cmd,
325 "ipv6 ospf6 bfd",
326 IP6_STR
327 OSPF6_STR
328 "Enables BFD support\n"
329 )
330 {
331 VTY_DECLVAR_CONTEXT(interface, ifp);
332 struct ospf6_interface *oi;
333 assert (ifp);
334
335 oi = (struct ospf6_interface *) ifp->info;
336 if (oi == NULL)
337 oi = ospf6_interface_create (ifp);
338 assert (oi);
339
340 ospf6_bfd_if_param_set (oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
341 BFD_DEF_DETECT_MULT, 1);
342 return CMD_SUCCESS;
343 }
344
345 DEFUN (ipv6_ospf6_bfd_param,
346 ipv6_ospf6_bfd_param_cmd,
347 "ipv6 ospf6 bfd (2-255) (50-60000) (50-60000)",
348 IP6_STR
349 OSPF6_STR
350 "Enables BFD support\n"
351 "Detect Multiplier\n"
352 "Required min receive interval\n"
353 "Desired min transmit interval\n")
354 {
355 VTY_DECLVAR_CONTEXT(interface, ifp);
356 int idx_number = 3;
357 int idx_number_2 = 4;
358 int idx_number_3 = 5;
359 struct ospf6_interface *oi;
360 u_int32_t rx_val;
361 u_int32_t tx_val;
362 u_int8_t dm_val;
363 int ret;
364
365 assert (ifp);
366
367 oi = (struct ospf6_interface *) ifp->info;
368 if (oi == NULL)
369 oi = ospf6_interface_create (ifp);
370 assert (oi);
371
372 if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val,
373 &rx_val, &tx_val)) != CMD_SUCCESS)
374 return ret;
375
376 ospf6_bfd_if_param_set (oi, rx_val, tx_val, dm_val, 0);
377
378 return CMD_SUCCESS;
379 }
380
381 DEFUN (no_ipv6_ospf6_bfd,
382 no_ipv6_ospf6_bfd_cmd,
383 "no ipv6 ospf6 bfd",
384 NO_STR
385 IP6_STR
386 OSPF6_STR
387 "Disables BFD support\n"
388 )
389 {
390 VTY_DECLVAR_CONTEXT(interface, ifp);
391 struct ospf6_interface *oi;
392 assert (ifp);
393
394 oi = (struct ospf6_interface *) ifp->info;
395 if (oi == NULL)
396 oi = ospf6_interface_create (ifp);
397 assert (oi);
398
399 if (oi->bfd_info)
400 {
401 ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
402 bfd_info_free((struct bfd_info **)&(oi->bfd_info));
403 }
404
405 return CMD_SUCCESS;
406 }
407
408 void
409 ospf6_bfd_init(void)
410 {
411 bfd_gbl_init();
412
413 /* Initialize BFD client functions */
414 zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
415 zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
416
417 /* Install BFD command */
418 install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
419 install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
420 install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
421 }