]> git.proxmox.com Git - mirror_frr.git/blame - bfdd/bfdd_vty.c
Merge pull request #5450 from donaldsharp/rpki_node_issues
[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
87 if (BFD_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);
114
115 vty_out(vty, "\t\tStatus: ");
116 switch (bs->ses_state) {
117 case PTM_BFD_ADM_DOWN:
118 vty_out(vty, "shutdown\n");
119 break;
120 case PTM_BFD_DOWN:
121 vty_out(vty, "down\n");
122
123 now = monotime(NULL);
98ef9c16 124 integer2timestr(now - bs->downtime.tv_sec, buf, sizeof(buf));
c2f29cf3
RZ
125 vty_out(vty, "\t\tDowntime: %s\n", buf);
126 break;
127 case PTM_BFD_INIT:
128 vty_out(vty, "init\n");
129 break;
130 case PTM_BFD_UP:
131 vty_out(vty, "up\n");
132
133 now = monotime(NULL);
134 integer2timestr(now - bs->uptime.tv_sec, buf, sizeof(buf));
135 vty_out(vty, "\t\tUptime: %s\n", buf);
136 break;
137
138 default:
139 vty_out(vty, "unknown\n");
140 break;
141 }
142
143 vty_out(vty, "\t\tDiagnostics: %s\n", diag2str(bs->local_diag));
144 vty_out(vty, "\t\tRemote diagnostics: %s\n", diag2str(bs->remote_diag));
145
146 vty_out(vty, "\t\tLocal timers:\n");
147 vty_out(vty, "\t\t\tReceive interval: %" PRIu32 "ms\n",
148 bs->timers.required_min_rx / 1000);
f43b9368 149 vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms\n",
c2f29cf3 150 bs->timers.desired_min_tx / 1000);
f43b9368
RZ
151 vty_out(vty, "\t\t\tEcho transmission interval: %" PRIu32 "ms\n",
152 bs->timers.required_min_echo / 1000);
c2f29cf3
RZ
153
154 vty_out(vty, "\t\tRemote timers:\n");
155 vty_out(vty, "\t\t\tReceive interval: %" PRIu32 "ms\n",
156 bs->remote_timers.required_min_rx / 1000);
157 vty_out(vty, "\t\t\tTransmission interval: %" PRIu32 "ms\n",
158 bs->remote_timers.desired_min_tx / 1000);
159 vty_out(vty, "\t\t\tEcho transmission interval: %" PRIu32 "ms\n",
160 bs->remote_timers.required_min_echo / 1000);
161
162 vty_out(vty, "\n");
163}
164
89a634c1 165static struct json_object *_peer_json_header(struct bfd_session *bs)
c2f29cf3
RZ
166{
167 struct json_object *jo = json_object_new_object();
79b4a6fc 168 char addr_buf[INET6_ADDRSTRLEN];
c2f29cf3 169
79b4a6fc 170 if (bs->key.mhop)
c2f29cf3 171 json_object_boolean_true_add(jo, "multihop");
79b4a6fc 172 else
c2f29cf3 173 json_object_boolean_false_add(jo, "multihop");
79b4a6fc
RZ
174
175 json_object_string_add(jo, "peer",
176 inet_ntop(bs->key.family, &bs->key.peer,
177 addr_buf, sizeof(addr_buf)));
178 if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
179 json_object_string_add(jo, "local",
180 inet_ntop(bs->key.family, &bs->key.local,
181 addr_buf, sizeof(addr_buf)));
182
183 if (bs->key.vrfname[0])
184 json_object_string_add(jo, "vrf", bs->key.vrfname);
185 if (bs->key.ifname[0])
186 json_object_string_add(jo, "interface", bs->key.ifname);
c2f29cf3
RZ
187
188 if (bs->pl)
189 json_object_string_add(jo, "label", bs->pl->pl_label);
190
89a634c1
RZ
191 return jo;
192}
193
194static struct json_object *__display_peer_json(struct bfd_session *bs)
195{
196 struct json_object *jo = _peer_json_header(bs);
197
c2f29cf3
RZ
198 json_object_int_add(jo, "id", bs->discrs.my_discr);
199 json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
200
201 switch (bs->ses_state) {
202 case PTM_BFD_ADM_DOWN:
203 json_object_string_add(jo, "status", "shutdown");
204 break;
205 case PTM_BFD_DOWN:
206 json_object_string_add(jo, "status", "down");
207 json_object_int_add(jo, "downtime",
98ef9c16 208 monotime(NULL) - bs->downtime.tv_sec);
c2f29cf3
RZ
209 break;
210 case PTM_BFD_INIT:
211 json_object_string_add(jo, "status", "init");
212 break;
213 case PTM_BFD_UP:
214 json_object_string_add(jo, "status", "up");
215 json_object_int_add(jo, "uptime",
216 monotime(NULL) - bs->uptime.tv_sec);
217 break;
218
219 default:
220 json_object_string_add(jo, "status", "unknown");
221 break;
222 }
223
224 json_object_string_add(jo, "diagnostic", diag2str(bs->local_diag));
225 json_object_string_add(jo, "remote-diagnostic",
226 diag2str(bs->remote_diag));
227
228 json_object_int_add(jo, "receive-interval",
229 bs->timers.required_min_rx / 1000);
230 json_object_int_add(jo, "transmit-interval",
231 bs->timers.desired_min_tx / 1000);
232 if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO))
233 json_object_int_add(jo, "echo-interval",
234 bs->timers.required_min_echo / 1000);
235 else
236 json_object_int_add(jo, "echo-interval", 0);
237
238 json_object_int_add(jo, "remote-receive-interval",
239 bs->remote_timers.required_min_rx / 1000);
240 json_object_int_add(jo, "remote-transmit-interval",
241 bs->remote_timers.desired_min_tx / 1000);
242 json_object_int_add(jo, "remote-echo-interval",
243 bs->remote_timers.required_min_echo / 1000);
244
245 return jo;
246}
247
248static void _display_peer_json(struct vty *vty, struct bfd_session *bs)
249{
250 struct json_object *jo = __display_peer_json(bs);
251
252 vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
253 json_object_free(jo);
254}
255
9146cc2a
PG
256struct bfd_vrf_tuple {
257 char *vrfname;
258 struct vty *vty;
259 struct json_object *jo;
260};
261
e3b78da8 262static void _display_peer_iter(struct hash_bucket *hb, void *arg)
c2f29cf3 263{
9146cc2a
PG
264 struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
265 struct vty *vty;
c2f29cf3
RZ
266 struct bfd_session *bs = hb->data;
267
9146cc2a
PG
268 if (!bvt)
269 return;
270 vty = bvt->vty;
271
272 if (bvt->vrfname) {
273 if (!bs->key.vrfname[0] ||
274 !strmatch(bs->key.vrfname, bvt->vrfname))
275 return;
276 }
c2f29cf3
RZ
277 _display_peer(vty, bs);
278}
279
e3b78da8 280static void _display_peer_json_iter(struct hash_bucket *hb, void *arg)
c2f29cf3 281{
9146cc2a
PG
282 struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
283 struct json_object *jo, *jon = NULL;
c2f29cf3
RZ
284 struct bfd_session *bs = hb->data;
285
9146cc2a
PG
286 if (!bvt)
287 return;
288 jo = bvt->jo;
289
290 if (bvt->vrfname) {
291 if (!bs->key.vrfname[0] ||
292 !strmatch(bs->key.vrfname, bvt->vrfname))
293 return;
294 }
295
c2f29cf3
RZ
296 jon = __display_peer_json(bs);
297 if (jon == NULL) {
298 log_warning("%s: not enough memory", __func__);
299 return;
300 }
301
302 json_object_array_add(jo, jon);
303}
304
9146cc2a 305static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json)
c2f29cf3
RZ
306{
307 struct json_object *jo;
9146cc2a
PG
308 struct bfd_vrf_tuple bvt;
309
310 memset(&bvt, 0, sizeof(bvt));
311 bvt.vrfname = vrfname;
c2f29cf3 312
d8729f8c 313 if (!use_json) {
9146cc2a 314 bvt.vty = vty;
89a634c1 315 vty_out(vty, "BFD Peers:\n");
9146cc2a 316 bfd_id_iterate(_display_peer_iter, &bvt);
c2f29cf3
RZ
317 return;
318 }
319
320 jo = json_object_new_array();
9146cc2a
PG
321 bvt.jo = jo;
322 bfd_id_iterate(_display_peer_json_iter, &bvt);
c2f29cf3
RZ
323
324 vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
325 json_object_free(jo);
326}
327
0684c9b1
RZ
328static void _display_peer_counter(struct vty *vty, struct bfd_session *bs)
329{
330 _display_peer_header(vty, bs);
331
332 vty_out(vty, "\t\tControl packet input: %" PRIu64 " packets\n",
333 bs->stats.rx_ctrl_pkt);
334 vty_out(vty, "\t\tControl packet output: %" PRIu64 " packets\n",
335 bs->stats.tx_ctrl_pkt);
336 vty_out(vty, "\t\tEcho packet input: %" PRIu64 " packets\n",
337 bs->stats.rx_echo_pkt);
338 vty_out(vty, "\t\tEcho packet output: %" PRIu64 " packets\n",
339 bs->stats.tx_echo_pkt);
340 vty_out(vty, "\t\tSession up events: %" PRIu64 "\n",
341 bs->stats.session_up);
342 vty_out(vty, "\t\tSession down events: %" PRIu64 "\n",
343 bs->stats.session_down);
344 vty_out(vty, "\t\tZebra notifications: %" PRIu64 "\n",
345 bs->stats.znotification);
346 vty_out(vty, "\n");
347}
348
349static struct json_object *__display_peer_counters_json(struct bfd_session *bs)
350{
351 struct json_object *jo = _peer_json_header(bs);
352
353 json_object_int_add(jo, "control-packet-input", bs->stats.rx_ctrl_pkt);
354 json_object_int_add(jo, "control-packet-output", bs->stats.tx_ctrl_pkt);
355 json_object_int_add(jo, "echo-packet-input", bs->stats.rx_echo_pkt);
356 json_object_int_add(jo, "echo-packet-output", bs->stats.tx_echo_pkt);
357 json_object_int_add(jo, "session-up", bs->stats.session_up);
358 json_object_int_add(jo, "session-down", bs->stats.session_down);
359 json_object_int_add(jo, "zebra-notifications", bs->stats.znotification);
360
361 return jo;
362}
363
364static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
365{
366 struct json_object *jo = __display_peer_counters_json(bs);
367
368 vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
369 json_object_free(jo);
370}
371
e3b78da8 372static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg)
0684c9b1 373{
6f374165
PG
374 struct bfd_vrf_tuple *bvt = arg;
375 struct vty *vty;
0684c9b1
RZ
376 struct bfd_session *bs = hb->data;
377
6f374165
PG
378 if (!bvt)
379 return;
380 vty = bvt->vty;
381
382 if (bvt->vrfname) {
383 if (!bs->key.vrfname[0] ||
384 !strmatch(bs->key.vrfname, bvt->vrfname))
385 return;
386 }
387
0684c9b1
RZ
388 _display_peer_counter(vty, bs);
389}
390
e3b78da8 391static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg)
0684c9b1 392{
6f374165 393 struct json_object *jo, *jon = NULL;
0684c9b1 394 struct bfd_session *bs = hb->data;
6f374165
PG
395 struct bfd_vrf_tuple *bvt = arg;
396
397 if (!bvt)
398 return;
399 jo = bvt->jo;
400
401 if (bvt->vrfname) {
402 if (!bs->key.vrfname[0] ||
403 !strmatch(bs->key.vrfname, bvt->vrfname))
404 return;
405 }
0684c9b1
RZ
406
407 jon = __display_peer_counters_json(bs);
408 if (jon == NULL) {
409 log_warning("%s: not enough memory", __func__);
410 return;
411 }
412
413 json_object_array_add(jo, jon);
414}
415
6f374165 416static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json)
0684c9b1
RZ
417{
418 struct json_object *jo;
6f374165 419 struct bfd_vrf_tuple bvt;
0684c9b1 420
6f374165
PG
421 memset(&bvt, 0, sizeof(struct bfd_vrf_tuple));
422 bvt.vrfname = vrfname;
d8729f8c 423 if (!use_json) {
6f374165 424 bvt.vty = vty;
0684c9b1 425 vty_out(vty, "BFD Peers:\n");
6f374165 426 bfd_id_iterate(_display_peer_counter_iter, &bvt);
0684c9b1
RZ
427 return;
428 }
429
430 jo = json_object_new_array();
6f374165 431 bvt.jo = jo;
0684c9b1
RZ
432 bfd_id_iterate(_display_peer_counter_json_iter, jo);
433
434 vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
435 json_object_free(jo);
436}
437
89a634c1
RZ
438static struct bfd_session *
439_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
440 const char *label, const char *peer_str,
441 const char *local_str, const char *ifname,
442 const char *vrfname)
c2f29cf3
RZ
443{
444 int idx;
445 bool mhop;
446 struct bfd_session *bs = NULL;
447 struct peer_label *pl;
448 struct bfd_peer_cfg bpc;
449 struct sockaddr_any psa, lsa, *lsap;
450 char errormsg[128];
451
452 /* Look up the BFD peer. */
453 if (label) {
454 pl = pl_find(label);
455 if (pl)
456 bs = pl->pl_bs;
457 } else {
458 strtosa(peer_str, &psa);
89a634c1 459 if (local_str) {
c2f29cf3
RZ
460 strtosa(local_str, &lsa);
461 lsap = &lsa;
462 } else
463 lsap = NULL;
464
465 idx = 0;
466 mhop = argv_find(argv, argc, "multihop", &idx);
467
468 if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname,
469 errormsg, sizeof(errormsg))
470 != 0) {
471 vty_out(vty, "%% Invalid peer configuration: %s\n",
472 errormsg);
89a634c1 473 return NULL;
c2f29cf3
RZ
474 }
475
476 bs = bs_peer_find(&bpc);
477 }
478
479 /* Find peer data. */
480 if (bs == NULL) {
481 vty_out(vty, "%% Unable to find 'peer %s",
482 label ? label : peer_str);
483 if (ifname)
484 vty_out(vty, " interface %s", ifname);
89a634c1 485 if (local_str)
c2f29cf3
RZ
486 vty_out(vty, " local-address %s", local_str);
487 if (vrfname)
488 vty_out(vty, " vrf %s", vrfname);
489 vty_out(vty, "'\n");
490
89a634c1 491 return NULL;
c2f29cf3
RZ
492 }
493
89a634c1
RZ
494 return bs;
495}
496
497
498/*
499 * Show commands.
500 */
1e81afc3 501DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf NAME] peers [json]",
89a634c1
RZ
502 SHOW_STR
503 "Bidirection Forwarding Detection\n"
9146cc2a 504 VRF_CMD_HELP_STR
89a634c1
RZ
505 "BFD peers status\n" JSON_STR)
506{
9146cc2a
PG
507 char *vrf_name = NULL;
508 int idx_vrf = 0;
509
510 if (argv_find(argv, argc, "vrf", &idx_vrf))
511 vrf_name = argv[idx_vrf + 1]->arg;
512
513 _display_all_peers(vty, vrf_name, use_json(argc, argv));
89a634c1
RZ
514
515 return CMD_SUCCESS;
516}
517
518DEFPY(bfd_show_peer, bfd_show_peer_cmd,
1e81afc3 519 "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
520 SHOW_STR
521 "Bidirection Forwarding Detection\n"
533ba31f 522 VRF_CMD_HELP_STR
89a634c1
RZ
523 "BFD peers status\n"
524 "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
533ba31f 525 LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR)
89a634c1
RZ
526{
527 struct bfd_session *bs;
528
529 /* Look up the BFD peer. */
530 bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
e429a2a0 531 ifname, vrf_name);
89a634c1
RZ
532 if (bs == NULL)
533 return CMD_WARNING_CONFIG_FAILED;
534
c2f29cf3
RZ
535 if (use_json(argc, argv)) {
536 _display_peer_json(vty, bs);
537 } else {
538 vty_out(vty, "BFD Peer:\n");
539 _display_peer(vty, bs);
540 }
541
542 return CMD_SUCCESS;
543}
544
0684c9b1 545DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
1e81afc3 546 "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
547 SHOW_STR
548 "Bidirection Forwarding Detection\n"
533ba31f 549 VRF_CMD_HELP_STR
0684c9b1
RZ
550 "BFD peers status\n"
551 "Peer label\n"
552 PEER_IPV4_STR
553 PEER_IPV6_STR
554 MHOP_STR
555 LOCAL_STR
556 LOCAL_IPV4_STR
557 LOCAL_IPV6_STR
558 INTERFACE_STR
559 LOCAL_INTF_STR
0684c9b1
RZ
560 "Show BFD peer counters information\n"
561 JSON_STR)
562{
563 struct bfd_session *bs;
564
565 /* Look up the BFD peer. */
566 bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
e429a2a0 567 ifname, vrf_name);
0684c9b1
RZ
568 if (bs == NULL)
569 return CMD_WARNING_CONFIG_FAILED;
570
571 if (use_json(argc, argv))
572 _display_peer_counters_json(vty, bs);
573 else
574 _display_peer_counter(vty, bs);
575
576 return CMD_SUCCESS;
577}
578
579DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
1e81afc3 580 "show bfd [vrf NAME] peers counters [json]",
0684c9b1
RZ
581 SHOW_STR
582 "Bidirection Forwarding Detection\n"
6f374165 583 VRF_CMD_HELP_STR
0684c9b1
RZ
584 "BFD peers status\n"
585 "Show BFD peer counters information\n"
586 JSON_STR)
587{
6f374165
PG
588 char *vrf_name = NULL;
589 int idx_vrf = 0;
590
591 if (argv_find(argv, argc, "vrf", &idx_vrf))
592 vrf_name = argv[idx_vrf + 1]->arg;
593
594 _display_peers_counter(vty, vrf_name, use_json(argc, argv));
0684c9b1
RZ
595
596 return CMD_SUCCESS;
597}
598
c2f29cf3
RZ
599
600/*
601 * Function definitions.
602 */
603
604/*
605 * Configuration rules:
606 *
607 * Single hop:
8a9f760e 608 * peer + (interface name)
c2f29cf3
RZ
609 *
610 * Multi hop:
611 * peer + local + (optional vrf)
612 *
613 * Anything else is misconfiguration.
614 */
615static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
616 const struct sockaddr_any *peer,
617 const struct sockaddr_any *local,
618 const char *ifname, const char *vrfname,
619 char *ebuf, size_t ebuflen)
620{
621 memset(bpc, 0, sizeof(*bpc));
622
623 /* Defaults */
624 bpc->bpc_shutdown = true;
625 bpc->bpc_detectmultiplier = BPC_DEF_DETECTMULTIPLIER;
626 bpc->bpc_recvinterval = BPC_DEF_RECEIVEINTERVAL;
627 bpc->bpc_txinterval = BPC_DEF_TRANSMITINTERVAL;
628 bpc->bpc_echointerval = BPC_DEF_ECHOINTERVAL;
629 bpc->bpc_lastevent = monotime(NULL);
630
631 /* Safety check: when no error buf is provided len must be zero. */
632 if (ebuf == NULL)
633 ebuflen = 0;
634
635 /* Peer is always mandatory. */
636 if (peer == NULL) {
637 snprintf(ebuf, ebuflen, "peer must not be empty");
638 return -1;
639 }
640
641 /* Validate address families. */
642 if (peer->sa_sin.sin_family == AF_INET) {
643 if (local && local->sa_sin.sin_family != AF_INET) {
644 snprintf(ebuf, ebuflen,
645 "local is IPv6, but peer is IPv4");
646 return -1;
647 }
648
649 bpc->bpc_ipv4 = true;
650 } else if (peer->sa_sin.sin_family == AF_INET6) {
651 if (local && local->sa_sin.sin_family != AF_INET6) {
652 snprintf(ebuf, ebuflen,
653 "local is IPv4, but peer is IPv6");
654 return -1;
655 }
656
657 bpc->bpc_ipv4 = false;
658 } else {
659 snprintf(ebuf, ebuflen, "invalid peer address family");
660 return -1;
661 }
662
663 /* Copy local and/or peer addresses. */
664 if (local)
665 bpc->bpc_local = *local;
666
4848ef74 667 bpc->bpc_peer = *peer;
c2f29cf3
RZ
668 bpc->bpc_mhop = mhop;
669
c2f29cf3
RZ
670 /* Handle interface specification configuration. */
671 if (ifname) {
c2f29cf3
RZ
672 bpc->bpc_has_localif = true;
673 if (strlcpy(bpc->bpc_localif, ifname, sizeof(bpc->bpc_localif))
674 > sizeof(bpc->bpc_localif)) {
675 snprintf(ebuf, ebuflen, "interface name too long");
676 return -1;
677 }
678 }
679
680 /* Handle VRF configuration. */
681 if (vrfname) {
682 bpc->bpc_has_vrfname = true;
683 if (strlcpy(bpc->bpc_vrfname, vrfname, sizeof(bpc->bpc_vrfname))
684 > sizeof(bpc->bpc_vrfname)) {
685 snprintf(ebuf, ebuflen, "vrf name too long");
686 return -1;
687 }
e0f36c91
PG
688 } else {
689 bpc->bpc_has_vrfname = true;
690 strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
c2f29cf3
RZ
691 }
692
693 return 0;
694}
c2f29cf3 695
a244e599
DS
696DEFUN_NOSH(show_debugging_bfd,
697 show_debugging_bfd_cmd,
698 "show debugging [bfd]",
699 SHOW_STR
700 DEBUG_STR
701 "BFD daemon\n")
702{
703 vty_out(vty, "BFD debugging status:\n");
704
705 return CMD_SUCCESS;
706}
707
c2f29cf3
RZ
708struct cmd_node bfd_node = {
709 BFD_NODE,
710 "%s(config-bfd)# ",
711 1,
712};
713
714struct cmd_node bfd_peer_node = {
715 BFD_PEER_NODE,
716 "%s(config-bfd-peer)# ",
717 1,
718};
719
0287a64a
RZ
720static int bfdd_write_config(struct vty *vty)
721{
722 struct lyd_node *dnode;
723 int written = 0;
724
725 dnode = yang_dnode_get(running_config->dnode, "/frr-bfdd:bfdd");
726 if (dnode) {
727 nb_cli_show_dnode_cmds(vty, dnode, false);
728 written = 1;
729 }
730
731 return written;
732}
733
c2f29cf3
RZ
734void bfdd_vty_init(void)
735{
0684c9b1
RZ
736 install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd);
737 install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd);
c2f29cf3
RZ
738 install_element(ENABLE_NODE, &bfd_show_peers_cmd);
739 install_element(ENABLE_NODE, &bfd_show_peer_cmd);
a244e599 740 install_element(ENABLE_NODE, &show_debugging_bfd_cmd);
c2f29cf3
RZ
741
742 /* Install BFD node and commands. */
743 install_node(&bfd_node, bfdd_write_config);
744 install_default(BFD_NODE);
c2f29cf3
RZ
745
746 /* Install BFD peer node. */
0287a64a 747 install_node(&bfd_peer_node, NULL);
c2f29cf3 748 install_default(BFD_PEER_NODE);
adc26455
RZ
749
750 bfdd_cli_init();
c2f29cf3 751}