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