]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bfd.c
Quagga: Fixup some compile warnings
[mirror_frr.git] / bgpd / bgp_bfd.c
CommitLineData
c43ed2e4
DS
1/**
2 * bgp_bfd.c: BGP 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"
7f342629 35#include "bfd.h"
856ca177 36#include "lib/json.h"
c43ed2e4 37#include "bgpd/bgpd.h"
7f342629 38#include "bgp_fsm.h"
c43ed2e4
DS
39#include "bgpd/bgp_bfd.h"
40#include "bgpd/bgp_debug.h"
41#include "bgpd/bgp_vty.h"
42
43extern struct zclient *zclient;
44
c43ed2e4
DS
45/*
46 * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template
47 * to peer.
48 */
49void
50bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
51{
7f342629
DS
52 struct bfd_info *bfd_info;
53 struct bfd_info *conf_bfd_info;
54
55 if (!conf->bfd_info)
56 return;
57
58 conf_bfd_info = (struct bfd_info *)conf->bfd_info;
59 if (!peer->bfd_info)
60 peer->bfd_info = bfd_info_create();
c43ed2e4 61
7f342629 62 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4
DS
63
64 /* Copy BFD parameter values */
65 bfd_info->required_min_rx = conf_bfd_info->required_min_rx;
66 bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx;
67 bfd_info->detect_mult = conf_bfd_info->detect_mult;
68}
69
70/*
71 * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop.
72 */
73static int
74bgp_bfd_is_peer_multihop(struct peer *peer)
75{
68fe91d6 76 if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) ||
77 is_ebgp_multihop_configured(peer)))
c43ed2e4
DS
78 return 1;
79 else
80 return 0;
81}
82
83/*
7f342629
DS
84 * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
85 * command to Zebra to be forwarded to BFD
c43ed2e4
DS
86 */
87static void
7f342629 88bgp_bfd_peer_sendmsg (struct peer *peer, int command)
c43ed2e4 89{
7f342629
DS
90 struct bfd_info *bfd_info;
91
92 bfd_info = (struct bfd_info *)peer->bfd_info;
93
94 if (peer->su.sa.sa_family == AF_INET)
95 bfd_peer_sendmsg (zclient, bfd_info, AF_INET,
96 &peer->su.sin.sin_addr,
97 (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
98 (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
7076bb2f 99 peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, VRF_DEFAULT);
7f342629
DS
100 else if (peer->su.sa.sa_family == AF_INET6)
101 bfd_peer_sendmsg (zclient, bfd_info, AF_INET6,
102 &peer->su.sin6.sin6_addr,
103 (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL,
104 (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
7076bb2f 105 peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, VRF_DEFAULT);
c43ed2e4
DS
106}
107
108/*
109 * bgp_bfd_register_peer - register a peer with BFD through zebra
110 * for monitoring the peer rechahability.
111 */
112void
113bgp_bfd_register_peer (struct peer *peer)
114{
7f342629 115 struct bfd_info *bfd_info;
c43ed2e4 116
7f342629
DS
117 if (!peer->bfd_info)
118 return;
119 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4
DS
120
121 /* Check if BFD is enabled and peer has already been registered with BFD */
7f342629 122 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
c43ed2e4
DS
123 return;
124
7f342629 125 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
c43ed2e4
DS
126}
127
128/**
129 * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra
130 * for stopping the monitoring of the peer
131 * rechahability.
132 */
133void
134bgp_bfd_deregister_peer (struct peer *peer)
135{
7f342629 136 struct bfd_info *bfd_info;
c43ed2e4 137
7f342629
DS
138 if (!peer->bfd_info)
139 return;
140 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4
DS
141
142 /* Check if BFD is eanbled and peer has not been registered */
7f342629 143 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
c43ed2e4
DS
144 return;
145
7f342629 146 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
c43ed2e4
DS
147}
148
149/*
150 * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
151 * through zebra.
152 */
7f342629 153static void
c43ed2e4
DS
154bgp_bfd_update_peer (struct peer *peer)
155{
7f342629 156 struct bfd_info *bfd_info;
c43ed2e4 157
7f342629
DS
158 if (!peer->bfd_info)
159 return;
160 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4
DS
161
162 /* Check if the peer has been registered with BFD*/
7f342629 163 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
c43ed2e4
DS
164 return;
165
7f342629 166 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
c43ed2e4
DS
167}
168
169/*
170 * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
171 * to zebra
172 */
7f342629 173static int
7076bb2f
FL
174bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length,
175 vrf_id_t vrf_id)
c43ed2e4
DS
176{
177 struct listnode *mnode, *node, *nnode;
178 struct bgp *bgp;
179 struct peer *peer;
180
181 if (BGP_DEBUG (zebra, ZEBRA))
182 zlog_debug("Zebra: BFD Dest replay request");
183
184 /* Replay the peer, if BFD is enabled in BGP */
185
186 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
187 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
188 {
c43ed2e4
DS
189 bgp_bfd_update_peer(peer);
190 }
191
192 return 0;
193}
194
195/*
68fe91d6 196 * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
197 * down the peer if the BFD session went down from * up.
198 */
199static void
200bgp_bfd_peer_status_update (struct peer *peer, int status)
201{
202 struct bfd_info *bfd_info;
203 int old_status;
204
205 bfd_info = (struct bfd_info *)peer->bfd_info;
206
207 if (bfd_info->status == status)
208 return;
209
210 old_status = bfd_info->status;
211 bfd_info->status = status;
212 bfd_info->last_update = bgp_clock();
213
214 if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
215 {
216 peer->last_reset = PEER_DOWN_BFD_DOWN;
217 BGP_EVENT_ADD (peer, BGP_Stop);
218 }
219}
220
221/*
222 * bgp_bfd_dest_update - Find the peer for which the BFD status
223 * has changed and bring down the peer
224 * connectivity if the BFD session went down.
c43ed2e4 225 */
7f342629 226static int
68fe91d6 227bgp_bfd_dest_update (int command, struct zclient *zclient,
7076bb2f 228 zebra_size_t length, vrf_id_t vrf_id)
c43ed2e4
DS
229{
230 struct interface *ifp;
231 struct prefix dp;
232 struct prefix sp;
68fe91d6 233 int status;
c43ed2e4 234
68fe91d6 235 ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status);
c43ed2e4
DS
236
237 if (BGP_DEBUG (zebra, ZEBRA))
238 {
239 char buf[2][128];
240 prefix2str(&dp, buf[0], sizeof(buf[0]));
241 if (ifp)
242 {
68fe91d6 243 zlog_debug("Zebra: interface %s bfd destination %s %s",
244 ifp->name, buf[0], bfd_get_status_str(status));
c43ed2e4
DS
245 }
246 else
247 {
248 prefix2str(&sp, buf[1], sizeof(buf[1]));
68fe91d6 249 zlog_debug("Zebra: source %s bfd destination %s %s",
250 buf[1], buf[0], bfd_get_status_str(status));
c43ed2e4
DS
251 }
252 }
253
254 /* Bring the peer down if BFD is enabled in BGP */
255 {
256 struct listnode *mnode, *node, *nnode;
257 struct bgp *bgp;
258 struct peer *peer;
259
260 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
261 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
262 {
7f342629 263 if (!peer->bfd_info)
c43ed2e4
DS
264 continue;
265
7bbc6864
DS
266 if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET))
267 {
268 if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr)
269 continue;
270 }
c43ed2e4 271#ifdef HAVE_IPV6
7bbc6864
DS
272 else if ((dp.family == AF_INET6) &&
273 (peer->su.sa.sa_family == AF_INET6))
274 {
275 if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr,
276 sizeof (struct in6_addr)))
277 continue;
278 }
c43ed2e4
DS
279#endif
280 else
281 continue;
282
283 if (ifp && (ifp == peer->nexthop.ifp))
7bbc6864 284 {
68fe91d6 285 bgp_bfd_peer_status_update(peer, status);
7bbc6864 286 }
c43ed2e4
DS
287 else
288 {
289 if (!peer->su_local)
290 continue;
291
7bbc6864
DS
292 if ((sp.family == AF_INET) &&
293 (peer->su_local->sa.sa_family == AF_INET))
294 {
295 if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr)
296 continue;
297 }
c43ed2e4 298#ifdef HAVE_IPV6
7bbc6864
DS
299 else if ((sp.family == AF_INET6) &&
300 (peer->su_local->sa.sa_family == AF_INET6))
301 {
302 if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr,
303 sizeof (struct in6_addr)))
304 continue;
305 }
c43ed2e4
DS
306#endif
307 else
308 continue;
7bbc6864 309
68fe91d6 310 bgp_bfd_peer_status_update(peer, status);
c43ed2e4
DS
311 }
312 }
313 }
314
315 return 0;
316}
317
318/*
319 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
320 */
7f342629 321static int
c43ed2e4 322bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
7f342629 323 u_int8_t detect_mult, int defaults)
c43ed2e4
DS
324{
325 struct peer_group *group;
326 struct listnode *node, *nnode;
7f342629 327 int command = 0;
c43ed2e4 328
68fe91d6 329 bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
330 detect_mult, defaults, &command);
c43ed2e4
DS
331
332 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
333 {
334 group = peer->group;
335 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
336 {
7f342629 337 command = 0;
68fe91d6 338 bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
339 detect_mult, defaults, &command);
c43ed2e4 340
7f342629
DS
341 if ((peer->status == Established) &&
342 (command == ZEBRA_BFD_DEST_REGISTER))
c43ed2e4 343 bgp_bfd_register_peer(peer);
7f342629 344 else if (command == ZEBRA_BFD_DEST_UPDATE)
c43ed2e4
DS
345 bgp_bfd_update_peer(peer);
346 }
347 }
7f342629 348 else
c43ed2e4 349 {
7f342629
DS
350 if ((peer->status == Established) &&
351 (command == ZEBRA_BFD_DEST_REGISTER))
c43ed2e4 352 bgp_bfd_register_peer(peer);
7f342629 353 else if (command == ZEBRA_BFD_DEST_UPDATE)
c43ed2e4
DS
354 bgp_bfd_update_peer(peer);
355 }
356 return 0;
357}
358
359/*
360 * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
361 */
7f342629 362static int
c43ed2e4
DS
363bgp_bfd_peer_param_unset (struct peer *peer)
364{
365 struct peer_group *group;
366 struct listnode *node, *nnode;
c43ed2e4 367
7f342629
DS
368 if (!peer->bfd_info)
369 return 0;
c43ed2e4
DS
370
371 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
372 {
7f342629 373 bfd_info_free(&(peer->bfd_info));
c43ed2e4
DS
374 group = peer->group;
375 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
376 {
c43ed2e4 377 bgp_bfd_deregister_peer(peer);
7f342629 378 bfd_info_free(&(peer->bfd_info));
c43ed2e4
DS
379 }
380 }
381 else
7f342629
DS
382 {
383 bgp_bfd_deregister_peer(peer);
384 bfd_info_free(&(peer->bfd_info));
385 }
c43ed2e4
DS
386 return 0;
387}
388
389/*
390 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
391 */
392void
393bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
394{
7f342629 395 struct bfd_info *bfd_info;
c43ed2e4 396
7f342629
DS
397 if (!peer->bfd_info)
398 return;
399
400 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 401
7f342629 402 if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG))
c43ed2e4
DS
403 vty_out (vty, " neighbor %s bfd %d %d %d%s", addr,
404 bfd_info->detect_mult, bfd_info->required_min_rx,
405 bfd_info->desired_min_tx, VTY_NEWLINE);
406 else
407 vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE);
408}
409
410/*
411 * bgp_bfd_show_info - Show the peer BFD information.
412 */
413void
856ca177 414bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh)
c43ed2e4 415{
68fe91d6 416 bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
417 bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
c43ed2e4
DS
418}
419
420DEFUN (neighbor_bfd,
421 neighbor_bfd_cmd,
422 NEIGHBOR_CMD2 "bfd",
423 NEIGHBOR_STR
424 NEIGHBOR_ADDR_STR2
425 "Enables BFD support\n")
426{
427 struct peer *peer;
428 int ret;
c43ed2e4
DS
429
430 peer = peer_and_group_lookup_vty (vty, argv[0]);
431 if (! peer)
432 return CMD_WARNING;
433
7f342629
DS
434 ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
435 BFD_DEF_DETECT_MULT, 1);
c43ed2e4
DS
436 if (ret != 0)
437 return bgp_vty_return (vty, ret);
438
439 return CMD_SUCCESS;
440
441}
442
443DEFUN (neighbor_bfd_param,
444 neighbor_bfd_param_cmd,
7f342629 445 NEIGHBOR_CMD2 "bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
c43ed2e4
DS
446 NEIGHBOR_STR
447 NEIGHBOR_ADDR_STR2
448 "Enables BFD support\n"
449 "Detect Multiplier\n"
450 "Required min receive interval\n"
451 "Desired min transmit interval\n")
452{
453 struct peer *peer;
454 u_int32_t rx_val;
455 u_int32_t tx_val;
456 u_int8_t dm_val;
457 int ret;
c43ed2e4
DS
458
459 peer = peer_and_group_lookup_vty (vty, argv[0]);
460 if (!peer)
461 return CMD_WARNING;
462
7f342629
DS
463 if ((ret = bfd_validate_param (vty, argv[1], argv[2], argv[3], &dm_val,
464 &rx_val, &tx_val)) != CMD_SUCCESS)
465 return ret;
c43ed2e4 466
7f342629 467 ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0);
c43ed2e4
DS
468 if (ret != 0)
469 return bgp_vty_return (vty, ret);
470
471 return CMD_SUCCESS;
472
473}
474
475DEFUN (no_neighbor_bfd,
476 no_neighbor_bfd_cmd,
477 NO_NEIGHBOR_CMD2 "bfd",
478 NO_STR
479 NEIGHBOR_STR
480 NEIGHBOR_ADDR_STR2
481 "Disables BFD support\n")
482{
483 struct peer *peer;
484 int ret;
485
486 peer = peer_and_group_lookup_vty (vty, argv[0]);
487 if (! peer)
488 return CMD_WARNING;
489
c43ed2e4
DS
490 ret = bgp_bfd_peer_param_unset(peer);
491 if (ret != 0)
492 return bgp_vty_return (vty, ret);
493
c43ed2e4
DS
494 return CMD_SUCCESS;
495}
496
497void
498bgp_bfd_init(void)
499{
500 /* Initialize BFD client functions */
68fe91d6 501 zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
c43ed2e4
DS
502 zclient->bfd_dest_replay = bgp_bfd_dest_replay;
503
504 /* "neighbor bfd" commands. */
505 install_element (BGP_NODE, &neighbor_bfd_cmd);
506 install_element (BGP_NODE, &neighbor_bfd_param_cmd);
507 install_element (BGP_NODE, &no_neighbor_bfd_cmd);
508}