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