]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_bfd.c
zebra: CHECK ME fixes
[mirror_frr.git] / ospf6d / ospf6_bfd.c
CommitLineData
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 *
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
46extern struct zclient *zclient;
47
68fe91d6 48/*
49 * ospf6_bfd_info_free - Free BFD info structure
50 */
51void
52ospf6_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 */
60void
61ospf6_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
7f342629
DS
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 */
1eab5b17 74void
7f342629
DS
75ospf6_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
1eab5b17 82 if (!oi->bfd_info || !on->bfd_info)
7f342629
DS
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,
7076bb2f 95 0, 0, command, 0, VRF_DEFAULT);
1eab5b17 96
97 if (command == ZEBRA_BFD_DEST_DEREGISTER)
98 bfd_info_free((struct bfd_info **)&on->bfd_info);
7f342629
DS
99}
100
101/*
102 * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
103 * neighbor state is changed to/from 2way.
104 */
105void
106ospf6_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 */
121static void
122ospf6_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 {
1eab5b17 129 if (command == ZEBRA_BFD_DEST_REGISTER)
68fe91d6 130 ospf6_bfd_info_nbr_create(oi, on);
68fe91d6 131
7f342629 132 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
1eab5b17 133 {
134 if (command == ZEBRA_BFD_DEST_DEREGISTER)
135 bfd_info_free((struct bfd_info **)&on->bfd_info);
136 continue;
137 }
138
7f342629
DS
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 */
147static int
055c4dfc 148ospf6_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length,
7076bb2f 149 vrf_id_t vrf_id)
7f342629
DS
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
055c4dfc 160 /* Send the client registration */
161 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
162
7f342629 163 /* Replay the neighbor, if BFD is enabled on the interface*/
b2d7c082 164 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), inode, ifp))
7f342629
DS
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/*
68fe91d6 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.
7f342629
DS
192 */
193static int
68fe91d6 194ospf6_bfd_interface_dest_update (int command, struct zclient *zclient,
7076bb2f 195 zebra_size_t length, vrf_id_t vrf_id)
7f342629
DS
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];
68fe91d6 204 int status;
205 int old_status;
206 struct bfd_info *bfd_info;
207 struct timeval tv;
7f342629 208
1e22a2af 209 ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
7f342629
DS
210
211 if ((ifp == NULL) || (dp.family != AF_INET6))
212 return 0;
213
214 if (IS_OSPF6_DEBUG_ZEBRA (RECV))
215 {
4690c7d7 216 char buf[PREFIX2STR_BUFFER];
7f342629 217 prefix2str(&dp, buf, sizeof(buf));
68fe91d6 218 zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
219 bfd_get_status_str(status));
7f342629
DS
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));
68fe91d6 235 zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst,
236 bfd_get_status_str(status));
7f342629
DS
237 }
238
68fe91d6 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 quagga_gettime (QUAGGA_CLK_MONOTONIC, &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 }
7f342629
DS
256 }
257
258 return 0;
259}
260
68fe91d6 261/*
262 * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
263 */
264void
265ospf6_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
7f342629
DS
285/*
286 * ospf6_bfd_write_config - Write the interface BFD configuration.
287 */
288void
289ospf6_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 */
310static void
311ospf6_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
323DEFUN (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 struct ospf6_interface *oi;
332 struct interface *ifp;
333
334 ifp = (struct interface *) vty->index;
335 assert (ifp);
336
337 oi = (struct ospf6_interface *) ifp->info;
338 if (oi == NULL)
339 oi = ospf6_interface_create (ifp);
340 assert (oi);
341
342 ospf6_bfd_if_param_set (oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
343 BFD_DEF_DETECT_MULT, 1);
344 return CMD_SUCCESS;
345}
346
347DEFUN (ipv6_ospf6_bfd_param,
348 ipv6_ospf6_bfd_param_cmd,
349 "ipv6 ospf6 bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
350 IP6_STR
351 OSPF6_STR
352 "Enables BFD support\n"
353 "Detect Multiplier\n"
354 "Required min receive interval\n"
355 "Desired min transmit interval\n")
356{
51c26414
DW
357 int idx_number = 3;
358 int idx_number_2 = 4;
359 int idx_number_3 = 5;
7f342629
DS
360 struct ospf6_interface *oi;
361 struct interface *ifp;
362 u_int32_t rx_val;
363 u_int32_t tx_val;
364 u_int8_t dm_val;
365 int ret;
366
367 ifp = (struct interface *) vty->index;
368 assert (ifp);
369
370 oi = (struct ospf6_interface *) ifp->info;
371 if (oi == NULL)
372 oi = ospf6_interface_create (ifp);
373 assert (oi);
374
51c26414 375 if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val,
7f342629
DS
376 &rx_val, &tx_val)) != CMD_SUCCESS)
377 return ret;
378
379 ospf6_bfd_if_param_set (oi, rx_val, tx_val, dm_val, 0);
380
381 return CMD_SUCCESS;
382}
383
384DEFUN (no_ipv6_ospf6_bfd,
385 no_ipv6_ospf6_bfd_cmd,
386 "no ipv6 ospf6 bfd",
387 NO_STR
388 IP6_STR
389 OSPF6_STR
390 "Disables BFD support\n"
391 )
392{
393 struct ospf6_interface *oi;
394 struct interface *ifp;
395
396 ifp = (struct interface *) vty->index;
397 assert (ifp);
398
399 oi = (struct ospf6_interface *) ifp->info;
400 if (oi == NULL)
401 oi = ospf6_interface_create (ifp);
402 assert (oi);
403
404 if (oi->bfd_info)
405 {
406 ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
68fe91d6 407 bfd_info_free((struct bfd_info **)&(oi->bfd_info));
7f342629
DS
408 }
409
410 return CMD_SUCCESS;
411}
412
413void
414ospf6_bfd_init(void)
415{
567b877d 416 bfd_gbl_init();
417
7f342629 418 /* Initialize BFD client functions */
68fe91d6 419 zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
7f342629
DS
420 zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
421
422 /* Install BFD command */
423 install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
424 install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
425 install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
426}