]> git.proxmox.com Git - mirror_frr.git/blame - bfdd/bfdd_vty.c
Merge pull request #12645 from gpnaveen/ospf_error_msg_enhancements
[mirror_frr.git] / bfdd / bfdd_vty.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
c2f29cf3
RZ
2/*
3 * BFD daemon code
4 * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
c2f29cf3
RZ
5 */
6
7#include <zebra.h>
8
9#include "lib/command.h"
10#include "lib/json.h"
11#include "lib/log.h"
0287a64a 12#include "lib/northbound_cli.h"
c2f29cf3
RZ
13#include "lib/vty.h"
14
15#include "bfd.h"
16
c2f29cf3 17#include "bfdd/bfdd_vty_clippy.c"
c2f29cf3
RZ
18
19/*
20 * Commands help string definitions.
21 */
c2f29cf3
RZ
22#define PEER_IPV4_STR "IPv4 peer address\n"
23#define PEER_IPV6_STR "IPv6 peer address\n"
24#define MHOP_STR "Configure multihop\n"
25#define LOCAL_STR "Configure local address\n"
26#define LOCAL_IPV4_STR "IPv4 local address\n"
27#define LOCAL_IPV6_STR "IPv6 local address\n"
28#define LOCAL_INTF_STR "Configure local interface name to use\n"
c2f29cf3
RZ
29
30/*
31 * Prototypes
32 */
c2f29cf3
RZ
33static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
34 const struct sockaddr_any *peer,
35 const struct sockaddr_any *local,
36 const char *ifname, const char *vrfname,
37 char *ebuf, size_t ebuflen);
38
89a634c1 39static void _display_peer_header(struct vty *vty, struct bfd_session *bs);
c2f29cf3 40static struct json_object *__display_peer_json(struct bfd_session *bs);
89a634c1 41static struct json_object *_peer_json_header(struct bfd_session *bs);
c2f29cf3
RZ
42static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
43static void _display_peer(struct vty *vty, struct bfd_session *bs);
9146cc2a 44static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json);
e3b78da8
TB
45static void _display_peer_iter(struct hash_bucket *hb, void *arg);
46static void _display_peer_json_iter(struct hash_bucket *hb, void *arg);
0684c9b1
RZ
47static void _display_peer_counter(struct vty *vty, struct bfd_session *bs);
48static struct json_object *__display_peer_counters_json(struct bfd_session *bs);
49static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs);
e3b78da8
TB
50static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg);
51static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg);
6f374165 52static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json);
618a06fe 53static void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
54 struct bfd_session *bs);
55
89a634c1
RZ
56static struct bfd_session *
57_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
58 const char *label, const char *peer_str,
59 const char *local_str, const char *ifname,
60 const char *vrfname);
c2f29cf3 61
c2f29cf3
RZ
62
63/*
64 * Show commands helper functions
65 */
89a634c1 66static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
c2f29cf3 67{
79b4a6fc
RZ
68 char addr_buf[INET6_ADDRSTRLEN];
69
70 vty_out(vty, "\tpeer %s",
71 inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
72 sizeof(addr_buf)));
73
b88113ef 74 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
c2f29cf3 75 vty_out(vty, " multihop");
79b4a6fc
RZ
76
77 if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
78 vty_out(vty, " local-address %s",
79 inet_ntop(bs->key.family, &bs->key.local, addr_buf,
80 sizeof(addr_buf)));
81
82 if (bs->key.vrfname[0])
83 vty_out(vty, " vrf %s", bs->key.vrfname);
84 if (bs->key.ifname[0])
85 vty_out(vty, " interface %s", bs->key.ifname);
86 vty_out(vty, "\n");
c2f29cf3
RZ
87
88 if (bs->pl)
89 vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
89a634c1
RZ
90}
91
92static void _display_peer(struct vty *vty, struct bfd_session *bs)
93{
94 char buf[256];
95 time_t now;
618a06fe 96 uint32_t min = 0;
97 uint32_t avg = 0;
98 uint32_t max = 0;
89a634c1
RZ
99
100 _display_peer_header(vty, bs);
c2f29cf3
RZ
101
102 vty_out(vty, "\t\tID: %u\n", bs->discrs.my_discr);
103 vty_out(vty, "\t\tRemote ID: %u\n", bs->discrs.remote_discr);
1a2e2fff
RZ
104 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE))
105 vty_out(vty, "\t\tPassive mode\n");
106 else
107 vty_out(vty, "\t\tActive mode\n");
262e1d25
RZ
108 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
109 vty_out(vty, "\t\tMinimum TTL: %d\n", bs->mh_ttl);
c2f29cf3
RZ
110
111 vty_out(vty, "\t\tStatus: ");
112 switch (bs->ses_state) {
113 case PTM_BFD_ADM_DOWN:
114 vty_out(vty, "shutdown\n");
115 break;
116 case PTM_BFD_DOWN:
117 vty_out(vty, "down\n");
118
119 now = monotime(NULL);
98ef9c16 120 integer2timestr(now - bs->downtime.tv_sec, buf, sizeof(buf));
c2f29cf3
RZ
121 vty_out(vty, "\t\tDowntime: %s\n", buf);
122 break;
123 case PTM_BFD_INIT:
124 vty_out(vty, "init\n");
125 break;
126 case PTM_BFD_UP:
127 vty_out(vty, "up\n");
128
129 now = monotime(NULL);
130 integer2timestr(now - bs->uptime.tv_sec, buf, sizeof(buf));
131 vty_out(vty, "\t\tUptime: %s\n", buf);
132 break;
133
134 default:
135 vty_out(vty, "unknown\n");
136 break;
137 }
138
139 vty_out(vty, "\t\tDiagnostics: %s\n", diag2str(bs->local_diag));
140 vty_out(vty, "\t\tRemote diagnostics: %s\n", diag2str(bs->remote_diag));
825e3b94 141 vty_out(vty, "\t\tPeer Type: %s\n",
b88113ef 142 CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) ? "configured" : "dynamic");
618a06fe 143 _display_rtt(&min, &avg, &max, bs);
144 vty_out(vty, "\t\tRTT min/avg/max: %u/%u/%u usec\n", min, avg, max);
c2f29cf3
RZ
145
146 vty_out(vty, "\t\tLocal timers:\n");
6cde4b45 147 vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
825e3b94 148 bs->detect_mult);
6cde4b45 149 vty_out(vty, "\t\t\tReceive interval: %ums\n",
c2f29cf3 150 bs->timers.required_min_rx / 1000);
6cde4b45 151 vty_out(vty, "\t\t\tTransmission interval: %ums\n",
c2f29cf3 152 bs->timers.desired_min_tx / 1000);
4df3e31c
IR
153 if (bs->timers.required_min_echo_rx != 0)
154 vty_out(vty, "\t\t\tEcho receive interval: %ums\n",
155 bs->timers.required_min_echo_rx / 1000);
156 else
157 vty_out(vty, "\t\t\tEcho receive interval: disabled\n");
158 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
159 vty_out(vty, "\t\t\tEcho transmission interval: %ums\n",
160 bs->timers.desired_min_echo_tx / 1000);
161 else
162 vty_out(vty, "\t\t\tEcho transmission interval: disabled\n");
c2f29cf3
RZ
163
164 vty_out(vty, "\t\tRemote timers:\n");
6cde4b45 165 vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
825e3b94 166 bs->remote_detect_mult);
6cde4b45 167 vty_out(vty, "\t\t\tReceive interval: %ums\n",
c2f29cf3 168 bs->remote_timers.required_min_rx / 1000);
6cde4b45 169 vty_out(vty, "\t\t\tTransmission interval: %ums\n",
c2f29cf3 170 bs->remote_timers.desired_min_tx / 1000);
4df3e31c
IR
171 if (bs->remote_timers.required_min_echo != 0)
172 vty_out(vty, "\t\t\tEcho receive interval: %ums\n",
173 bs->remote_timers.required_min_echo / 1000);
174 else
175 vty_out(vty, "\t\t\tEcho receive interval: disabled\n");
c2f29cf3
RZ
176
177 vty_out(vty, "\n");
178}
179
89a634c1 180static struct json_object *_peer_json_header(struct bfd_session *bs)
c2f29cf3
RZ
181{
182 struct json_object *jo = json_object_new_object();
79b4a6fc 183 char addr_buf[INET6_ADDRSTRLEN];
c2f29cf3 184
79b4a6fc 185 if (bs->key.mhop)
c2f29cf3 186 json_object_boolean_true_add(jo, "multihop");
79b4a6fc 187 else
c2f29cf3 188 json_object_boolean_false_add(jo, "multihop");
79b4a6fc
RZ
189
190 json_object_string_add(jo, "peer",
191 inet_ntop(bs->key.family, &bs->key.peer,
192 addr_buf, sizeof(addr_buf)));
193 if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
194 json_object_string_add(jo, "local",
195 inet_ntop(bs->key.family, &bs->key.local,
196 addr_buf, sizeof(addr_buf)));
197
198 if (bs->key.vrfname[0])
199 json_object_string_add(jo, "vrf", bs->key.vrfname);
200 if (bs->key.ifname[0])
201 json_object_string_add(jo, "interface", bs->key.ifname);
c2f29cf3
RZ
202
203 if (bs->pl)
204 json_object_string_add(jo, "label", bs->pl->pl_label);
205
89a634c1
RZ
206 return jo;
207}
208
209static struct json_object *__display_peer_json(struct bfd_session *bs)
210{
211 struct json_object *jo = _peer_json_header(bs);
618a06fe 212 uint32_t min = 0;
213 uint32_t avg = 0;
214 uint32_t max = 0;
89a634c1 215
c2f29cf3
RZ
216 json_object_int_add(jo, "id", bs->discrs.my_discr);
217 json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
1a2e2fff
RZ
218 json_object_boolean_add(jo, "passive-mode",
219 CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE));
262e1d25
RZ
220 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
221 json_object_int_add(jo, "minimum-ttl", bs->mh_ttl);
c2f29cf3
RZ
222
223 switch (bs->ses_state) {
224 case PTM_BFD_ADM_DOWN:
225 json_object_string_add(jo, "status", "shutdown");
226 break;
227 case PTM_BFD_DOWN:
228 json_object_string_add(jo, "status", "down");
229 json_object_int_add(jo, "downtime",
98ef9c16 230 monotime(NULL) - bs->downtime.tv_sec);
c2f29cf3
RZ
231 break;
232 case PTM_BFD_INIT:
233 json_object_string_add(jo, "status", "init");
234 break;
235 case PTM_BFD_UP:
236 json_object_string_add(jo, "status", "up");
237 json_object_int_add(jo, "uptime",
238 monotime(NULL) - bs->uptime.tv_sec);
239 break;
240
241 default:
242 json_object_string_add(jo, "status", "unknown");
243 break;
244 }
245
246 json_object_string_add(jo, "diagnostic", diag2str(bs->local_diag));
247 json_object_string_add(jo, "remote-diagnostic",
248 diag2str(bs->remote_diag));
249
250 json_object_int_add(jo, "receive-interval",
251 bs->timers.required_min_rx / 1000);
252 json_object_int_add(jo, "transmit-interval",
253 bs->timers.desired_min_tx / 1000);
4df3e31c
IR
254 json_object_int_add(jo, "echo-receive-interval",
255 bs->timers.required_min_echo_rx / 1000);
b88113ef 256 if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
4df3e31c
IR
257 json_object_int_add(jo, "echo-transmit-interval",
258 bs->timers.desired_min_echo_tx / 1000);
c2f29cf3 259 else
4df3e31c 260 json_object_int_add(jo, "echo-transmit-interval", 0);
c2f29cf3 261
1d0a11e6
S
262 json_object_int_add(jo, "detect-multiplier", bs->detect_mult);
263
c2f29cf3
RZ
264 json_object_int_add(jo, "remote-receive-interval",
265 bs->remote_timers.required_min_rx / 1000);
266 json_object_int_add(jo, "remote-transmit-interval",
267 bs->remote_timers.desired_min_tx / 1000);
4df3e31c 268 json_object_int_add(jo, "remote-echo-receive-interval",
c2f29cf3 269 bs->remote_timers.required_min_echo / 1000);
1d0a11e6
S
270 json_object_int_add(jo, "remote-detect-multiplier",
271 bs->remote_detect_mult);
c2f29cf3 272
618a06fe 273 _display_rtt(&min, &avg, &max, bs);
274 json_object_int_add(jo, "rtt-min", min);
275 json_object_int_add(jo, "rtt-avg", avg);
276 json_object_int_add(jo, "rtt-max", max);
277
c2f29cf3
RZ
278 return jo;
279}
280
281static void _display_peer_json(struct vty *vty, struct bfd_session *bs)
282{
283 struct json_object *jo = __display_peer_json(bs);
284
4e37fcb6 285 vty_json(vty, jo);
c2f29cf3
RZ
286}
287
9146cc2a 288struct bfd_vrf_tuple {
fa6e709f 289 const char *vrfname;
9146cc2a
PG
290 struct vty *vty;
291 struct json_object *jo;
292};
293
e3b78da8 294static void _display_peer_iter(struct hash_bucket *hb, void *arg)
c2f29cf3 295{
9146cc2a
PG
296 struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
297 struct vty *vty;
c2f29cf3
RZ
298 struct bfd_session *bs = hb->data;
299
9146cc2a
PG
300 if (!bvt)
301 return;
302 vty = bvt->vty;
303
304 if (bvt->vrfname) {
305 if (!bs->key.vrfname[0] ||
306 !strmatch(bs->key.vrfname, bvt->vrfname))
307 return;
308 }
c2f29cf3
RZ
309 _display_peer(vty, bs);
310}
311
e3b78da8 312static void _display_peer_json_iter(struct hash_bucket *hb, void *arg)
c2f29cf3 313{
9146cc2a
PG
314 struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
315 struct json_object *jo, *jon = NULL;
c2f29cf3
RZ
316 struct bfd_session *bs = hb->data;
317
9146cc2a
PG
318 if (!bvt)
319 return;
320 jo = bvt->jo;
321
322 if (bvt->vrfname) {
323 if (!bs->key.vrfname[0] ||
324 !strmatch(bs->key.vrfname, bvt->vrfname))
325 return;
326 }
327
c2f29cf3
RZ
328 jon = __display_peer_json(bs);
329 if (jon == NULL) {
259b64eb 330 zlog_warn("%s: not enough memory", __func__);
c2f29cf3
RZ
331 return;
332 }
333
334 json_object_array_add(jo, jon);
335}
336
9146cc2a 337static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json)
c2f29cf3
RZ
338{
339 struct json_object *jo;
1d0a11e6 340 struct bfd_vrf_tuple bvt = {0};
9146cc2a 341
9146cc2a 342 bvt.vrfname = vrfname;
c2f29cf3 343
d8729f8c 344 if (!use_json) {
9146cc2a 345 bvt.vty = vty;
89a634c1 346 vty_out(vty, "BFD Peers:\n");
9146cc2a 347 bfd_id_iterate(_display_peer_iter, &bvt);
c2f29cf3
RZ
348 return;
349 }
350
351 jo = json_object_new_array();
9146cc2a
PG
352 bvt.jo = jo;
353 bfd_id_iterate(_display_peer_json_iter, &bvt);
c2f29cf3 354
4e37fcb6 355 vty_json(vty, jo);
c2f29cf3
RZ
356}
357
0684c9b1
RZ
358static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
359{
360 _display_peer_header(vty, bs);
361
400632a9
RZ
362 /* Ask data plane for updated counters. */
363 if (bfd_dplane_update_session_counters(bs) == -1)
364 zlog_debug("%s: failed to update BFD session counters (%s)",
365 __func__, bs_to_string(bs));
366
0684c9b1
RZ
367 vty_out(vty, "\t\tControl packet input: %" PRIu64 " packets\n",
368 bs->stats.rx_ctrl_pkt);
369 vty_out(vty, "\t\tControl packet output: %" PRIu64 " packets\n",
370 bs->stats.tx_ctrl_pkt);
371 vty_out(vty, "\t\tEcho packet input: %" PRIu64 " packets\n",
372 bs->stats.rx_echo_pkt);
373 vty_out(vty, "\t\tEcho packet output: %" PRIu64 " packets\n",
374 bs->stats.tx_echo_pkt);
375 vty_out(vty, "\t\tSession up events: %" PRIu64 "\n",
376 bs->stats.session_up);
377 vty_out(vty, "\t\tSession down events: %" PRIu64 "\n",
378 bs->stats.session_down);
379 vty_out(vty, "\t\tZebra notifications: %" PRIu64 "\n",
380 bs->stats.znotification);
381 vty_out(vty, "\n");
382}
383
384static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
385{
386 struct json_object *jo = _peer_json_header(bs);
387
400632a9
RZ
388 /* Ask data plane for updated counters. */
389 if (bfd_dplane_update_session_counters(bs) == -1)
390 zlog_debug("%s: failed to update BFD session counters (%s)",
391 __func__, bs_to_string(bs));
392
0684c9b1
RZ
393 json_object_int_add(jo, "control-packet-input", bs->stats.rx_ctrl_pkt);
394 json_object_int_add(jo, "control-packet-output", bs->stats.tx_ctrl_pkt);
395 json_object_int_add(jo, "echo-packet-input", bs->stats.rx_echo_pkt);
396 json_object_int_add(jo, "echo-packet-output", bs->stats.tx_echo_pkt);
397 json_object_int_add(jo, "session-up", bs->stats.session_up);
398 json_object_int_add(jo, "session-down", bs->stats.session_down);
399 json_object_int_add(jo, "zebra-notifications", bs->stats.znotification);
400
401 return jo;
402}
403
404static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
405{
406 struct json_object *jo = __display_peer_counters_json(bs);
407
4e37fcb6 408 vty_json(vty, jo);
0684c9b1
RZ
409}
410
e3b78da8 411static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg)
0684c9b1 412{
6f374165
PG
413 struct bfd_vrf_tuple *bvt = arg;
414 struct vty *vty;
0684c9b1
RZ
415 struct bfd_session *bs = hb->data;
416
6f374165
PG
417 if (!bvt)
418 return;
419 vty = bvt->vty;
420
421 if (bvt->vrfname) {
422 if (!bs->key.vrfname[0] ||
423 !strmatch(bs->key.vrfname, bvt->vrfname))
424 return;
425 }
426
0684c9b1
RZ
427 _display_peer_counter(vty, bs);
428}
429
e3b78da8 430static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg)
0684c9b1 431{
6f374165 432 struct json_object *jo, *jon = NULL;
0684c9b1 433 struct bfd_session *bs = hb->data;
6f374165
PG
434 struct bfd_vrf_tuple *bvt = arg;
435
436 if (!bvt)
437 return;
438 jo = bvt->jo;
439
440 if (bvt->vrfname) {
441 if (!bs->key.vrfname[0] ||
442 !strmatch(bs->key.vrfname, bvt->vrfname))
443 return;
444 }
0684c9b1
RZ
445
446 jon = __display_peer_counters_json(bs);
447 if (jon == NULL) {
259b64eb 448 zlog_warn("%s: not enough memory", __func__);
0684c9b1
RZ
449 return;
450 }
451
452 json_object_array_add(jo, jon);
453}
454
6f374165 455static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json)
0684c9b1
RZ
456{
457 struct json_object *jo;
1d0a11e6 458 struct bfd_vrf_tuple bvt = {0};
0684c9b1 459
6f374165 460 bvt.vrfname = vrfname;
d8729f8c 461 if (!use_json) {
6f374165 462 bvt.vty = vty;
0684c9b1 463 vty_out(vty, "BFD Peers:\n");
6f374165 464 bfd_id_iterate(_display_peer_counter_iter, &bvt);
0684c9b1
RZ
465 return;
466 }
467
468 jo = json_object_new_array();
6f374165 469 bvt.jo = jo;
1d923374 470 bfd_id_iterate(_display_peer_counter_json_iter, &bvt);
0684c9b1 471
4e37fcb6 472 vty_json(vty, jo);
0684c9b1
RZ
473}
474
2d73a326 475static void _clear_peer_counter(struct bfd_session *bs)
d6790033
S
476{
477 /* Clear only pkt stats, intention is not to loose system
478 events counters */
479 bs->stats.rx_ctrl_pkt = 0;
480 bs->stats.tx_ctrl_pkt = 0;
481 bs->stats.rx_echo_pkt = 0;
482 bs->stats.tx_echo_pkt = 0;
483}
484
fa6e709f
S
485static void _display_peer_brief(struct vty *vty, struct bfd_session *bs)
486{
487 char addr_buf[INET6_ADDRSTRLEN];
488
e9cea444 489 vty_out(vty, "%-10u", bs->discrs.my_discr);
490 inet_ntop(bs->key.family, &bs->key.local, addr_buf, sizeof(addr_buf));
491 vty_out(vty, " %-40s", addr_buf);
492 inet_ntop(bs->key.family, &bs->key.peer, addr_buf, sizeof(addr_buf));
493 vty_out(vty, " %-40s", addr_buf);
494 vty_out(vty, "%-15s\n", state_list[bs->ses_state].str);
fa6e709f
S
495}
496
7f5818fb 497static void _display_peer_brief_iter(struct hash_bucket *hb, void *arg)
fa6e709f
S
498{
499 struct bfd_vrf_tuple *bvt = arg;
500 struct vty *vty;
501 struct bfd_session *bs = hb->data;
502
503 if (!bvt)
504 return;
505 vty = bvt->vty;
506
507 if (bvt->vrfname) {
508 if (!bs->key.vrfname[0] ||
509 !strmatch(bs->key.vrfname, bvt->vrfname))
510 return;
511 }
512
513 _display_peer_brief(vty, bs);
514}
515
516static void _display_peers_brief(struct vty *vty, const char *vrfname, bool use_json)
517{
518 struct json_object *jo;
1d0a11e6 519 struct bfd_vrf_tuple bvt = {0};
fa6e709f 520
fa6e709f
S
521 bvt.vrfname = vrfname;
522
a8f58eb6 523 if (!use_json) {
fa6e709f
S
524 bvt.vty = vty;
525
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");
531
532 vty_out(vty, "%-10s", "=========");
533 vty_out(vty, " %-40s", "============");
534 vty_out(vty, " %-40s", "===========");
535 vty_out(vty, "%-15s\n", "======");
536
537 bfd_id_iterate(_display_peer_brief_iter, &bvt);
538 return;
539 }
540
541 jo = json_object_new_array();
542 bvt.jo = jo;
543
544 bfd_id_iterate(_display_peer_json_iter, &bvt);
545
4e37fcb6 546 vty_json(vty, jo);
fa6e709f
S
547}
548
89a634c1
RZ
549static struct bfd_session *
550_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
551 const char *label, const char *peer_str,
552 const char *local_str, const char *ifname,
553 const char *vrfname)
c2f29cf3
RZ
554{
555 int idx;
556 bool mhop;
557 struct bfd_session *bs = NULL;
558 struct peer_label *pl;
559 struct bfd_peer_cfg bpc;
560 struct sockaddr_any psa, lsa, *lsap;
561 char errormsg[128];
562
563 /* Look up the BFD peer. */
564 if (label) {
565 pl = pl_find(label);
566 if (pl)
567 bs = pl->pl_bs;
c3634e44 568 } else if (peer_str) {
c2f29cf3 569 strtosa(peer_str, &psa);
89a634c1 570 if (local_str) {
c2f29cf3
RZ
571 strtosa(local_str, &lsa);
572 lsap = &lsa;
573 } else
574 lsap = NULL;
575
576 idx = 0;
577 mhop = argv_find(argv, argc, "multihop", &idx);
578
579 if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname,
580 errormsg, sizeof(errormsg))
581 != 0) {
582 vty_out(vty, "%% Invalid peer configuration: %s\n",
583 errormsg);
89a634c1 584 return NULL;
c2f29cf3
RZ
585 }
586
587 bs = bs_peer_find(&bpc);
c3634e44
IR
588 } else {
589 vty_out(vty, "%% Invalid arguments\n");
590 return NULL;
c2f29cf3
RZ
591 }
592
593 /* Find peer data. */
594 if (bs == NULL) {
595 vty_out(vty, "%% Unable to find 'peer %s",
596 label ? label : peer_str);
597 if (ifname)
598 vty_out(vty, " interface %s", ifname);
89a634c1 599 if (local_str)
c2f29cf3
RZ
600 vty_out(vty, " local-address %s", local_str);
601 if (vrfname)
602 vty_out(vty, " vrf %s", vrfname);
603 vty_out(vty, "'\n");
604
89a634c1 605 return NULL;
c2f29cf3
RZ
606 }
607
89a634c1
RZ
608 return bs;
609}
610
618a06fe 611void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
612 struct bfd_session *bs)
613{
614#ifdef BFD_LINUX
615 uint8_t i;
616 uint32_t average = 0;
617
618 if (bs->rtt_valid == 0)
619 return;
620
621 *max = bs->rtt[0];
622 *min = 1000;
623 *avg = 0;
624
625 for (i = 0; i < bs->rtt_valid; i++) {
626 if (bs->rtt[i] < *min)
627 *min = bs->rtt[i];
628 if (bs->rtt[i] > *max)
629 *max = bs->rtt[i];
630 average += bs->rtt[i];
631 }
632 *avg = average / bs->rtt_valid;
633
634#endif
635}
89a634c1
RZ
636
637/*
638 * Show commands.
639 */
1e81afc3 640DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf NAME] peers [json]",
89a634c1
RZ
641 SHOW_STR
642 "Bidirection Forwarding Detection\n"
9146cc2a 643 VRF_CMD_HELP_STR
89a634c1
RZ
644 "BFD peers status\n" JSON_STR)
645{
9146cc2a
PG
646 char *vrf_name = NULL;
647 int idx_vrf = 0;
648
649 if (argv_find(argv, argc, "vrf", &idx_vrf))
650 vrf_name = argv[idx_vrf + 1]->arg;
651
652 _display_all_peers(vty, vrf_name, use_json(argc, argv));
89a634c1
RZ
653
654 return CMD_SUCCESS;
655}
656
657DEFPY(bfd_show_peer, bfd_show_peer_cmd,
1e81afc3 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}]> [json]",
89a634c1
RZ
659 SHOW_STR
660 "Bidirection Forwarding Detection\n"
533ba31f 661 VRF_CMD_HELP_STR
89a634c1
RZ
662 "BFD peers status\n"
663 "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
533ba31f 664 LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR)
89a634c1
RZ
665{
666 struct bfd_session *bs;
667
668 /* Look up the BFD peer. */
669 bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
e429a2a0 670 ifname, vrf_name);
89a634c1
RZ
671 if (bs == NULL)
672 return CMD_WARNING_CONFIG_FAILED;
673
c2f29cf3
RZ
674 if (use_json(argc, argv)) {
675 _display_peer_json(vty, bs);
676 } else {
677 vty_out(vty, "BFD Peer:\n");
678 _display_peer(vty, bs);
679 }
680
681 return CMD_SUCCESS;
682}
683
0684c9b1 684DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
1e81afc3 685 "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]",
0684c9b1
RZ
686 SHOW_STR
687 "Bidirection Forwarding Detection\n"
533ba31f 688 VRF_CMD_HELP_STR
0684c9b1
RZ
689 "BFD peers status\n"
690 "Peer label\n"
691 PEER_IPV4_STR
692 PEER_IPV6_STR
693 MHOP_STR
694 LOCAL_STR
695 LOCAL_IPV4_STR
696 LOCAL_IPV6_STR
697 INTERFACE_STR
698 LOCAL_INTF_STR
0684c9b1
RZ
699 "Show BFD peer counters information\n"
700 JSON_STR)
701{
702 struct bfd_session *bs;
703
704 /* Look up the BFD peer. */
705 bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
e429a2a0 706 ifname, vrf_name);
0684c9b1
RZ
707 if (bs == NULL)
708 return CMD_WARNING_CONFIG_FAILED;
709
710 if (use_json(argc, argv))
711 _display_peer_counters_json(vty, bs);
712 else
713 _display_peer_counter(vty, bs);
714
715 return CMD_SUCCESS;
716}
717
718DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
1e81afc3 719 "show bfd [vrf NAME] peers counters [json]",
0684c9b1
RZ
720 SHOW_STR
721 "Bidirection Forwarding Detection\n"
6f374165 722 VRF_CMD_HELP_STR
0684c9b1
RZ
723 "BFD peers status\n"
724 "Show BFD peer counters information\n"
725 JSON_STR)
726{
6f374165
PG
727 char *vrf_name = NULL;
728 int idx_vrf = 0;
729
730 if (argv_find(argv, argc, "vrf", &idx_vrf))
731 vrf_name = argv[idx_vrf + 1]->arg;
732
733 _display_peers_counter(vty, vrf_name, use_json(argc, argv));
0684c9b1
RZ
734
735 return CMD_SUCCESS;
736}
737
d6790033
S
738DEFPY(bfd_clear_peer_counters, bfd_clear_peer_counters_cmd,
739 "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",
740 SHOW_STR
741 "Bidirection Forwarding Detection\n"
742 VRF_CMD_HELP_STR
743 "BFD peers status\n"
744 "Peer label\n"
745 PEER_IPV4_STR
746 PEER_IPV6_STR
747 MHOP_STR
748 LOCAL_STR
749 LOCAL_IPV4_STR
750 LOCAL_IPV6_STR
751 INTERFACE_STR
752 LOCAL_INTF_STR
753 "clear BFD peer counters information\n")
754{
755 struct bfd_session *bs;
756
757 /* Look up the BFD peer. */
758 bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
759 ifname, vrfname);
760 if (bs == NULL)
761 return CMD_WARNING_CONFIG_FAILED;
2d73a326 762
d6790033
S
763 _clear_peer_counter(bs);
764
765 return CMD_SUCCESS;
766}
c2f29cf3 767
fa6e709f
S
768DEFPY(bfd_show_peers_brief, bfd_show_peers_brief_cmd,
769 "show bfd [vrf <NAME$vrfname>] peers brief [json]",
770 SHOW_STR
771 "Bidirection Forwarding Detection\n"
772 VRF_CMD_HELP_STR
773 "BFD peers status\n"
774 "Show BFD peer information in tabular form\n"
775 JSON_STR)
776{
1d0a11e6
S
777 char *vrf_name = NULL;
778 int idx_vrf = 0;
779
780 if (argv_find(argv, argc, "vrf", &idx_vrf))
781 vrf_name = argv[idx_vrf + 1]->arg;
782
783 _display_peers_brief(vty, vrf_name, use_json(argc, argv));
fa6e709f
S
784
785 return CMD_SUCCESS;
786}
787
400632a9
RZ
788DEFPY(show_bfd_distributed, show_bfd_distributed_cmd,
789 "show bfd distributed",
790 SHOW_STR
791 "Bidirection Forwarding Detection\n"
792 "Show BFD data plane (distributed BFD) statistics\n")
793{
794 bfd_dplane_show_counters(vty);
795 return CMD_SUCCESS;
796}
797
8ba709dd
RZ
798DEFPY(
799 bfd_debug_distributed, bfd_debug_distributed_cmd,
800 "[no] debug bfd distributed",
801 NO_STR
802 DEBUG_STR
803 "Bidirection Forwarding Detection\n"
804 "BFD data plane (distributed BFD) debugging\n")
805{
806 bglobal.debug_dplane = !no;
807 return CMD_SUCCESS;
808}
809
48da2c31
RZ
810DEFPY(
811 bfd_debug_peer, bfd_debug_peer_cmd,
812 "[no] debug bfd peer",
813 NO_STR
814 DEBUG_STR
815 "Bidirection Forwarding Detection\n"
816 "Peer events debugging\n")
817{
818 bglobal.debug_peer_event = !no;
819 return CMD_SUCCESS;
820}
821
822DEFPY(
823 bfd_debug_zebra, bfd_debug_zebra_cmd,
824 "[no] debug bfd zebra",
825 NO_STR
826 DEBUG_STR
827 "Bidirection Forwarding Detection\n"
828 "Zebra events debugging\n")
829{
830 bglobal.debug_zebra = !no;
831 return CMD_SUCCESS;
832}
833
834DEFPY(
835 bfd_debug_network, bfd_debug_network_cmd,
836 "[no] debug bfd network",
837 NO_STR
838 DEBUG_STR
839 "Bidirection Forwarding Detection\n"
840 "Network layer debugging\n")
841{
842 bglobal.debug_network = !no;
843 return CMD_SUCCESS;
844}
845
c2f29cf3
RZ
846/*
847 * Function definitions.
848 */
849
850/*
851 * Configuration rules:
852 *
853 * Single hop:
8a9f760e 854 * peer + (interface name)
c2f29cf3
RZ
855 *
856 * Multi hop:
857 * peer + local + (optional vrf)
858 *
859 * Anything else is misconfiguration.
860 */
861static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
862 const struct sockaddr_any *peer,
863 const struct sockaddr_any *local,
864 const char *ifname, const char *vrfname,
865 char *ebuf, size_t ebuflen)
866{
867 memset(bpc, 0, sizeof(*bpc));
868
869 /* Defaults */
59dad813 870 bpc->bpc_shutdown = false;
c2f29cf3
RZ
871 bpc->bpc_detectmultiplier = BPC_DEF_DETECTMULTIPLIER;
872 bpc->bpc_recvinterval = BPC_DEF_RECEIVEINTERVAL;
873 bpc->bpc_txinterval = BPC_DEF_TRANSMITINTERVAL;
4df3e31c
IR
874 bpc->bpc_echorecvinterval = BPC_DEF_ECHORECEIVEINTERVAL;
875 bpc->bpc_echotxinterval = BPC_DEF_ECHOTRANSMITINTERVAL;
c2f29cf3
RZ
876 bpc->bpc_lastevent = monotime(NULL);
877
878 /* Safety check: when no error buf is provided len must be zero. */
879 if (ebuf == NULL)
880 ebuflen = 0;
881
882 /* Peer is always mandatory. */
883 if (peer == NULL) {
884 snprintf(ebuf, ebuflen, "peer must not be empty");
885 return -1;
886 }
887
888 /* Validate address families. */
889 if (peer->sa_sin.sin_family == AF_INET) {
890 if (local && local->sa_sin.sin_family != AF_INET) {
891 snprintf(ebuf, ebuflen,
892 "local is IPv6, but peer is IPv4");
893 return -1;
894 }
895
896 bpc->bpc_ipv4 = true;
897 } else if (peer->sa_sin.sin_family == AF_INET6) {
898 if (local && local->sa_sin.sin_family != AF_INET6) {
899 snprintf(ebuf, ebuflen,
900 "local is IPv4, but peer is IPv6");
901 return -1;
902 }
903
904 bpc->bpc_ipv4 = false;
905 } else {
906 snprintf(ebuf, ebuflen, "invalid peer address family");
907 return -1;
908 }
909
910 /* Copy local and/or peer addresses. */
911 if (local)
912 bpc->bpc_local = *local;
913
4848ef74 914 bpc->bpc_peer = *peer;
c2f29cf3
RZ
915 bpc->bpc_mhop = mhop;
916
c2f29cf3
RZ
917 /* Handle interface specification configuration. */
918 if (ifname) {
c2f29cf3
RZ
919 bpc->bpc_has_localif = true;
920 if (strlcpy(bpc->bpc_localif, ifname, sizeof(bpc->bpc_localif))
921 > sizeof(bpc->bpc_localif)) {
922 snprintf(ebuf, ebuflen, "interface name too long");
923 return -1;
924 }
925 }
926
927 /* Handle VRF configuration. */
928 if (vrfname) {
929 bpc->bpc_has_vrfname = true;
930 if (strlcpy(bpc->bpc_vrfname, vrfname, sizeof(bpc->bpc_vrfname))
931 > sizeof(bpc->bpc_vrfname)) {
932 snprintf(ebuf, ebuflen, "vrf name too long");
933 return -1;
934 }
e0f36c91
PG
935 } else {
936 bpc->bpc_has_vrfname = true;
937 strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
c2f29cf3
RZ
938 }
939
940 return 0;
941}
c2f29cf3 942
a244e599
DS
943DEFUN_NOSH(show_debugging_bfd,
944 show_debugging_bfd_cmd,
945 "show debugging [bfd]",
946 SHOW_STR
947 DEBUG_STR
948 "BFD daemon\n")
949{
950 vty_out(vty, "BFD debugging status:\n");
8ba709dd
RZ
951 if (bglobal.debug_dplane)
952 vty_out(vty, " Distributed BFD debugging is on.\n");
9be4b18a
PG
953 if (bglobal.debug_peer_event)
954 vty_out(vty, " Peer events debugging is on.\n");
955 if (bglobal.debug_zebra)
956 vty_out(vty, " Zebra events debugging is on.\n");
957 if (bglobal.debug_network)
958 vty_out(vty, " Network layer debugging is on.\n");
a244e599 959
cf00164b
DS
960 cmd_show_lib_debugs(vty);
961
a244e599
DS
962 return CMD_SUCCESS;
963}
964
612c2c15 965static int bfdd_write_config(struct vty *vty);
c2f29cf3 966struct cmd_node bfd_node = {
f4b8291f 967 .name = "bfd",
62b346ee 968 .node = BFD_NODE,
24389580 969 .parent_node = CONFIG_NODE,
62b346ee 970 .prompt = "%s(config-bfd)# ",
612c2c15 971 .config_write = bfdd_write_config,
c2f29cf3
RZ
972};
973
974struct cmd_node bfd_peer_node = {
f4b8291f 975 .name = "bfd peer",
62b346ee 976 .node = BFD_PEER_NODE,
24389580 977 .parent_node = BFD_NODE,
62b346ee 978 .prompt = "%s(config-bfd-peer)# ",
c2f29cf3
RZ
979};
980
0287a64a
RZ
981static int bfdd_write_config(struct vty *vty)
982{
983 struct lyd_node *dnode;
984 int written = 0;
985
8ba709dd
RZ
986 if (bglobal.debug_dplane) {
987 vty_out(vty, "debug bfd distributed\n");
988 written = 1;
989 }
990
48da2c31
RZ
991 if (bglobal.debug_peer_event) {
992 vty_out(vty, "debug bfd peer\n");
993 written = 1;
994 }
995
996 if (bglobal.debug_zebra) {
997 vty_out(vty, "debug bfd zebra\n");
998 written = 1;
999 }
1000
1001 if (bglobal.debug_network) {
1002 vty_out(vty, "debug bfd network\n");
1003 written = 1;
1004 }
1005
0287a64a
RZ
1006 dnode = yang_dnode_get(running_config->dnode, "/frr-bfdd:bfdd");
1007 if (dnode) {
1008 nb_cli_show_dnode_cmds(vty, dnode, false);
1009 written = 1;
1010 }
1011
1012 return written;
1013}
1014
c2f29cf3
RZ
1015void bfdd_vty_init(void)
1016{
0684c9b1
RZ
1017 install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd);
1018 install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd);
d6790033 1019 install_element(ENABLE_NODE, &bfd_clear_peer_counters_cmd);
c2f29cf3
RZ
1020 install_element(ENABLE_NODE, &bfd_show_peers_cmd);
1021 install_element(ENABLE_NODE, &bfd_show_peer_cmd);
fa6e709f 1022 install_element(ENABLE_NODE, &bfd_show_peers_brief_cmd);
400632a9 1023 install_element(ENABLE_NODE, &show_bfd_distributed_cmd);
a244e599 1024 install_element(ENABLE_NODE, &show_debugging_bfd_cmd);
c2f29cf3 1025
8ba709dd 1026 install_element(ENABLE_NODE, &bfd_debug_distributed_cmd);
48da2c31
RZ
1027 install_element(ENABLE_NODE, &bfd_debug_peer_cmd);
1028 install_element(ENABLE_NODE, &bfd_debug_zebra_cmd);
1029 install_element(ENABLE_NODE, &bfd_debug_network_cmd);
1030
8ba709dd 1031 install_element(CONFIG_NODE, &bfd_debug_distributed_cmd);
48da2c31
RZ
1032 install_element(CONFIG_NODE, &bfd_debug_peer_cmd);
1033 install_element(CONFIG_NODE, &bfd_debug_zebra_cmd);
1034 install_element(CONFIG_NODE, &bfd_debug_network_cmd);
1035
c2f29cf3 1036 /* Install BFD node and commands. */
612c2c15 1037 install_node(&bfd_node);
c2f29cf3 1038 install_default(BFD_NODE);
c2f29cf3
RZ
1039
1040 /* Install BFD peer node. */
612c2c15 1041 install_node(&bfd_peer_node);
c2f29cf3 1042 install_default(BFD_PEER_NODE);
adc26455
RZ
1043
1044 bfdd_cli_init();
c2f29cf3 1045}