3 * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
5 * FRR is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
10 * FRR is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with FRR; see the file COPYING. If not, write to the Free
17 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 #include "lib/command.h"
26 #include "lib/northbound_cli.h"
31 #ifndef VTYSH_EXTRACT_PL
32 #include "bfdd/bfdd_vty_clippy.c"
36 * Commands help string definitions.
38 #define PEER_IPV4_STR "IPv4 peer address\n"
39 #define PEER_IPV6_STR "IPv6 peer address\n"
40 #define MHOP_STR "Configure multihop\n"
41 #define LOCAL_STR "Configure local address\n"
42 #define LOCAL_IPV4_STR "IPv4 local address\n"
43 #define LOCAL_IPV6_STR "IPv6 local address\n"
44 #define LOCAL_INTF_STR "Configure local interface name to use\n"
49 static int bfd_configure_peer(struct bfd_peer_cfg
*bpc
, bool mhop
,
50 const struct sockaddr_any
*peer
,
51 const struct sockaddr_any
*local
,
52 const char *ifname
, const char *vrfname
,
53 char *ebuf
, size_t ebuflen
);
55 static void _display_peer_header(struct vty
*vty
, struct bfd_session
*bs
);
56 static struct json_object
*__display_peer_json(struct bfd_session
*bs
);
57 static struct json_object
*_peer_json_header(struct bfd_session
*bs
);
58 static void _display_peer_json(struct vty
*vty
, struct bfd_session
*bs
);
59 static void _display_peer(struct vty
*vty
, struct bfd_session
*bs
);
60 static void _display_all_peers(struct vty
*vty
, char *vrfname
, bool use_json
);
61 static void _display_peer_iter(struct hash_bucket
*hb
, void *arg
);
62 static void _display_peer_json_iter(struct hash_bucket
*hb
, void *arg
);
63 static void _display_peer_counter(struct vty
*vty
, struct bfd_session
*bs
);
64 static struct json_object
*__display_peer_counters_json(struct bfd_session
*bs
);
65 static void _display_peer_counters_json(struct vty
*vty
, struct bfd_session
*bs
);
66 static void _display_peer_counter_iter(struct hash_bucket
*hb
, void *arg
);
67 static void _display_peer_counter_json_iter(struct hash_bucket
*hb
, void *arg
);
68 static void _display_peers_counter(struct vty
*vty
, char *vrfname
, bool use_json
);
69 static struct bfd_session
*
70 _find_peer_or_error(struct vty
*vty
, int argc
, struct cmd_token
**argv
,
71 const char *label
, const char *peer_str
,
72 const char *local_str
, const char *ifname
,
77 * Show commands helper functions
79 static void _display_peer_header(struct vty
*vty
, struct bfd_session
*bs
)
81 char addr_buf
[INET6_ADDRSTRLEN
];
83 vty_out(vty
, "\tpeer %s",
84 inet_ntop(bs
->key
.family
, &bs
->key
.peer
, addr_buf
,
87 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
88 vty_out(vty
, " multihop");
90 if (memcmp(&bs
->key
.local
, &zero_addr
, sizeof(bs
->key
.local
)))
91 vty_out(vty
, " local-address %s",
92 inet_ntop(bs
->key
.family
, &bs
->key
.local
, addr_buf
,
95 if (bs
->key
.vrfname
[0])
96 vty_out(vty
, " vrf %s", bs
->key
.vrfname
);
97 if (bs
->key
.ifname
[0])
98 vty_out(vty
, " interface %s", bs
->key
.ifname
);
102 vty_out(vty
, "\t\tlabel: %s\n", bs
->pl
->pl_label
);
105 static void _display_peer(struct vty
*vty
, struct bfd_session
*bs
)
110 _display_peer_header(vty
, bs
);
112 vty_out(vty
, "\t\tID: %u\n", bs
->discrs
.my_discr
);
113 vty_out(vty
, "\t\tRemote ID: %u\n", bs
->discrs
.remote_discr
);
114 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_PASSIVE
))
115 vty_out(vty
, "\t\tPassive mode\n");
117 vty_out(vty
, "\t\tActive mode\n");
118 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
119 vty_out(vty
, "\t\tMinimum TTL: %d\n", bs
->mh_ttl
);
121 vty_out(vty
, "\t\tStatus: ");
122 switch (bs
->ses_state
) {
123 case PTM_BFD_ADM_DOWN
:
124 vty_out(vty
, "shutdown\n");
127 vty_out(vty
, "down\n");
129 now
= monotime(NULL
);
130 integer2timestr(now
- bs
->downtime
.tv_sec
, buf
, sizeof(buf
));
131 vty_out(vty
, "\t\tDowntime: %s\n", buf
);
134 vty_out(vty
, "init\n");
137 vty_out(vty
, "up\n");
139 now
= monotime(NULL
);
140 integer2timestr(now
- bs
->uptime
.tv_sec
, buf
, sizeof(buf
));
141 vty_out(vty
, "\t\tUptime: %s\n", buf
);
145 vty_out(vty
, "unknown\n");
149 vty_out(vty
, "\t\tDiagnostics: %s\n", diag2str(bs
->local_diag
));
150 vty_out(vty
, "\t\tRemote diagnostics: %s\n", diag2str(bs
->remote_diag
));
151 vty_out(vty
, "\t\tPeer Type: %s\n",
152 CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
) ? "configured" : "dynamic");
154 vty_out(vty
, "\t\tLocal timers:\n");
155 vty_out(vty
, "\t\t\tDetect-multiplier: %u\n",
157 vty_out(vty
, "\t\t\tReceive interval: %ums\n",
158 bs
->timers
.required_min_rx
/ 1000);
159 vty_out(vty
, "\t\t\tTransmission interval: %ums\n",
160 bs
->timers
.desired_min_tx
/ 1000);
161 vty_out(vty
, "\t\t\tEcho transmission interval: %ums\n",
162 bs
->timers
.required_min_echo
/ 1000);
164 vty_out(vty
, "\t\tRemote timers:\n");
165 vty_out(vty
, "\t\t\tDetect-multiplier: %u\n",
166 bs
->remote_detect_mult
);
167 vty_out(vty
, "\t\t\tReceive interval: %ums\n",
168 bs
->remote_timers
.required_min_rx
/ 1000);
169 vty_out(vty
, "\t\t\tTransmission interval: %ums\n",
170 bs
->remote_timers
.desired_min_tx
/ 1000);
171 vty_out(vty
, "\t\t\tEcho transmission interval: %ums\n",
172 bs
->remote_timers
.required_min_echo
/ 1000);
177 static struct json_object
*_peer_json_header(struct bfd_session
*bs
)
179 struct json_object
*jo
= json_object_new_object();
180 char addr_buf
[INET6_ADDRSTRLEN
];
183 json_object_boolean_true_add(jo
, "multihop");
185 json_object_boolean_false_add(jo
, "multihop");
187 json_object_string_add(jo
, "peer",
188 inet_ntop(bs
->key
.family
, &bs
->key
.peer
,
189 addr_buf
, sizeof(addr_buf
)));
190 if (memcmp(&bs
->key
.local
, &zero_addr
, sizeof(bs
->key
.local
)))
191 json_object_string_add(jo
, "local",
192 inet_ntop(bs
->key
.family
, &bs
->key
.local
,
193 addr_buf
, sizeof(addr_buf
)));
195 if (bs
->key
.vrfname
[0])
196 json_object_string_add(jo
, "vrf", bs
->key
.vrfname
);
197 if (bs
->key
.ifname
[0])
198 json_object_string_add(jo
, "interface", bs
->key
.ifname
);
201 json_object_string_add(jo
, "label", bs
->pl
->pl_label
);
206 static struct json_object
*__display_peer_json(struct bfd_session
*bs
)
208 struct json_object
*jo
= _peer_json_header(bs
);
210 json_object_int_add(jo
, "id", bs
->discrs
.my_discr
);
211 json_object_int_add(jo
, "remote-id", bs
->discrs
.remote_discr
);
212 json_object_boolean_add(jo
, "passive-mode",
213 CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_PASSIVE
));
214 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
215 json_object_int_add(jo
, "minimum-ttl", bs
->mh_ttl
);
217 switch (bs
->ses_state
) {
218 case PTM_BFD_ADM_DOWN
:
219 json_object_string_add(jo
, "status", "shutdown");
222 json_object_string_add(jo
, "status", "down");
223 json_object_int_add(jo
, "downtime",
224 monotime(NULL
) - bs
->downtime
.tv_sec
);
227 json_object_string_add(jo
, "status", "init");
230 json_object_string_add(jo
, "status", "up");
231 json_object_int_add(jo
, "uptime",
232 monotime(NULL
) - bs
->uptime
.tv_sec
);
236 json_object_string_add(jo
, "status", "unknown");
240 json_object_string_add(jo
, "diagnostic", diag2str(bs
->local_diag
));
241 json_object_string_add(jo
, "remote-diagnostic",
242 diag2str(bs
->remote_diag
));
244 json_object_int_add(jo
, "receive-interval",
245 bs
->timers
.required_min_rx
/ 1000);
246 json_object_int_add(jo
, "transmit-interval",
247 bs
->timers
.desired_min_tx
/ 1000);
248 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
))
249 json_object_int_add(jo
, "echo-interval",
250 bs
->timers
.required_min_echo
/ 1000);
252 json_object_int_add(jo
, "echo-interval", 0);
254 json_object_int_add(jo
, "detect-multiplier", bs
->detect_mult
);
256 json_object_int_add(jo
, "remote-receive-interval",
257 bs
->remote_timers
.required_min_rx
/ 1000);
258 json_object_int_add(jo
, "remote-transmit-interval",
259 bs
->remote_timers
.desired_min_tx
/ 1000);
260 json_object_int_add(jo
, "remote-echo-interval",
261 bs
->remote_timers
.required_min_echo
/ 1000);
262 json_object_int_add(jo
, "remote-detect-multiplier",
263 bs
->remote_detect_mult
);
268 static void _display_peer_json(struct vty
*vty
, struct bfd_session
*bs
)
270 struct json_object
*jo
= __display_peer_json(bs
);
272 vty_out(vty
, "%s\n", json_object_to_json_string_ext(jo
, 0));
273 json_object_free(jo
);
276 struct bfd_vrf_tuple
{
279 struct json_object
*jo
;
282 static void _display_peer_iter(struct hash_bucket
*hb
, void *arg
)
284 struct bfd_vrf_tuple
*bvt
= (struct bfd_vrf_tuple
*)arg
;
286 struct bfd_session
*bs
= hb
->data
;
293 if (!bs
->key
.vrfname
[0] ||
294 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
297 _display_peer(vty
, bs
);
300 static void _display_peer_json_iter(struct hash_bucket
*hb
, void *arg
)
302 struct bfd_vrf_tuple
*bvt
= (struct bfd_vrf_tuple
*)arg
;
303 struct json_object
*jo
, *jon
= NULL
;
304 struct bfd_session
*bs
= hb
->data
;
311 if (!bs
->key
.vrfname
[0] ||
312 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
316 jon
= __display_peer_json(bs
);
318 zlog_warn("%s: not enough memory", __func__
);
322 json_object_array_add(jo
, jon
);
325 static void _display_all_peers(struct vty
*vty
, char *vrfname
, bool use_json
)
327 struct json_object
*jo
;
328 struct bfd_vrf_tuple bvt
= {0};
330 bvt
.vrfname
= vrfname
;
334 vty_out(vty
, "BFD Peers:\n");
335 bfd_id_iterate(_display_peer_iter
, &bvt
);
339 jo
= json_object_new_array();
341 bfd_id_iterate(_display_peer_json_iter
, &bvt
);
343 vty_out(vty
, "%s\n", json_object_to_json_string_ext(jo
, 0));
344 json_object_free(jo
);
347 static void _display_peer_counter(struct vty
*vty
, struct bfd_session
*bs
)
349 _display_peer_header(vty
, bs
);
351 /* Ask data plane for updated counters. */
352 if (bfd_dplane_update_session_counters(bs
) == -1)
353 zlog_debug("%s: failed to update BFD session counters (%s)",
354 __func__
, bs_to_string(bs
));
356 vty_out(vty
, "\t\tControl packet input: %" PRIu64
" packets\n",
357 bs
->stats
.rx_ctrl_pkt
);
358 vty_out(vty
, "\t\tControl packet output: %" PRIu64
" packets\n",
359 bs
->stats
.tx_ctrl_pkt
);
360 vty_out(vty
, "\t\tEcho packet input: %" PRIu64
" packets\n",
361 bs
->stats
.rx_echo_pkt
);
362 vty_out(vty
, "\t\tEcho packet output: %" PRIu64
" packets\n",
363 bs
->stats
.tx_echo_pkt
);
364 vty_out(vty
, "\t\tSession up events: %" PRIu64
"\n",
365 bs
->stats
.session_up
);
366 vty_out(vty
, "\t\tSession down events: %" PRIu64
"\n",
367 bs
->stats
.session_down
);
368 vty_out(vty
, "\t\tZebra notifications: %" PRIu64
"\n",
369 bs
->stats
.znotification
);
373 static struct json_object
*__display_peer_counters_json(struct bfd_session
*bs
)
375 struct json_object
*jo
= _peer_json_header(bs
);
377 /* Ask data plane for updated counters. */
378 if (bfd_dplane_update_session_counters(bs
) == -1)
379 zlog_debug("%s: failed to update BFD session counters (%s)",
380 __func__
, bs_to_string(bs
));
382 json_object_int_add(jo
, "control-packet-input", bs
->stats
.rx_ctrl_pkt
);
383 json_object_int_add(jo
, "control-packet-output", bs
->stats
.tx_ctrl_pkt
);
384 json_object_int_add(jo
, "echo-packet-input", bs
->stats
.rx_echo_pkt
);
385 json_object_int_add(jo
, "echo-packet-output", bs
->stats
.tx_echo_pkt
);
386 json_object_int_add(jo
, "session-up", bs
->stats
.session_up
);
387 json_object_int_add(jo
, "session-down", bs
->stats
.session_down
);
388 json_object_int_add(jo
, "zebra-notifications", bs
->stats
.znotification
);
393 static void _display_peer_counters_json(struct vty
*vty
, struct bfd_session
*bs
)
395 struct json_object
*jo
= __display_peer_counters_json(bs
);
397 vty_out(vty
, "%s\n", json_object_to_json_string_ext(jo
, 0));
398 json_object_free(jo
);
401 static void _display_peer_counter_iter(struct hash_bucket
*hb
, void *arg
)
403 struct bfd_vrf_tuple
*bvt
= arg
;
405 struct bfd_session
*bs
= hb
->data
;
412 if (!bs
->key
.vrfname
[0] ||
413 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
417 _display_peer_counter(vty
, bs
);
420 static void _display_peer_counter_json_iter(struct hash_bucket
*hb
, void *arg
)
422 struct json_object
*jo
, *jon
= NULL
;
423 struct bfd_session
*bs
= hb
->data
;
424 struct bfd_vrf_tuple
*bvt
= arg
;
431 if (!bs
->key
.vrfname
[0] ||
432 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
436 jon
= __display_peer_counters_json(bs
);
438 zlog_warn("%s: not enough memory", __func__
);
442 json_object_array_add(jo
, jon
);
445 static void _display_peers_counter(struct vty
*vty
, char *vrfname
, bool use_json
)
447 struct json_object
*jo
;
448 struct bfd_vrf_tuple bvt
= {0};
450 bvt
.vrfname
= vrfname
;
453 vty_out(vty
, "BFD Peers:\n");
454 bfd_id_iterate(_display_peer_counter_iter
, &bvt
);
458 jo
= json_object_new_array();
460 bfd_id_iterate(_display_peer_counter_json_iter
, &bvt
);
462 vty_out(vty
, "%s\n", json_object_to_json_string_ext(jo
, 0));
463 json_object_free(jo
);
466 static void _clear_peer_counter(struct bfd_session
*bs
)
468 /* Clear only pkt stats, intention is not to loose system
470 bs
->stats
.rx_ctrl_pkt
= 0;
471 bs
->stats
.tx_ctrl_pkt
= 0;
472 bs
->stats
.rx_echo_pkt
= 0;
473 bs
->stats
.tx_echo_pkt
= 0;
476 static void _display_peer_brief(struct vty
*vty
, struct bfd_session
*bs
)
478 char addr_buf
[INET6_ADDRSTRLEN
];
480 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
)) {
481 vty_out(vty
, "%-10u", bs
->discrs
.my_discr
);
482 inet_ntop(bs
->key
.family
, &bs
->key
.local
, addr_buf
, sizeof(addr_buf
));
483 vty_out(vty
, " %-40s", addr_buf
);
484 inet_ntop(bs
->key
.family
, &bs
->key
.peer
, addr_buf
, sizeof(addr_buf
));
485 vty_out(vty
, " %-40s", addr_buf
);
486 vty_out(vty
, "%-15s\n", state_list
[bs
->ses_state
].str
);
488 vty_out(vty
, "%-10u", bs
->discrs
.my_discr
);
489 vty_out(vty
, " %-40s", satostr(&bs
->local_address
));
490 inet_ntop(bs
->key
.family
, &bs
->key
.peer
, addr_buf
, sizeof(addr_buf
));
491 vty_out(vty
, " %-40s", addr_buf
);
493 vty_out(vty
, "%-15s\n", state_list
[bs
->ses_state
].str
);
497 static void _display_peer_brief_iter(struct hash_bucket
*hb
, void *arg
)
499 struct bfd_vrf_tuple
*bvt
= arg
;
501 struct bfd_session
*bs
= hb
->data
;
508 if (!bs
->key
.vrfname
[0] ||
509 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
513 _display_peer_brief(vty
, bs
);
516 static void _display_peers_brief(struct vty
*vty
, const char *vrfname
, bool use_json
)
518 struct json_object
*jo
;
519 struct bfd_vrf_tuple bvt
= {0};
521 bvt
.vrfname
= vrfname
;
526 vty_out(vty
, "Session count: %lu\n", bfd_get_session_count());
527 vty_out(vty
, "%-10s", "SessionId");
528 vty_out(vty
, " %-40s", "LocalAddress");
529 vty_out(vty
, " %-40s", "PeerAddress");
530 vty_out(vty
, "%-15s\n", "Status");
532 vty_out(vty
, "%-10s", "=========");
533 vty_out(vty
, " %-40s", "============");
534 vty_out(vty
, " %-40s", "===========");
535 vty_out(vty
, "%-15s\n", "======");
537 bfd_id_iterate(_display_peer_brief_iter
, &bvt
);
541 jo
= json_object_new_array();
544 bfd_id_iterate(_display_peer_json_iter
, &bvt
);
546 vty_out(vty
, "%s\n", json_object_to_json_string_ext(jo
, 0));
547 json_object_free(jo
);
550 static struct bfd_session
*
551 _find_peer_or_error(struct vty
*vty
, int argc
, struct cmd_token
**argv
,
552 const char *label
, const char *peer_str
,
553 const char *local_str
, const char *ifname
,
558 struct bfd_session
*bs
= NULL
;
559 struct peer_label
*pl
;
560 struct bfd_peer_cfg bpc
;
561 struct sockaddr_any psa
, lsa
, *lsap
;
564 /* Look up the BFD peer. */
570 strtosa(peer_str
, &psa
);
572 strtosa(local_str
, &lsa
);
578 mhop
= argv_find(argv
, argc
, "multihop", &idx
);
580 if (bfd_configure_peer(&bpc
, mhop
, &psa
, lsap
, ifname
, vrfname
,
581 errormsg
, sizeof(errormsg
))
583 vty_out(vty
, "%% Invalid peer configuration: %s\n",
588 bs
= bs_peer_find(&bpc
);
591 /* Find peer data. */
593 vty_out(vty
, "%% Unable to find 'peer %s",
594 label
? label
: peer_str
);
596 vty_out(vty
, " interface %s", ifname
);
598 vty_out(vty
, " local-address %s", local_str
);
600 vty_out(vty
, " vrf %s", vrfname
);
613 DEFPY(bfd_show_peers
, bfd_show_peers_cmd
, "show bfd [vrf NAME] peers [json]",
615 "Bidirection Forwarding Detection\n"
617 "BFD peers status\n" JSON_STR
)
619 char *vrf_name
= NULL
;
622 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
623 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
625 _display_all_peers(vty
, vrf_name
, use_json(argc
, argv
));
630 DEFPY(bfd_show_peer
, bfd_show_peer_cmd
,
631 "show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]",
633 "Bidirection Forwarding Detection\n"
636 "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
637 LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR
)
639 struct bfd_session
*bs
;
641 /* Look up the BFD peer. */
642 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
645 return CMD_WARNING_CONFIG_FAILED
;
647 if (use_json(argc
, argv
)) {
648 _display_peer_json(vty
, bs
);
650 vty_out(vty
, "BFD Peer:\n");
651 _display_peer(vty
, bs
);
657 DEFPY(bfd_show_peer_counters
, bfd_show_peer_counters_cmd
,
658 "show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]",
660 "Bidirection Forwarding Detection\n"
672 "Show BFD peer counters information\n"
675 struct bfd_session
*bs
;
677 /* Look up the BFD peer. */
678 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
681 return CMD_WARNING_CONFIG_FAILED
;
683 if (use_json(argc
, argv
))
684 _display_peer_counters_json(vty
, bs
);
686 _display_peer_counter(vty
, bs
);
691 DEFPY(bfd_show_peers_counters
, bfd_show_peers_counters_cmd
,
692 "show bfd [vrf NAME] peers counters [json]",
694 "Bidirection Forwarding Detection\n"
697 "Show BFD peer counters information\n"
700 char *vrf_name
= NULL
;
703 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
704 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
706 _display_peers_counter(vty
, vrf_name
, use_json(argc
, argv
));
711 DEFPY(bfd_clear_peer_counters
, bfd_clear_peer_counters_cmd
,
712 "clear bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters",
714 "Bidirection Forwarding Detection\n"
726 "clear BFD peer counters information\n")
728 struct bfd_session
*bs
;
730 /* Look up the BFD peer. */
731 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
734 return CMD_WARNING_CONFIG_FAILED
;
736 _clear_peer_counter(bs
);
741 DEFPY(bfd_show_peers_brief
, bfd_show_peers_brief_cmd
,
742 "show bfd [vrf <NAME$vrfname>] peers brief [json]",
744 "Bidirection Forwarding Detection\n"
747 "Show BFD peer information in tabular form\n"
750 char *vrf_name
= NULL
;
753 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
754 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
756 _display_peers_brief(vty
, vrf_name
, use_json(argc
, argv
));
761 DEFPY(show_bfd_distributed
, show_bfd_distributed_cmd
,
762 "show bfd distributed",
764 "Bidirection Forwarding Detection\n"
765 "Show BFD data plane (distributed BFD) statistics\n")
767 bfd_dplane_show_counters(vty
);
772 bfd_debug_distributed
, bfd_debug_distributed_cmd
,
773 "[no] debug bfd distributed",
776 "Bidirection Forwarding Detection\n"
777 "BFD data plane (distributed BFD) debugging\n")
779 bglobal
.debug_dplane
= !no
;
784 bfd_debug_peer
, bfd_debug_peer_cmd
,
785 "[no] debug bfd peer",
788 "Bidirection Forwarding Detection\n"
789 "Peer events debugging\n")
791 bglobal
.debug_peer_event
= !no
;
796 bfd_debug_zebra
, bfd_debug_zebra_cmd
,
797 "[no] debug bfd zebra",
800 "Bidirection Forwarding Detection\n"
801 "Zebra events debugging\n")
803 bglobal
.debug_zebra
= !no
;
808 bfd_debug_network
, bfd_debug_network_cmd
,
809 "[no] debug bfd network",
812 "Bidirection Forwarding Detection\n"
813 "Network layer debugging\n")
815 bglobal
.debug_network
= !no
;
820 * Function definitions.
824 * Configuration rules:
827 * peer + (interface name)
830 * peer + local + (optional vrf)
832 * Anything else is misconfiguration.
834 static int bfd_configure_peer(struct bfd_peer_cfg
*bpc
, bool mhop
,
835 const struct sockaddr_any
*peer
,
836 const struct sockaddr_any
*local
,
837 const char *ifname
, const char *vrfname
,
838 char *ebuf
, size_t ebuflen
)
840 memset(bpc
, 0, sizeof(*bpc
));
843 bpc
->bpc_shutdown
= true;
844 bpc
->bpc_detectmultiplier
= BPC_DEF_DETECTMULTIPLIER
;
845 bpc
->bpc_recvinterval
= BPC_DEF_RECEIVEINTERVAL
;
846 bpc
->bpc_txinterval
= BPC_DEF_TRANSMITINTERVAL
;
847 bpc
->bpc_echointerval
= BPC_DEF_ECHOINTERVAL
;
848 bpc
->bpc_lastevent
= monotime(NULL
);
850 /* Safety check: when no error buf is provided len must be zero. */
854 /* Peer is always mandatory. */
856 snprintf(ebuf
, ebuflen
, "peer must not be empty");
860 /* Validate address families. */
861 if (peer
->sa_sin
.sin_family
== AF_INET
) {
862 if (local
&& local
->sa_sin
.sin_family
!= AF_INET
) {
863 snprintf(ebuf
, ebuflen
,
864 "local is IPv6, but peer is IPv4");
868 bpc
->bpc_ipv4
= true;
869 } else if (peer
->sa_sin
.sin_family
== AF_INET6
) {
870 if (local
&& local
->sa_sin
.sin_family
!= AF_INET6
) {
871 snprintf(ebuf
, ebuflen
,
872 "local is IPv4, but peer is IPv6");
876 bpc
->bpc_ipv4
= false;
878 snprintf(ebuf
, ebuflen
, "invalid peer address family");
882 /* Copy local and/or peer addresses. */
884 bpc
->bpc_local
= *local
;
886 bpc
->bpc_peer
= *peer
;
887 bpc
->bpc_mhop
= mhop
;
889 /* Handle interface specification configuration. */
891 bpc
->bpc_has_localif
= true;
892 if (strlcpy(bpc
->bpc_localif
, ifname
, sizeof(bpc
->bpc_localif
))
893 > sizeof(bpc
->bpc_localif
)) {
894 snprintf(ebuf
, ebuflen
, "interface name too long");
899 /* Handle VRF configuration. */
901 bpc
->bpc_has_vrfname
= true;
902 if (strlcpy(bpc
->bpc_vrfname
, vrfname
, sizeof(bpc
->bpc_vrfname
))
903 > sizeof(bpc
->bpc_vrfname
)) {
904 snprintf(ebuf
, ebuflen
, "vrf name too long");
908 bpc
->bpc_has_vrfname
= true;
909 strlcpy(bpc
->bpc_vrfname
, VRF_DEFAULT_NAME
, sizeof(bpc
->bpc_vrfname
));
915 DEFUN_NOSH(show_debugging_bfd
,
916 show_debugging_bfd_cmd
,
917 "show debugging [bfd]",
922 vty_out(vty
, "BFD debugging status:\n");
923 if (bglobal
.debug_dplane
)
924 vty_out(vty
, " Distributed BFD debugging is on.\n");
925 if (bglobal
.debug_peer_event
)
926 vty_out(vty
, " Peer events debugging is on.\n");
927 if (bglobal
.debug_zebra
)
928 vty_out(vty
, " Zebra events debugging is on.\n");
929 if (bglobal
.debug_network
)
930 vty_out(vty
, " Network layer debugging is on.\n");
935 static int bfdd_write_config(struct vty
*vty
);
936 struct cmd_node bfd_node
= {
939 .parent_node
= CONFIG_NODE
,
940 .prompt
= "%s(config-bfd)# ",
941 .config_write
= bfdd_write_config
,
944 struct cmd_node bfd_peer_node
= {
946 .node
= BFD_PEER_NODE
,
947 .parent_node
= BFD_NODE
,
948 .prompt
= "%s(config-bfd-peer)# ",
951 static int bfdd_write_config(struct vty
*vty
)
953 struct lyd_node
*dnode
;
956 if (bglobal
.debug_dplane
) {
957 vty_out(vty
, "debug bfd distributed\n");
961 if (bglobal
.debug_peer_event
) {
962 vty_out(vty
, "debug bfd peer\n");
966 if (bglobal
.debug_zebra
) {
967 vty_out(vty
, "debug bfd zebra\n");
971 if (bglobal
.debug_network
) {
972 vty_out(vty
, "debug bfd network\n");
976 dnode
= yang_dnode_get(running_config
->dnode
, "/frr-bfdd:bfdd");
978 nb_cli_show_dnode_cmds(vty
, dnode
, false);
985 void bfdd_vty_init(void)
987 install_element(ENABLE_NODE
, &bfd_show_peers_counters_cmd
);
988 install_element(ENABLE_NODE
, &bfd_show_peer_counters_cmd
);
989 install_element(ENABLE_NODE
, &bfd_clear_peer_counters_cmd
);
990 install_element(ENABLE_NODE
, &bfd_show_peers_cmd
);
991 install_element(ENABLE_NODE
, &bfd_show_peer_cmd
);
992 install_element(ENABLE_NODE
, &bfd_show_peers_brief_cmd
);
993 install_element(ENABLE_NODE
, &show_bfd_distributed_cmd
);
994 install_element(ENABLE_NODE
, &show_debugging_bfd_cmd
);
996 install_element(ENABLE_NODE
, &bfd_debug_distributed_cmd
);
997 install_element(ENABLE_NODE
, &bfd_debug_peer_cmd
);
998 install_element(ENABLE_NODE
, &bfd_debug_zebra_cmd
);
999 install_element(ENABLE_NODE
, &bfd_debug_network_cmd
);
1001 install_element(CONFIG_NODE
, &bfd_debug_distributed_cmd
);
1002 install_element(CONFIG_NODE
, &bfd_debug_peer_cmd
);
1003 install_element(CONFIG_NODE
, &bfd_debug_zebra_cmd
);
1004 install_element(CONFIG_NODE
, &bfd_debug_network_cmd
);
1006 /* Install BFD node and commands. */
1007 install_node(&bfd_node
);
1008 install_default(BFD_NODE
);
1010 /* Install BFD peer node. */
1011 install_node(&bfd_peer_node
);
1012 install_default(BFD_PEER_NODE
);