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 void _display_rtt(uint32_t *min
, uint32_t *avg
, uint32_t *max
,
70 struct bfd_session
*bs
);
72 static struct bfd_session
*
73 _find_peer_or_error(struct vty
*vty
, int argc
, struct cmd_token
**argv
,
74 const char *label
, const char *peer_str
,
75 const char *local_str
, const char *ifname
,
80 * Show commands helper functions
82 static void _display_peer_header(struct vty
*vty
, struct bfd_session
*bs
)
84 char addr_buf
[INET6_ADDRSTRLEN
];
86 vty_out(vty
, "\tpeer %s",
87 inet_ntop(bs
->key
.family
, &bs
->key
.peer
, addr_buf
,
90 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
91 vty_out(vty
, " multihop");
93 if (memcmp(&bs
->key
.local
, &zero_addr
, sizeof(bs
->key
.local
)))
94 vty_out(vty
, " local-address %s",
95 inet_ntop(bs
->key
.family
, &bs
->key
.local
, addr_buf
,
98 if (bs
->key
.vrfname
[0])
99 vty_out(vty
, " vrf %s", bs
->key
.vrfname
);
100 if (bs
->key
.ifname
[0])
101 vty_out(vty
, " interface %s", bs
->key
.ifname
);
105 vty_out(vty
, "\t\tlabel: %s\n", bs
->pl
->pl_label
);
108 static void _display_peer(struct vty
*vty
, struct bfd_session
*bs
)
116 _display_peer_header(vty
, bs
);
118 vty_out(vty
, "\t\tID: %u\n", bs
->discrs
.my_discr
);
119 vty_out(vty
, "\t\tRemote ID: %u\n", bs
->discrs
.remote_discr
);
120 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_PASSIVE
))
121 vty_out(vty
, "\t\tPassive mode\n");
123 vty_out(vty
, "\t\tActive mode\n");
124 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
125 vty_out(vty
, "\t\tMinimum TTL: %d\n", bs
->mh_ttl
);
127 vty_out(vty
, "\t\tStatus: ");
128 switch (bs
->ses_state
) {
129 case PTM_BFD_ADM_DOWN
:
130 vty_out(vty
, "shutdown\n");
133 vty_out(vty
, "down\n");
135 now
= monotime(NULL
);
136 integer2timestr(now
- bs
->downtime
.tv_sec
, buf
, sizeof(buf
));
137 vty_out(vty
, "\t\tDowntime: %s\n", buf
);
140 vty_out(vty
, "init\n");
143 vty_out(vty
, "up\n");
145 now
= monotime(NULL
);
146 integer2timestr(now
- bs
->uptime
.tv_sec
, buf
, sizeof(buf
));
147 vty_out(vty
, "\t\tUptime: %s\n", buf
);
151 vty_out(vty
, "unknown\n");
155 vty_out(vty
, "\t\tDiagnostics: %s\n", diag2str(bs
->local_diag
));
156 vty_out(vty
, "\t\tRemote diagnostics: %s\n", diag2str(bs
->remote_diag
));
157 vty_out(vty
, "\t\tPeer Type: %s\n",
158 CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_CONFIG
) ? "configured" : "dynamic");
159 _display_rtt(&min
, &avg
, &max
, bs
);
160 vty_out(vty
, "\t\tRTT min/avg/max: %u/%u/%u usec\n", min
, avg
, max
);
162 vty_out(vty
, "\t\tLocal timers:\n");
163 vty_out(vty
, "\t\t\tDetect-multiplier: %u\n",
165 vty_out(vty
, "\t\t\tReceive interval: %ums\n",
166 bs
->timers
.required_min_rx
/ 1000);
167 vty_out(vty
, "\t\t\tTransmission interval: %ums\n",
168 bs
->timers
.desired_min_tx
/ 1000);
169 if (bs
->timers
.required_min_echo_rx
!= 0)
170 vty_out(vty
, "\t\t\tEcho receive interval: %ums\n",
171 bs
->timers
.required_min_echo_rx
/ 1000);
173 vty_out(vty
, "\t\t\tEcho receive interval: disabled\n");
174 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
))
175 vty_out(vty
, "\t\t\tEcho transmission interval: %ums\n",
176 bs
->timers
.desired_min_echo_tx
/ 1000);
178 vty_out(vty
, "\t\t\tEcho transmission interval: disabled\n");
180 vty_out(vty
, "\t\tRemote timers:\n");
181 vty_out(vty
, "\t\t\tDetect-multiplier: %u\n",
182 bs
->remote_detect_mult
);
183 vty_out(vty
, "\t\t\tReceive interval: %ums\n",
184 bs
->remote_timers
.required_min_rx
/ 1000);
185 vty_out(vty
, "\t\t\tTransmission interval: %ums\n",
186 bs
->remote_timers
.desired_min_tx
/ 1000);
187 if (bs
->remote_timers
.required_min_echo
!= 0)
188 vty_out(vty
, "\t\t\tEcho receive interval: %ums\n",
189 bs
->remote_timers
.required_min_echo
/ 1000);
191 vty_out(vty
, "\t\t\tEcho receive interval: disabled\n");
196 static struct json_object
*_peer_json_header(struct bfd_session
*bs
)
198 struct json_object
*jo
= json_object_new_object();
199 char addr_buf
[INET6_ADDRSTRLEN
];
202 json_object_boolean_true_add(jo
, "multihop");
204 json_object_boolean_false_add(jo
, "multihop");
206 json_object_string_add(jo
, "peer",
207 inet_ntop(bs
->key
.family
, &bs
->key
.peer
,
208 addr_buf
, sizeof(addr_buf
)));
209 if (memcmp(&bs
->key
.local
, &zero_addr
, sizeof(bs
->key
.local
)))
210 json_object_string_add(jo
, "local",
211 inet_ntop(bs
->key
.family
, &bs
->key
.local
,
212 addr_buf
, sizeof(addr_buf
)));
214 if (bs
->key
.vrfname
[0])
215 json_object_string_add(jo
, "vrf", bs
->key
.vrfname
);
216 if (bs
->key
.ifname
[0])
217 json_object_string_add(jo
, "interface", bs
->key
.ifname
);
220 json_object_string_add(jo
, "label", bs
->pl
->pl_label
);
225 static struct json_object
*__display_peer_json(struct bfd_session
*bs
)
227 struct json_object
*jo
= _peer_json_header(bs
);
232 json_object_int_add(jo
, "id", bs
->discrs
.my_discr
);
233 json_object_int_add(jo
, "remote-id", bs
->discrs
.remote_discr
);
234 json_object_boolean_add(jo
, "passive-mode",
235 CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_PASSIVE
));
236 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_MH
))
237 json_object_int_add(jo
, "minimum-ttl", bs
->mh_ttl
);
239 switch (bs
->ses_state
) {
240 case PTM_BFD_ADM_DOWN
:
241 json_object_string_add(jo
, "status", "shutdown");
244 json_object_string_add(jo
, "status", "down");
245 json_object_int_add(jo
, "downtime",
246 monotime(NULL
) - bs
->downtime
.tv_sec
);
249 json_object_string_add(jo
, "status", "init");
252 json_object_string_add(jo
, "status", "up");
253 json_object_int_add(jo
, "uptime",
254 monotime(NULL
) - bs
->uptime
.tv_sec
);
258 json_object_string_add(jo
, "status", "unknown");
262 json_object_string_add(jo
, "diagnostic", diag2str(bs
->local_diag
));
263 json_object_string_add(jo
, "remote-diagnostic",
264 diag2str(bs
->remote_diag
));
266 json_object_int_add(jo
, "receive-interval",
267 bs
->timers
.required_min_rx
/ 1000);
268 json_object_int_add(jo
, "transmit-interval",
269 bs
->timers
.desired_min_tx
/ 1000);
270 json_object_int_add(jo
, "echo-receive-interval",
271 bs
->timers
.required_min_echo_rx
/ 1000);
272 if (CHECK_FLAG(bs
->flags
, BFD_SESS_FLAG_ECHO
))
273 json_object_int_add(jo
, "echo-transmit-interval",
274 bs
->timers
.desired_min_echo_tx
/ 1000);
276 json_object_int_add(jo
, "echo-transmit-interval", 0);
278 json_object_int_add(jo
, "detect-multiplier", bs
->detect_mult
);
280 json_object_int_add(jo
, "remote-receive-interval",
281 bs
->remote_timers
.required_min_rx
/ 1000);
282 json_object_int_add(jo
, "remote-transmit-interval",
283 bs
->remote_timers
.desired_min_tx
/ 1000);
284 json_object_int_add(jo
, "remote-echo-receive-interval",
285 bs
->remote_timers
.required_min_echo
/ 1000);
286 json_object_int_add(jo
, "remote-detect-multiplier",
287 bs
->remote_detect_mult
);
289 _display_rtt(&min
, &avg
, &max
, bs
);
290 json_object_int_add(jo
, "rtt-min", min
);
291 json_object_int_add(jo
, "rtt-avg", avg
);
292 json_object_int_add(jo
, "rtt-max", max
);
297 static void _display_peer_json(struct vty
*vty
, struct bfd_session
*bs
)
299 struct json_object
*jo
= __display_peer_json(bs
);
304 struct bfd_vrf_tuple
{
307 struct json_object
*jo
;
310 static void _display_peer_iter(struct hash_bucket
*hb
, void *arg
)
312 struct bfd_vrf_tuple
*bvt
= (struct bfd_vrf_tuple
*)arg
;
314 struct bfd_session
*bs
= hb
->data
;
321 if (!bs
->key
.vrfname
[0] ||
322 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
325 _display_peer(vty
, bs
);
328 static void _display_peer_json_iter(struct hash_bucket
*hb
, void *arg
)
330 struct bfd_vrf_tuple
*bvt
= (struct bfd_vrf_tuple
*)arg
;
331 struct json_object
*jo
, *jon
= NULL
;
332 struct bfd_session
*bs
= hb
->data
;
339 if (!bs
->key
.vrfname
[0] ||
340 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
344 jon
= __display_peer_json(bs
);
346 zlog_warn("%s: not enough memory", __func__
);
350 json_object_array_add(jo
, jon
);
353 static void _display_all_peers(struct vty
*vty
, char *vrfname
, bool use_json
)
355 struct json_object
*jo
;
356 struct bfd_vrf_tuple bvt
= {0};
358 bvt
.vrfname
= vrfname
;
362 vty_out(vty
, "BFD Peers:\n");
363 bfd_id_iterate(_display_peer_iter
, &bvt
);
367 jo
= json_object_new_array();
369 bfd_id_iterate(_display_peer_json_iter
, &bvt
);
374 static void _display_peer_counter(struct vty
*vty
, struct bfd_session
*bs
)
376 _display_peer_header(vty
, bs
);
378 /* Ask data plane for updated counters. */
379 if (bfd_dplane_update_session_counters(bs
) == -1)
380 zlog_debug("%s: failed to update BFD session counters (%s)",
381 __func__
, bs_to_string(bs
));
383 vty_out(vty
, "\t\tControl packet input: %" PRIu64
" packets\n",
384 bs
->stats
.rx_ctrl_pkt
);
385 vty_out(vty
, "\t\tControl packet output: %" PRIu64
" packets\n",
386 bs
->stats
.tx_ctrl_pkt
);
387 vty_out(vty
, "\t\tEcho packet input: %" PRIu64
" packets\n",
388 bs
->stats
.rx_echo_pkt
);
389 vty_out(vty
, "\t\tEcho packet output: %" PRIu64
" packets\n",
390 bs
->stats
.tx_echo_pkt
);
391 vty_out(vty
, "\t\tSession up events: %" PRIu64
"\n",
392 bs
->stats
.session_up
);
393 vty_out(vty
, "\t\tSession down events: %" PRIu64
"\n",
394 bs
->stats
.session_down
);
395 vty_out(vty
, "\t\tZebra notifications: %" PRIu64
"\n",
396 bs
->stats
.znotification
);
400 static struct json_object
*__display_peer_counters_json(struct bfd_session
*bs
)
402 struct json_object
*jo
= _peer_json_header(bs
);
404 /* Ask data plane for updated counters. */
405 if (bfd_dplane_update_session_counters(bs
) == -1)
406 zlog_debug("%s: failed to update BFD session counters (%s)",
407 __func__
, bs_to_string(bs
));
409 json_object_int_add(jo
, "control-packet-input", bs
->stats
.rx_ctrl_pkt
);
410 json_object_int_add(jo
, "control-packet-output", bs
->stats
.tx_ctrl_pkt
);
411 json_object_int_add(jo
, "echo-packet-input", bs
->stats
.rx_echo_pkt
);
412 json_object_int_add(jo
, "echo-packet-output", bs
->stats
.tx_echo_pkt
);
413 json_object_int_add(jo
, "session-up", bs
->stats
.session_up
);
414 json_object_int_add(jo
, "session-down", bs
->stats
.session_down
);
415 json_object_int_add(jo
, "zebra-notifications", bs
->stats
.znotification
);
420 static void _display_peer_counters_json(struct vty
*vty
, struct bfd_session
*bs
)
422 struct json_object
*jo
= __display_peer_counters_json(bs
);
427 static void _display_peer_counter_iter(struct hash_bucket
*hb
, void *arg
)
429 struct bfd_vrf_tuple
*bvt
= arg
;
431 struct bfd_session
*bs
= hb
->data
;
438 if (!bs
->key
.vrfname
[0] ||
439 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
443 _display_peer_counter(vty
, bs
);
446 static void _display_peer_counter_json_iter(struct hash_bucket
*hb
, void *arg
)
448 struct json_object
*jo
, *jon
= NULL
;
449 struct bfd_session
*bs
= hb
->data
;
450 struct bfd_vrf_tuple
*bvt
= arg
;
457 if (!bs
->key
.vrfname
[0] ||
458 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
462 jon
= __display_peer_counters_json(bs
);
464 zlog_warn("%s: not enough memory", __func__
);
468 json_object_array_add(jo
, jon
);
471 static void _display_peers_counter(struct vty
*vty
, char *vrfname
, bool use_json
)
473 struct json_object
*jo
;
474 struct bfd_vrf_tuple bvt
= {0};
476 bvt
.vrfname
= vrfname
;
479 vty_out(vty
, "BFD Peers:\n");
480 bfd_id_iterate(_display_peer_counter_iter
, &bvt
);
484 jo
= json_object_new_array();
486 bfd_id_iterate(_display_peer_counter_json_iter
, &bvt
);
491 static void _clear_peer_counter(struct bfd_session
*bs
)
493 /* Clear only pkt stats, intention is not to loose system
495 bs
->stats
.rx_ctrl_pkt
= 0;
496 bs
->stats
.tx_ctrl_pkt
= 0;
497 bs
->stats
.rx_echo_pkt
= 0;
498 bs
->stats
.tx_echo_pkt
= 0;
501 static void _display_peer_brief(struct vty
*vty
, struct bfd_session
*bs
)
503 char addr_buf
[INET6_ADDRSTRLEN
];
505 vty_out(vty
, "%-10u", bs
->discrs
.my_discr
);
506 inet_ntop(bs
->key
.family
, &bs
->key
.local
, addr_buf
, sizeof(addr_buf
));
507 vty_out(vty
, " %-40s", addr_buf
);
508 inet_ntop(bs
->key
.family
, &bs
->key
.peer
, addr_buf
, sizeof(addr_buf
));
509 vty_out(vty
, " %-40s", addr_buf
);
510 vty_out(vty
, "%-15s\n", state_list
[bs
->ses_state
].str
);
513 static void _display_peer_brief_iter(struct hash_bucket
*hb
, void *arg
)
515 struct bfd_vrf_tuple
*bvt
= arg
;
517 struct bfd_session
*bs
= hb
->data
;
524 if (!bs
->key
.vrfname
[0] ||
525 !strmatch(bs
->key
.vrfname
, bvt
->vrfname
))
529 _display_peer_brief(vty
, bs
);
532 static void _display_peers_brief(struct vty
*vty
, const char *vrfname
, bool use_json
)
534 struct json_object
*jo
;
535 struct bfd_vrf_tuple bvt
= {0};
537 bvt
.vrfname
= vrfname
;
542 vty_out(vty
, "Session count: %lu\n", bfd_get_session_count());
543 vty_out(vty
, "%-10s", "SessionId");
544 vty_out(vty
, " %-40s", "LocalAddress");
545 vty_out(vty
, " %-40s", "PeerAddress");
546 vty_out(vty
, "%-15s\n", "Status");
548 vty_out(vty
, "%-10s", "=========");
549 vty_out(vty
, " %-40s", "============");
550 vty_out(vty
, " %-40s", "===========");
551 vty_out(vty
, "%-15s\n", "======");
553 bfd_id_iterate(_display_peer_brief_iter
, &bvt
);
557 jo
= json_object_new_array();
560 bfd_id_iterate(_display_peer_json_iter
, &bvt
);
565 static struct bfd_session
*
566 _find_peer_or_error(struct vty
*vty
, int argc
, struct cmd_token
**argv
,
567 const char *label
, const char *peer_str
,
568 const char *local_str
, const char *ifname
,
573 struct bfd_session
*bs
= NULL
;
574 struct peer_label
*pl
;
575 struct bfd_peer_cfg bpc
;
576 struct sockaddr_any psa
, lsa
, *lsap
;
579 /* Look up the BFD peer. */
584 } else if (peer_str
) {
585 strtosa(peer_str
, &psa
);
587 strtosa(local_str
, &lsa
);
593 mhop
= argv_find(argv
, argc
, "multihop", &idx
);
595 if (bfd_configure_peer(&bpc
, mhop
, &psa
, lsap
, ifname
, vrfname
,
596 errormsg
, sizeof(errormsg
))
598 vty_out(vty
, "%% Invalid peer configuration: %s\n",
603 bs
= bs_peer_find(&bpc
);
605 vty_out(vty
, "%% Invalid arguments\n");
609 /* Find peer data. */
611 vty_out(vty
, "%% Unable to find 'peer %s",
612 label
? label
: peer_str
);
614 vty_out(vty
, " interface %s", ifname
);
616 vty_out(vty
, " local-address %s", local_str
);
618 vty_out(vty
, " vrf %s", vrfname
);
627 void _display_rtt(uint32_t *min
, uint32_t *avg
, uint32_t *max
,
628 struct bfd_session
*bs
)
632 uint32_t average
= 0;
634 if (bs
->rtt_valid
== 0)
641 for (i
= 0; i
< bs
->rtt_valid
; i
++) {
642 if (bs
->rtt
[i
] < *min
)
644 if (bs
->rtt
[i
] > *max
)
646 average
+= bs
->rtt
[i
];
648 *avg
= average
/ bs
->rtt_valid
;
656 DEFPY(bfd_show_peers
, bfd_show_peers_cmd
, "show bfd [vrf NAME] peers [json]",
658 "Bidirection Forwarding Detection\n"
660 "BFD peers status\n" JSON_STR
)
662 char *vrf_name
= NULL
;
665 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
666 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
668 _display_all_peers(vty
, vrf_name
, use_json(argc
, argv
));
673 DEFPY(bfd_show_peer
, bfd_show_peer_cmd
,
674 "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]",
676 "Bidirection Forwarding Detection\n"
679 "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
680 LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR
)
682 struct bfd_session
*bs
;
684 /* Look up the BFD peer. */
685 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
688 return CMD_WARNING_CONFIG_FAILED
;
690 if (use_json(argc
, argv
)) {
691 _display_peer_json(vty
, bs
);
693 vty_out(vty
, "BFD Peer:\n");
694 _display_peer(vty
, bs
);
700 DEFPY(bfd_show_peer_counters
, bfd_show_peer_counters_cmd
,
701 "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]",
703 "Bidirection Forwarding Detection\n"
715 "Show BFD peer counters information\n"
718 struct bfd_session
*bs
;
720 /* Look up the BFD peer. */
721 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
724 return CMD_WARNING_CONFIG_FAILED
;
726 if (use_json(argc
, argv
))
727 _display_peer_counters_json(vty
, bs
);
729 _display_peer_counter(vty
, bs
);
734 DEFPY(bfd_show_peers_counters
, bfd_show_peers_counters_cmd
,
735 "show bfd [vrf NAME] peers counters [json]",
737 "Bidirection Forwarding Detection\n"
740 "Show BFD peer counters information\n"
743 char *vrf_name
= NULL
;
746 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
747 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
749 _display_peers_counter(vty
, vrf_name
, use_json(argc
, argv
));
754 DEFPY(bfd_clear_peer_counters
, bfd_clear_peer_counters_cmd
,
755 "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",
757 "Bidirection Forwarding Detection\n"
769 "clear BFD peer counters information\n")
771 struct bfd_session
*bs
;
773 /* Look up the BFD peer. */
774 bs
= _find_peer_or_error(vty
, argc
, argv
, label
, peer_str
, local_str
,
777 return CMD_WARNING_CONFIG_FAILED
;
779 _clear_peer_counter(bs
);
784 DEFPY(bfd_show_peers_brief
, bfd_show_peers_brief_cmd
,
785 "show bfd [vrf <NAME$vrfname>] peers brief [json]",
787 "Bidirection Forwarding Detection\n"
790 "Show BFD peer information in tabular form\n"
793 char *vrf_name
= NULL
;
796 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
797 vrf_name
= argv
[idx_vrf
+ 1]->arg
;
799 _display_peers_brief(vty
, vrf_name
, use_json(argc
, argv
));
804 DEFPY(show_bfd_distributed
, show_bfd_distributed_cmd
,
805 "show bfd distributed",
807 "Bidirection Forwarding Detection\n"
808 "Show BFD data plane (distributed BFD) statistics\n")
810 bfd_dplane_show_counters(vty
);
815 bfd_debug_distributed
, bfd_debug_distributed_cmd
,
816 "[no] debug bfd distributed",
819 "Bidirection Forwarding Detection\n"
820 "BFD data plane (distributed BFD) debugging\n")
822 bglobal
.debug_dplane
= !no
;
827 bfd_debug_peer
, bfd_debug_peer_cmd
,
828 "[no] debug bfd peer",
831 "Bidirection Forwarding Detection\n"
832 "Peer events debugging\n")
834 bglobal
.debug_peer_event
= !no
;
839 bfd_debug_zebra
, bfd_debug_zebra_cmd
,
840 "[no] debug bfd zebra",
843 "Bidirection Forwarding Detection\n"
844 "Zebra events debugging\n")
846 bglobal
.debug_zebra
= !no
;
851 bfd_debug_network
, bfd_debug_network_cmd
,
852 "[no] debug bfd network",
855 "Bidirection Forwarding Detection\n"
856 "Network layer debugging\n")
858 bglobal
.debug_network
= !no
;
863 * Function definitions.
867 * Configuration rules:
870 * peer + (interface name)
873 * peer + local + (optional vrf)
875 * Anything else is misconfiguration.
877 static int bfd_configure_peer(struct bfd_peer_cfg
*bpc
, bool mhop
,
878 const struct sockaddr_any
*peer
,
879 const struct sockaddr_any
*local
,
880 const char *ifname
, const char *vrfname
,
881 char *ebuf
, size_t ebuflen
)
883 memset(bpc
, 0, sizeof(*bpc
));
886 bpc
->bpc_shutdown
= false;
887 bpc
->bpc_detectmultiplier
= BPC_DEF_DETECTMULTIPLIER
;
888 bpc
->bpc_recvinterval
= BPC_DEF_RECEIVEINTERVAL
;
889 bpc
->bpc_txinterval
= BPC_DEF_TRANSMITINTERVAL
;
890 bpc
->bpc_echorecvinterval
= BPC_DEF_ECHORECEIVEINTERVAL
;
891 bpc
->bpc_echotxinterval
= BPC_DEF_ECHOTRANSMITINTERVAL
;
892 bpc
->bpc_lastevent
= monotime(NULL
);
894 /* Safety check: when no error buf is provided len must be zero. */
898 /* Peer is always mandatory. */
900 snprintf(ebuf
, ebuflen
, "peer must not be empty");
904 /* Validate address families. */
905 if (peer
->sa_sin
.sin_family
== AF_INET
) {
906 if (local
&& local
->sa_sin
.sin_family
!= AF_INET
) {
907 snprintf(ebuf
, ebuflen
,
908 "local is IPv6, but peer is IPv4");
912 bpc
->bpc_ipv4
= true;
913 } else if (peer
->sa_sin
.sin_family
== AF_INET6
) {
914 if (local
&& local
->sa_sin
.sin_family
!= AF_INET6
) {
915 snprintf(ebuf
, ebuflen
,
916 "local is IPv4, but peer is IPv6");
920 bpc
->bpc_ipv4
= false;
922 snprintf(ebuf
, ebuflen
, "invalid peer address family");
926 /* Copy local and/or peer addresses. */
928 bpc
->bpc_local
= *local
;
930 bpc
->bpc_peer
= *peer
;
931 bpc
->bpc_mhop
= mhop
;
933 /* Handle interface specification configuration. */
935 bpc
->bpc_has_localif
= true;
936 if (strlcpy(bpc
->bpc_localif
, ifname
, sizeof(bpc
->bpc_localif
))
937 > sizeof(bpc
->bpc_localif
)) {
938 snprintf(ebuf
, ebuflen
, "interface name too long");
943 /* Handle VRF configuration. */
945 bpc
->bpc_has_vrfname
= true;
946 if (strlcpy(bpc
->bpc_vrfname
, vrfname
, sizeof(bpc
->bpc_vrfname
))
947 > sizeof(bpc
->bpc_vrfname
)) {
948 snprintf(ebuf
, ebuflen
, "vrf name too long");
952 bpc
->bpc_has_vrfname
= true;
953 strlcpy(bpc
->bpc_vrfname
, VRF_DEFAULT_NAME
, sizeof(bpc
->bpc_vrfname
));
959 DEFUN_NOSH(show_debugging_bfd
,
960 show_debugging_bfd_cmd
,
961 "show debugging [bfd]",
966 vty_out(vty
, "BFD debugging status:\n");
967 if (bglobal
.debug_dplane
)
968 vty_out(vty
, " Distributed BFD debugging is on.\n");
969 if (bglobal
.debug_peer_event
)
970 vty_out(vty
, " Peer events debugging is on.\n");
971 if (bglobal
.debug_zebra
)
972 vty_out(vty
, " Zebra events debugging is on.\n");
973 if (bglobal
.debug_network
)
974 vty_out(vty
, " Network layer debugging is on.\n");
979 static int bfdd_write_config(struct vty
*vty
);
980 struct cmd_node bfd_node
= {
983 .parent_node
= CONFIG_NODE
,
984 .prompt
= "%s(config-bfd)# ",
985 .config_write
= bfdd_write_config
,
988 struct cmd_node bfd_peer_node
= {
990 .node
= BFD_PEER_NODE
,
991 .parent_node
= BFD_NODE
,
992 .prompt
= "%s(config-bfd-peer)# ",
995 static int bfdd_write_config(struct vty
*vty
)
997 struct lyd_node
*dnode
;
1000 if (bglobal
.debug_dplane
) {
1001 vty_out(vty
, "debug bfd distributed\n");
1005 if (bglobal
.debug_peer_event
) {
1006 vty_out(vty
, "debug bfd peer\n");
1010 if (bglobal
.debug_zebra
) {
1011 vty_out(vty
, "debug bfd zebra\n");
1015 if (bglobal
.debug_network
) {
1016 vty_out(vty
, "debug bfd network\n");
1020 dnode
= yang_dnode_get(running_config
->dnode
, "/frr-bfdd:bfdd");
1022 nb_cli_show_dnode_cmds(vty
, dnode
, false);
1029 void bfdd_vty_init(void)
1031 install_element(ENABLE_NODE
, &bfd_show_peers_counters_cmd
);
1032 install_element(ENABLE_NODE
, &bfd_show_peer_counters_cmd
);
1033 install_element(ENABLE_NODE
, &bfd_clear_peer_counters_cmd
);
1034 install_element(ENABLE_NODE
, &bfd_show_peers_cmd
);
1035 install_element(ENABLE_NODE
, &bfd_show_peer_cmd
);
1036 install_element(ENABLE_NODE
, &bfd_show_peers_brief_cmd
);
1037 install_element(ENABLE_NODE
, &show_bfd_distributed_cmd
);
1038 install_element(ENABLE_NODE
, &show_debugging_bfd_cmd
);
1040 install_element(ENABLE_NODE
, &bfd_debug_distributed_cmd
);
1041 install_element(ENABLE_NODE
, &bfd_debug_peer_cmd
);
1042 install_element(ENABLE_NODE
, &bfd_debug_zebra_cmd
);
1043 install_element(ENABLE_NODE
, &bfd_debug_network_cmd
);
1045 install_element(CONFIG_NODE
, &bfd_debug_distributed_cmd
);
1046 install_element(CONFIG_NODE
, &bfd_debug_peer_cmd
);
1047 install_element(CONFIG_NODE
, &bfd_debug_zebra_cmd
);
1048 install_element(CONFIG_NODE
, &bfd_debug_network_cmd
);
1050 /* Install BFD node and commands. */
1051 install_node(&bfd_node
);
1052 install_default(BFD_NODE
);
1054 /* Install BFD peer node. */
1055 install_node(&bfd_peer_node
);
1056 install_default(BFD_PEER_NODE
);