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