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