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