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