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