]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_bfd.c
Merge pull request #3502 from donaldsharp/socket_to_me_baby
[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 *
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
c43ed2e4
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"
7f342629 33#include "bfd.h"
856ca177 34#include "lib/json.h"
039f3a34
DS
35#include "filter.h"
36
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 45/*
d62a17ae 46 * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group
47 * template
c43ed2e4
DS
48 * to peer.
49 */
d62a17ae 50void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
c43ed2e4 51{
d62a17ae 52 struct bfd_info *bfd_info;
53 struct bfd_info *conf_bfd_info;
7f342629 54
d62a17ae 55 if (!conf->bfd_info)
56 return;
7f342629 57
d62a17ae 58 conf_bfd_info = (struct bfd_info *)conf->bfd_info;
59 if (!peer->bfd_info)
60 peer->bfd_info = bfd_info_create();
c43ed2e4 61
d62a17ae 62 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 63
d62a17ae 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 bfd_info->type = conf_bfd_info->type;
c43ed2e4
DS
69}
70
71/*
d62a17ae 72 * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single
73 * hop.
c43ed2e4 74 */
d62a17ae 75int bgp_bfd_is_peer_multihop(struct peer *peer)
c43ed2e4 76{
d62a17ae 77 struct bfd_info *bfd_info;
986aa00f 78
d62a17ae 79 bfd_info = (struct bfd_info *)peer->bfd_info;
986aa00f 80
d62a17ae 81 if (!bfd_info)
82 return 0;
986aa00f 83
d62a17ae 84 if ((bfd_info->type == BFD_TYPE_MULTIHOP)
85 || ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network)
86 || is_ebgp_multihop_configured(peer))
87 return 1;
88 else
89 return 0;
c43ed2e4
DS
90}
91
92/*
7f342629
DS
93 * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister
94 * command to Zebra to be forwarded to BFD
c43ed2e4 95 */
d62a17ae 96static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
c43ed2e4 97{
d62a17ae 98 struct bfd_info *bfd_info;
99 vrf_id_t vrf_id = VRF_DEFAULT;
100 int multihop;
101
102 bfd_info = (struct bfd_info *)peer->bfd_info;
103
5410015a 104 if (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
d62a17ae 105 vrf_id = peer->bgp->vrf_id;
106
107 if (command == ZEBRA_BFD_DEST_DEREGISTER) {
108 multihop =
109 CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
110 UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
111 } else {
112 multihop = bgp_bfd_is_peer_multihop(peer);
113 if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop)
114 SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
115 }
116
117 if (peer->su.sa.sa_family == AF_INET)
118 bfd_peer_sendmsg(
119 zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr,
120 (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
121 (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
122 peer->ttl, multihop, command, 1, vrf_id);
123 else if (peer->su.sa.sa_family == AF_INET6)
124 bfd_peer_sendmsg(
125 zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr,
126 (peer->su_local) ? &peer->su_local->sin6.sin6_addr
127 : NULL,
128 (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
129 peer->ttl, multihop, command, 1, vrf_id);
c43ed2e4
DS
130}
131
132/*
133 * bgp_bfd_register_peer - register a peer with BFD through zebra
134 * for monitoring the peer rechahability.
135 */
d62a17ae 136void bgp_bfd_register_peer(struct peer *peer)
c43ed2e4 137{
d62a17ae 138 struct bfd_info *bfd_info;
c43ed2e4 139
d62a17ae 140 if (!peer->bfd_info)
141 return;
142 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 143
d62a17ae 144 /* Check if BFD is enabled and peer has already been registered with BFD
145 */
146 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
147 return;
c43ed2e4 148
d62a17ae 149 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
c43ed2e4
DS
150}
151
152/**
153 * bgp_bfd_deregister_peer - deregister a peer with BFD through zebra
154 * for stopping the monitoring of the peer
155 * rechahability.
156 */
d62a17ae 157void bgp_bfd_deregister_peer(struct peer *peer)
c43ed2e4 158{
d62a17ae 159 struct bfd_info *bfd_info;
c43ed2e4 160
d62a17ae 161 if (!peer->bfd_info)
162 return;
163 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 164
d62a17ae 165 /* Check if BFD is eanbled and peer has not been registered */
166 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
167 return;
c43ed2e4 168
d62a17ae 169 bfd_info->status = BFD_STATUS_DOWN;
170 bfd_info->last_update = bgp_clock();
5c940836 171
d62a17ae 172 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
c43ed2e4
DS
173}
174
175/*
176 * bgp_bfd_update_peer - update peer with BFD with new BFD paramters
177 * through zebra.
178 */
d62a17ae 179static void bgp_bfd_update_peer(struct peer *peer)
c43ed2e4 180{
d62a17ae 181 struct bfd_info *bfd_info;
c43ed2e4 182
d62a17ae 183 if (!peer->bfd_info)
184 return;
185 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 186
d62a17ae 187 /* Check if the peer has been registered with BFD*/
188 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
189 return;
c43ed2e4 190
d62a17ae 191 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
c43ed2e4
DS
192}
193
986aa00f 194/*
195 * bgp_bfd_update_type - update session type with BFD through zebra.
196 */
d62a17ae 197static void bgp_bfd_update_type(struct peer *peer)
986aa00f 198{
d62a17ae 199 struct bfd_info *bfd_info;
200 int multihop;
201
202 if (!peer->bfd_info)
203 return;
204 bfd_info = (struct bfd_info *)peer->bfd_info;
205
206 /* Check if the peer has been registered with BFD*/
207 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
208 return;
209
210 if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) {
211 multihop = bgp_bfd_is_peer_multihop(peer);
212 if ((multihop
213 && !CHECK_FLAG(bfd_info->flags,
214 BFD_FLAG_BFD_TYPE_MULTIHOP))
9d303b37
DL
215 || (!multihop && CHECK_FLAG(bfd_info->flags,
216 BFD_FLAG_BFD_TYPE_MULTIHOP))) {
d62a17ae 217 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
218 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
219 }
220 } else {
221 if ((bfd_info->type == BFD_TYPE_MULTIHOP
222 && !CHECK_FLAG(bfd_info->flags,
223 BFD_FLAG_BFD_TYPE_MULTIHOP))
224 || (bfd_info->type == BFD_TYPE_SINGLEHOP
225 && CHECK_FLAG(bfd_info->flags,
226 BFD_FLAG_BFD_TYPE_MULTIHOP))) {
227 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
228 bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
229 }
230 }
986aa00f 231}
232
c43ed2e4
DS
233/*
234 * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
235 * to zebra
236 */
d62a17ae 237static int bgp_bfd_dest_replay(int command, struct zclient *client,
238 zebra_size_t length, vrf_id_t vrf_id)
c43ed2e4 239{
d62a17ae 240 struct listnode *mnode, *node, *nnode;
241 struct bgp *bgp;
242 struct peer *peer;
c43ed2e4 243
d62a17ae 244 if (BGP_DEBUG(zebra, ZEBRA))
245 zlog_debug("Zebra: BFD Dest replay request");
c43ed2e4 246
d62a17ae 247 /* Send the client registration */
248 bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
055c4dfc 249
d62a17ae 250 /* Replay the peer, if BFD is enabled in BGP */
c43ed2e4 251
d62a17ae 252 for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp))
253 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
254 bgp_bfd_update_peer(peer);
255 }
c43ed2e4 256
d62a17ae 257 return 0;
c43ed2e4
DS
258}
259
260/*
68fe91d6 261 * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
d62a17ae 262 * down the peer if the BFD session went down from
263 * * up.
68fe91d6 264 */
d62a17ae 265static void bgp_bfd_peer_status_update(struct peer *peer, int status)
68fe91d6 266{
d62a17ae 267 struct bfd_info *bfd_info;
268 int old_status;
68fe91d6 269
d62a17ae 270 bfd_info = (struct bfd_info *)peer->bfd_info;
68fe91d6 271
d62a17ae 272 if (bfd_info->status == status)
273 return;
68fe91d6 274
d62a17ae 275 old_status = bfd_info->status;
276 bfd_info->status = status;
277 bfd_info->last_update = bgp_clock();
68fe91d6 278
d62a17ae 279 if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) {
280 peer->last_reset = PEER_DOWN_BFD_DOWN;
281 BGP_EVENT_ADD(peer, BGP_Stop);
282 }
68fe91d6 283}
284
285/*
286 * bgp_bfd_dest_update - Find the peer for which the BFD status
287 * has changed and bring down the peer
288 * connectivity if the BFD session went down.
c43ed2e4 289 */
d62a17ae 290static int bgp_bfd_dest_update(int command, struct zclient *zclient,
291 zebra_size_t length, vrf_id_t vrf_id)
c43ed2e4 292{
d62a17ae 293 struct interface *ifp;
294 struct prefix dp;
295 struct prefix sp;
296 int status;
297
298 ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id);
299
300 if (BGP_DEBUG(zebra, ZEBRA)) {
301 char buf[2][PREFIX2STR_BUFFER];
302 prefix2str(&dp, buf[0], sizeof(buf[0]));
303 if (ifp) {
304 zlog_debug(
a8bf7d9c 305 "Zebra: vrf %u interface %s bfd destination %s %s",
d62a17ae 306 vrf_id, ifp->name, buf[0],
307 bfd_get_status_str(status));
308 } else {
309 prefix2str(&sp, buf[1], sizeof(buf[1]));
310 zlog_debug(
a8bf7d9c 311 "Zebra: vrf %u source %s bfd destination %s %s",
d62a17ae 312 vrf_id, buf[1], buf[0],
313 bfd_get_status_str(status));
314 }
315 }
316
317 /* Bring the peer down if BFD is enabled in BGP */
318 {
319 struct listnode *mnode, *node, *nnode;
320 struct bgp *bgp;
321 struct peer *peer;
322
323 for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp))
324 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
325 if (!peer->bfd_info)
326 continue;
327
328 if ((dp.family == AF_INET)
329 && (peer->su.sa.sa_family == AF_INET)) {
330 if (dp.u.prefix4.s_addr
331 != peer->su.sin.sin_addr.s_addr)
332 continue;
333 } else if ((dp.family == AF_INET6)
334 && (peer->su.sa.sa_family
335 == AF_INET6)) {
336 if (memcmp(&dp.u.prefix6,
337 &peer->su.sin6.sin6_addr,
338 sizeof(struct in6_addr)))
339 continue;
340 } else
341 continue;
342
343 if (ifp && (ifp == peer->nexthop.ifp)) {
344 bgp_bfd_peer_status_update(peer,
345 status);
346 } else {
347 if (!peer->su_local)
348 continue;
349
350 if ((sp.family == AF_INET)
351 && (peer->su_local->sa.sa_family
352 == AF_INET)) {
353 if (sp.u.prefix4.s_addr
354 != peer->su_local->sin
355 .sin_addr.s_addr)
356 continue;
357 } else if ((sp.family == AF_INET6)
358 && (peer->su_local->sa
359 .sa_family
360 == AF_INET6)) {
361 if (memcmp(&sp.u.prefix6,
362 &peer->su_local->sin6
363 .sin6_addr,
364 sizeof(struct
365 in6_addr)))
366 continue;
367 } else
368 continue;
369
370 if ((vrf_id != VRF_DEFAULT)
371 && (peer->bgp->vrf_id != vrf_id))
372 continue;
373
374 bgp_bfd_peer_status_update(peer,
375 status);
376 }
377 }
378 }
379
380 return 0;
c43ed2e4
DS
381}
382
383/*
384 * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer.
385 */
d7c0a89a
QY
386static int bgp_bfd_peer_param_set(struct peer *peer, uint32_t min_rx,
387 uint32_t min_tx, uint8_t detect_mult,
d62a17ae 388 int defaults)
c43ed2e4 389{
d62a17ae 390 struct peer_group *group;
391 struct listnode *node, *nnode;
392 int command = 0;
393
394 bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
395 detect_mult, defaults, &command);
396
397 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
398 group = peer->group;
399 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
400 command = 0;
401 bfd_set_param((struct bfd_info **)&(peer->bfd_info),
402 min_rx, min_tx, detect_mult, defaults,
403 &command);
404
405 if ((peer->status == Established)
406 && (command == ZEBRA_BFD_DEST_REGISTER))
407 bgp_bfd_register_peer(peer);
408 else if (command == ZEBRA_BFD_DEST_UPDATE)
409 bgp_bfd_update_peer(peer);
410 }
411 } else {
412 if ((peer->status == Established)
413 && (command == ZEBRA_BFD_DEST_REGISTER))
414 bgp_bfd_register_peer(peer);
415 else if (command == ZEBRA_BFD_DEST_UPDATE)
416 bgp_bfd_update_peer(peer);
417 }
418 return 0;
c43ed2e4
DS
419}
420
421/*
d62a17ae 422 * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for
423 * peer.
c43ed2e4 424 */
d62a17ae 425static int bgp_bfd_peer_param_unset(struct peer *peer)
c43ed2e4 426{
d62a17ae 427 struct peer_group *group;
428 struct listnode *node, *nnode;
429
430 if (!peer->bfd_info)
431 return 0;
432
433 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
434 bfd_info_free(&(peer->bfd_info));
435 group = peer->group;
436 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
437 bgp_bfd_deregister_peer(peer);
438 bfd_info_free(&(peer->bfd_info));
439 }
440 } else {
441 bgp_bfd_deregister_peer(peer);
442 bfd_info_free(&(peer->bfd_info));
443 }
444 return 0;
c43ed2e4
DS
445}
446
986aa00f 447/*
d62a17ae 448 * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or
449 * singlehop)
986aa00f 450 */
d62a17ae 451static int bgp_bfd_peer_param_type_set(struct peer *peer,
452 enum bfd_sess_type type)
986aa00f 453{
d62a17ae 454 struct peer_group *group;
455 struct listnode *node, *nnode;
456 int command = 0;
457 struct bfd_info *bfd_info;
458
459 if (!peer->bfd_info)
460 bfd_set_param((struct bfd_info **)&(peer->bfd_info),
461 BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
462 BFD_DEF_DETECT_MULT, 1, &command);
463
464 bfd_info = (struct bfd_info *)peer->bfd_info;
465 bfd_info->type = type;
466
467 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
468 group = peer->group;
469 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
470 command = 0;
471 if (!peer->bfd_info)
472 bfd_set_param(
473 (struct bfd_info **)&(peer->bfd_info),
474 BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
475 BFD_DEF_DETECT_MULT, 1, &command);
476
477 bfd_info = (struct bfd_info *)peer->bfd_info;
478 bfd_info->type = type;
479
480 if (peer->status == Established) {
481 if (command == ZEBRA_BFD_DEST_REGISTER)
482 bgp_bfd_register_peer(peer);
483 else
484 bgp_bfd_update_type(peer);
485 }
486 }
487 } else {
488 if (peer->status == Established) {
489 if (command == ZEBRA_BFD_DEST_REGISTER)
490 bgp_bfd_register_peer(peer);
491 else
492 bgp_bfd_update_type(peer);
493 }
494 }
495
496 return 0;
986aa00f 497}
498
c43ed2e4
DS
499/*
500 * bgp_bfd_peer_config_write - Write the peer BFD configuration.
501 */
d62a17ae 502void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
c43ed2e4 503{
d62a17ae 504 struct bfd_info *bfd_info;
c43ed2e4 505
d62a17ae 506 if (!peer->bfd_info)
507 return;
7f342629 508
d62a17ae 509 bfd_info = (struct bfd_info *)peer->bfd_info;
c43ed2e4 510
d62a17ae 511 if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
a0841732
RZ
512#if HAVE_BFDD > 0
513 vty_out(vty, " neighbor %s bfd\n", addr);
514#else
d62a17ae 515 vty_out(vty, " neighbor %s bfd %d %d %d\n", addr,
516 bfd_info->detect_mult, bfd_info->required_min_rx,
517 bfd_info->desired_min_tx);
a0841732 518#endif /* HAVE_BFDD */
986aa00f 519
d62a17ae 520 if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED)
521 vty_out(vty, " neighbor %s bfd %s\n", addr,
522 (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop"
523 : "singlehop");
986aa00f 524
d62a17ae 525 if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)
526 && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
527 vty_out(vty, " neighbor %s bfd\n", addr);
c43ed2e4
DS
528}
529
530/*
531 * bgp_bfd_show_info - Show the peer BFD information.
532 */
9f049418 533void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json,
d62a17ae 534 json_object *json_neigh)
c43ed2e4 535{
d62a17ae 536 bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
537 bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
c43ed2e4
DS
538}
539
540DEFUN (neighbor_bfd,
541 neighbor_bfd_cmd,
9ccf14f7 542 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
c43ed2e4
DS
543 NEIGHBOR_STR
544 NEIGHBOR_ADDR_STR2
545 "Enables BFD support\n")
546{
d62a17ae 547 int idx_peer = 1;
548 struct peer *peer;
549 int ret;
c43ed2e4 550
d62a17ae 551 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
552 if (!peer)
553 return CMD_WARNING_CONFIG_FAILED;
c43ed2e4 554
d62a17ae 555 ret = bgp_bfd_peer_param_set(peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
556 BFD_DEF_DETECT_MULT, 1);
557 if (ret != 0)
558 return bgp_vty_return(vty, ret);
c43ed2e4 559
d62a17ae 560 return CMD_SUCCESS;
c43ed2e4
DS
561}
562
64dc4b2d
RZ
563#if HAVE_BFDD > 0
564DEFUN_HIDDEN(
565#else
566DEFUN(
567#endif /* HAVE_BFDD */
568 neighbor_bfd_param,
c43ed2e4 569 neighbor_bfd_param_cmd,
9ccf14f7 570 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd (2-255) (50-60000) (50-60000)",
c43ed2e4
DS
571 NEIGHBOR_STR
572 NEIGHBOR_ADDR_STR2
573 "Enables BFD support\n"
574 "Detect Multiplier\n"
575 "Required min receive interval\n"
576 "Desired min transmit interval\n")
577{
d62a17ae 578 int idx_peer = 1;
579 int idx_number_1 = 3;
580 int idx_number_2 = 4;
581 int idx_number_3 = 5;
582 struct peer *peer;
d7c0a89a
QY
583 uint32_t rx_val;
584 uint32_t tx_val;
585 uint8_t dm_val;
d62a17ae 586 int ret;
587
588 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
589 if (!peer)
590 return CMD_WARNING_CONFIG_FAILED;
591
592 if ((ret = bfd_validate_param(
593 vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg,
594 argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
595 != CMD_SUCCESS)
596 return ret;
597
598 ret = bgp_bfd_peer_param_set(peer, rx_val, tx_val, dm_val, 0);
599 if (ret != 0)
600 return bgp_vty_return(vty, ret);
601
602 return CMD_SUCCESS;
c43ed2e4
DS
603}
604
986aa00f 605DEFUN_HIDDEN (neighbor_bfd_type,
606 neighbor_bfd_type_cmd,
e83a9414 607 "neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>",
986aa00f 608 NEIGHBOR_STR
609 NEIGHBOR_ADDR_STR2
610 "Enables BFD support\n"
d7fa34c1
QY
611 "Multihop session\n"
612 "Single hop session\n")
986aa00f 613{
d62a17ae 614 int idx_peer = 1;
615 int idx_hop = 3;
616 struct peer *peer;
617 enum bfd_sess_type type;
618 int ret;
619
620 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
621 if (!peer)
622 return CMD_WARNING_CONFIG_FAILED;
623
624 if (strmatch(argv[idx_hop]->text, "singlehop"))
625 type = BFD_TYPE_SINGLEHOP;
626 else if (strmatch(argv[idx_hop]->text, "multihop"))
627 type = BFD_TYPE_MULTIHOP;
628 else
629 return CMD_WARNING_CONFIG_FAILED;
630
631 ret = bgp_bfd_peer_param_type_set(peer, type);
632 if (ret != 0)
633 return bgp_vty_return(vty, ret);
634
635 return CMD_SUCCESS;
986aa00f 636}
637
c43ed2e4
DS
638DEFUN (no_neighbor_bfd,
639 no_neighbor_bfd_cmd,
64dc4b2d
RZ
640#if HAVE_BFDD > 0
641 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd",
642#else
5bf15956 643 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd [(2-255) (50-60000) (50-60000)]",
64dc4b2d 644#endif /* HAVE_BFDD */
c43ed2e4
DS
645 NO_STR
646 NEIGHBOR_STR
647 NEIGHBOR_ADDR_STR2
5bf15956 648 "Disables BFD support\n"
64dc4b2d 649#if HAVE_BFDD == 0
5bf15956
DW
650 "Detect Multiplier\n"
651 "Required min receive interval\n"
64dc4b2d
RZ
652 "Desired min transmit interval\n"
653#endif /* !HAVE_BFDD */
654)
c43ed2e4 655{
d62a17ae 656 int idx_peer = 2;
657 struct peer *peer;
658 int ret;
c43ed2e4 659
d62a17ae 660 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
661 if (!peer)
662 return CMD_WARNING_CONFIG_FAILED;
c43ed2e4 663
d62a17ae 664 ret = bgp_bfd_peer_param_unset(peer);
665 if (ret != 0)
666 return bgp_vty_return(vty, ret);
c43ed2e4 667
d62a17ae 668 return CMD_SUCCESS;
c43ed2e4
DS
669}
670
813d4307 671
986aa00f 672DEFUN_HIDDEN (no_neighbor_bfd_type,
673 no_neighbor_bfd_type_cmd,
e83a9414 674 "no neighbor <A.B.C.D|X:X::X:X|WORD> bfd <multihop|singlehop>",
986aa00f 675 NO_STR
676 NEIGHBOR_STR
677 NEIGHBOR_ADDR_STR2
678 "Disables BFD support\n"
3a2d747c
QY
679 "Multihop session\n"
680 "Singlehop session\n")
986aa00f 681{
d62a17ae 682 int idx_peer = 2;
683 struct peer *peer;
684 int ret;
986aa00f 685
d62a17ae 686 peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
687 if (!peer)
688 return CMD_WARNING_CONFIG_FAILED;
986aa00f 689
d62a17ae 690 if (!peer->bfd_info)
691 return 0;
986aa00f 692
d62a17ae 693 ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED);
694 if (ret != 0)
695 return bgp_vty_return(vty, ret);
986aa00f 696
d62a17ae 697 return CMD_SUCCESS;
986aa00f 698}
699
d62a17ae 700void bgp_bfd_init(void)
c43ed2e4 701{
d62a17ae 702 bfd_gbl_init();
703
704 /* Initialize BFD client functions */
705 zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
706 zclient->bfd_dest_replay = bgp_bfd_dest_replay;
707
708 /* "neighbor bfd" commands. */
709 install_element(BGP_NODE, &neighbor_bfd_cmd);
710 install_element(BGP_NODE, &neighbor_bfd_param_cmd);
711 install_element(BGP_NODE, &neighbor_bfd_type_cmd);
712 install_element(BGP_NODE, &no_neighbor_bfd_cmd);
713 install_element(BGP_NODE, &no_neighbor_bfd_type_cmd);
c43ed2e4 714}