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