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