]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bfd.c
Fixing a space before VRF_CMD_STR in ip route commands.
[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,
99 peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1);
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,
105 peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1);
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
c43ed2e4
DS
174bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
175{
176 struct listnode *mnode, *node, *nnode;
177 struct bgp *bgp;
178 struct peer *peer;
179
180 if (BGP_DEBUG (zebra, ZEBRA))
181 zlog_debug("Zebra: BFD Dest replay request");
182
183 /* Replay the peer, if BFD is enabled in BGP */
184
185 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
186 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
187 {
c43ed2e4
DS
188 bgp_bfd_update_peer(peer);
189 }
190
191 return 0;
192}
193
194/*
68fe91d6 195 * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
196 * down the peer if the BFD session went down from * up.
197 */
198static void
199bgp_bfd_peer_status_update (struct peer *peer, int status)
200{
201 struct bfd_info *bfd_info;
202 int old_status;
203
204 bfd_info = (struct bfd_info *)peer->bfd_info;
205
206 if (bfd_info->status == status)
207 return;
208
209 old_status = bfd_info->status;
210 bfd_info->status = status;
211 bfd_info->last_update = bgp_clock();
212
213 if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
214 {
215 peer->last_reset = PEER_DOWN_BFD_DOWN;
216 BGP_EVENT_ADD (peer, BGP_Stop);
217 }
218}
219
220/*
221 * bgp_bfd_dest_update - Find the peer for which the BFD status
222 * has changed and bring down the peer
223 * connectivity if the BFD session went down.
c43ed2e4 224 */
7f342629 225static int
68fe91d6 226bgp_bfd_dest_update (int command, struct zclient *zclient,
c43ed2e4
DS
227 zebra_size_t length)
228{
229 struct interface *ifp;
230 struct prefix dp;
231 struct prefix sp;
68fe91d6 232 int status;
c43ed2e4 233
68fe91d6 234 ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status);
c43ed2e4
DS
235
236 if (BGP_DEBUG (zebra, ZEBRA))
237 {
238 char buf[2][128];
239 prefix2str(&dp, buf[0], sizeof(buf[0]));
240 if (ifp)
241 {
68fe91d6 242 zlog_debug("Zebra: interface %s bfd destination %s %s",
243 ifp->name, buf[0], bfd_get_status_str(status));
c43ed2e4
DS
244 }
245 else
246 {
247 prefix2str(&sp, buf[1], sizeof(buf[1]));
68fe91d6 248 zlog_debug("Zebra: source %s bfd destination %s %s",
249 buf[1], buf[0], bfd_get_status_str(status));
c43ed2e4
DS
250 }
251 }
252
253 /* Bring the peer down if BFD is enabled in BGP */
254 {
255 struct listnode *mnode, *node, *nnode;
256 struct bgp *bgp;
257 struct peer *peer;
258
259 for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
260 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
261 {
7f342629 262 if (!peer->bfd_info)
c43ed2e4
DS
263 continue;
264
7bbc6864
DS
265 if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET))
266 {
267 if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr)
268 continue;
269 }
c43ed2e4 270#ifdef HAVE_IPV6
7bbc6864
DS
271 else if ((dp.family == AF_INET6) &&
272 (peer->su.sa.sa_family == AF_INET6))
273 {
274 if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr,
275 sizeof (struct in6_addr)))
276 continue;
277 }
c43ed2e4
DS
278#endif
279 else
280 continue;
281
282 if (ifp && (ifp == peer->nexthop.ifp))
7bbc6864 283 {
68fe91d6 284 bgp_bfd_peer_status_update(peer, status);
7bbc6864 285 }
c43ed2e4
DS
286 else
287 {
288 if (!peer->su_local)
289 continue;
290
7bbc6864
DS
291 if ((sp.family == AF_INET) &&
292 (peer->su_local->sa.sa_family == AF_INET))
293 {
294 if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr)
295 continue;
296 }
c43ed2e4 297#ifdef HAVE_IPV6
7bbc6864
DS
298 else if ((sp.family == AF_INET6) &&
299 (peer->su_local->sa.sa_family == AF_INET6))
300 {
301 if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr,
302 sizeof (struct in6_addr)))
303 continue;
304 }
c43ed2e4
DS
305#endif
306 else
307 continue;
7bbc6864 308
68fe91d6 309 bgp_bfd_peer_status_update(peer, status);
c43ed2e4
DS
310 }
311 }
312 }
313
314 return 0;
315}
316
317/*
318 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
319 */
7f342629 320static int
c43ed2e4 321bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
7f342629 322 u_int8_t detect_mult, int defaults)
c43ed2e4
DS
323{
324 struct peer_group *group;
325 struct listnode *node, *nnode;
7f342629 326 int command = 0;
c43ed2e4 327
68fe91d6 328 bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
329 detect_mult, defaults, &command);
c43ed2e4
DS
330
331 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
332 {
333 group = peer->group;
334 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
335 {
7f342629 336 command = 0;
68fe91d6 337 bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
338 detect_mult, defaults, &command);
c43ed2e4 339
7f342629
DS
340 if ((peer->status == Established) &&
341 (command == ZEBRA_BFD_DEST_REGISTER))
c43ed2e4 342 bgp_bfd_register_peer(peer);
7f342629 343 else if (command == ZEBRA_BFD_DEST_UPDATE)
c43ed2e4
DS
344 bgp_bfd_update_peer(peer);
345 }
346 }
7f342629 347 else
c43ed2e4 348 {
7f342629
DS
349 if ((peer->status == Established) &&
350 (command == ZEBRA_BFD_DEST_REGISTER))
c43ed2e4 351 bgp_bfd_register_peer(peer);
7f342629 352 else if (command == ZEBRA_BFD_DEST_UPDATE)
c43ed2e4
DS
353 bgp_bfd_update_peer(peer);
354 }
355 return 0;
356}
357
358/*
359 * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
360 */
7f342629 361static int
c43ed2e4
DS
362bgp_bfd_peer_param_unset (struct peer *peer)
363{
364 struct peer_group *group;
365 struct listnode *node, *nnode;
c43ed2e4 366
7f342629
DS
367 if (!peer->bfd_info)
368 return 0;
c43ed2e4
DS
369
370 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
371 {
7f342629 372 bfd_info_free(&(peer->bfd_info));
c43ed2e4
DS
373 group = peer->group;
374 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
375 {
c43ed2e4 376 bgp_bfd_deregister_peer(peer);
7f342629 377 bfd_info_free(&(peer->bfd_info));
c43ed2e4
DS
378 }
379 }
380 else
7f342629
DS
381 {
382 bgp_bfd_deregister_peer(peer);
383 bfd_info_free(&(peer->bfd_info));
384 }
c43ed2e4
DS
385 return 0;
386}
387
388/*
389 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
390 */
391void
392bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
393{
7f342629 394 struct bfd_info *bfd_info;
c43ed2e4 395
7f342629
DS
396 if (!peer->bfd_info)
397 return;
398
399 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 400
7f342629 401 if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG))
c43ed2e4
DS
402 vty_out (vty, " neighbor %s bfd %d %d %d%s", addr,
403 bfd_info->detect_mult, bfd_info->required_min_rx,
404 bfd_info->desired_min_tx, VTY_NEWLINE);
405 else
406 vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE);
407}
408
409/*
410 * bgp_bfd_show_info - Show the peer BFD information.
411 */
412void
856ca177 413bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh)
c43ed2e4 414{
68fe91d6 415 bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
416 bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
c43ed2e4
DS
417}
418
419DEFUN (neighbor_bfd,
420 neighbor_bfd_cmd,
421 NEIGHBOR_CMD2 "bfd",
422 NEIGHBOR_STR
423 NEIGHBOR_ADDR_STR2
424 "Enables BFD support\n")
425{
426 struct peer *peer;
427 int ret;
c43ed2e4
DS
428
429 peer = peer_and_group_lookup_vty (vty, argv[0]);
430 if (! peer)
431 return CMD_WARNING;
432
7f342629
DS
433 ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
434 BFD_DEF_DETECT_MULT, 1);
c43ed2e4
DS
435 if (ret != 0)
436 return bgp_vty_return (vty, ret);
437
438 return CMD_SUCCESS;
439
440}
441
442DEFUN (neighbor_bfd_param,
443 neighbor_bfd_param_cmd,
7f342629 444 NEIGHBOR_CMD2 "bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE,
c43ed2e4
DS
445 NEIGHBOR_STR
446 NEIGHBOR_ADDR_STR2
447 "Enables BFD support\n"
448 "Detect Multiplier\n"
449 "Required min receive interval\n"
450 "Desired min transmit interval\n")
451{
452 struct peer *peer;
453 u_int32_t rx_val;
454 u_int32_t tx_val;
455 u_int8_t dm_val;
456 int ret;
c43ed2e4
DS
457
458 peer = peer_and_group_lookup_vty (vty, argv[0]);
459 if (!peer)
460 return CMD_WARNING;
461
7f342629
DS
462 if ((ret = bfd_validate_param (vty, argv[1], argv[2], argv[3], &dm_val,
463 &rx_val, &tx_val)) != CMD_SUCCESS)
464 return ret;
c43ed2e4 465
7f342629 466 ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0);
c43ed2e4
DS
467 if (ret != 0)
468 return bgp_vty_return (vty, ret);
469
470 return CMD_SUCCESS;
471
472}
473
474DEFUN (no_neighbor_bfd,
475 no_neighbor_bfd_cmd,
476 NO_NEIGHBOR_CMD2 "bfd",
477 NO_STR
478 NEIGHBOR_STR
479 NEIGHBOR_ADDR_STR2
480 "Disables BFD support\n")
481{
482 struct peer *peer;
483 int ret;
484
485 peer = peer_and_group_lookup_vty (vty, argv[0]);
486 if (! peer)
487 return CMD_WARNING;
488
c43ed2e4
DS
489 ret = bgp_bfd_peer_param_unset(peer);
490 if (ret != 0)
491 return bgp_vty_return (vty, ret);
492
c43ed2e4
DS
493 return CMD_SUCCESS;
494}
495
496void
497bgp_bfd_init(void)
498{
499 /* Initialize BFD client functions */
68fe91d6 500 zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
c43ed2e4
DS
501 zclient->bfd_dest_replay = bgp_bfd_dest_replay;
502
503 /* "neighbor bfd" commands. */
504 install_element (BGP_NODE, &neighbor_bfd_cmd);
505 install_element (BGP_NODE, &neighbor_bfd_param_cmd);
506 install_element (BGP_NODE, &no_neighbor_bfd_cmd);
507}