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