2 * BFD daemon CLI implementation.
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "lib/command.h"
27 #include "lib/northbound_cli.h"
29 #ifndef VTYSH_EXTRACT_PL
30 #include "bfdd/bfdd_cli_clippy.c"
31 #endif /* VTYSH_EXTRACT_PL */
39 #define PEER_STR "Configure peer\n"
40 #define INTERFACE_NAME_STR "Configure interface name to use\n"
41 #define PEER_IPV4_STR "IPv4 peer address\n"
42 #define PEER_IPV6_STR "IPv6 peer address\n"
43 #define MHOP_STR "Configure multihop\n"
44 #define LOCAL_STR "Configure local address\n"
45 #define LOCAL_IPV4_STR "IPv4 local address\n"
46 #define LOCAL_IPV6_STR "IPv6 local address\n"
47 #define LOCAL_INTF_STR "Configure local interface name to use\n"
48 #define VRF_STR "Configure VRF\n"
49 #define VRF_NAME_STR "Configure VRF name\n"
55 bfd_cli_is_single_hop(struct vty
*vty
)
57 return strstr(VTY_CURR_XPATH
, "/single-hop") != NULL
;
64 bfd_enter
, bfd_enter_cmd
,
66 "Configure BFD peers\n")
70 nb_cli_enqueue_change(vty
, "/frr-bfdd:bfdd/bfd", NB_OP_CREATE
, NULL
);
71 ret
= nb_cli_apply_changes(vty
, NULL
);
72 if (ret
== CMD_SUCCESS
)
73 VTY_PUSH_XPATH(BFD_NODE
, "/frr-bfdd:bfdd/bfd");
79 bfd_config_reset
, bfd_config_reset_cmd
,
82 "Configure BFD peers\n")
84 nb_cli_enqueue_change(vty
, "/frr-bfdd:bfdd/bfd", NB_OP_DESTROY
, NULL
);
85 return nb_cli_apply_changes(vty
, NULL
);
88 void bfd_cli_show_header(struct vty
*vty
,
89 struct lyd_node
*dnode
__attribute__((__unused__
)),
90 bool show_defaults
__attribute__((__unused__
)))
92 vty_out(vty
, "!\nbfd\n");
95 void bfd_cli_show_header_end(struct vty
*vty
,
96 struct lyd_node
*dnode
__attribute__((__unused__
)))
102 bfd_peer_enter
, bfd_peer_enter_cmd
,
103 "peer <A.B.C.D|X:X::X:X> [{multihop$multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME$ifname|vrf NAME}]",
117 char source_str
[INET6_ADDRSTRLEN
+ 32];
118 char xpath
[XPATH_MAXLEN
], xpath_srcaddr
[XPATH_MAXLEN
+ 32];
121 if (!local_address_str
) {
122 vty_out(vty
, "%% local-address is required when using multihop\n");
123 return CMD_WARNING_CONFIG_FAILED
;
125 snprintf(source_str
, sizeof(source_str
), "[source-addr='%s']",
130 slen
= snprintf(xpath
, sizeof(xpath
),
131 "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
132 multihop
? "multi-hop" : "single-hop", source_str
,
135 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
136 "[interface='%s']", ifname
);
138 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
141 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']", vrf
);
143 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']",
146 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
147 if (multihop
== NULL
&& local_address_str
!= NULL
) {
148 snprintf(xpath_srcaddr
, sizeof(xpath_srcaddr
),
149 "%s/source-addr", xpath
);
150 nb_cli_enqueue_change(vty
, xpath_srcaddr
, NB_OP_MODIFY
,
154 /* Apply settings immediately. */
155 ret
= nb_cli_apply_changes(vty
, NULL
);
156 if (ret
== CMD_SUCCESS
)
157 VTY_PUSH_XPATH(BFD_PEER_NODE
, xpath
);
163 bfd_no_peer
, bfd_no_peer_cmd
,
164 "no peer <A.B.C.D|X:X::X:X> [{multihop$multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME$ifname|vrf NAME}]",
179 char xpath
[XPATH_MAXLEN
];
180 char source_str
[INET6_ADDRSTRLEN
+ 32];
183 snprintf(source_str
, sizeof(source_str
), "[source-addr='%s']",
188 slen
= snprintf(xpath
, sizeof(xpath
),
189 "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
190 multihop
? "multi-hop" : "single-hop", source_str
,
193 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
194 "[interface='%s']", ifname
);
196 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
199 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']", vrf
);
201 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']",
204 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
206 /* Apply settings immediatly. */
207 return nb_cli_apply_changes(vty
, NULL
);
210 static void _bfd_cli_show_peer(struct vty
*vty
, struct lyd_node
*dnode
,
211 bool show_defaults
__attribute__((__unused__
)),
214 const char *vrf
= yang_dnode_get_string(dnode
, "./vrf");
215 const char *ifname
= yang_dnode_get_string(dnode
, "./interface");
217 vty_out(vty
, " peer %s",
218 yang_dnode_get_string(dnode
, "./dest-addr"));
221 vty_out(vty
, " multihop");
223 if (yang_dnode_exists(dnode
, "./source-addr"))
224 vty_out(vty
, " local-address %s",
225 yang_dnode_get_string(dnode
, "./source-addr"));
227 if (strcmp(vrf
, VRF_DEFAULT_NAME
))
228 vty_out(vty
, " vrf %s", vrf
);
230 if (strcmp(ifname
, "*"))
231 vty_out(vty
, " interface %s", ifname
);
236 void bfd_cli_show_single_hop_peer(struct vty
*vty
,
237 struct lyd_node
*dnode
,
240 _bfd_cli_show_peer(vty
, dnode
, show_defaults
, false);
243 void bfd_cli_show_multi_hop_peer(struct vty
*vty
,
244 struct lyd_node
*dnode
,
247 _bfd_cli_show_peer(vty
, dnode
, show_defaults
, true);
250 void bfd_cli_show_peer_end(struct vty
*vty
,
251 struct lyd_node
*dnode
__attribute__((__unused__
)))
253 vty_out(vty
, " !\n");
257 bfd_peer_shutdown
, bfd_peer_shutdown_cmd
,
260 "Disable BFD peer\n")
262 nb_cli_enqueue_change(vty
, "./administrative-down", NB_OP_MODIFY
,
263 no
? "false" : "true");
264 return nb_cli_apply_changes(vty
, NULL
);
267 void bfd_cli_show_shutdown(struct vty
*vty
, struct lyd_node
*dnode
,
271 vty_out(vty
, " shutdown\n");
273 vty_out(vty
, " %sshutdown\n",
274 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
278 bfd_peer_passive
, bfd_peer_passive_cmd
,
281 "Don't attempt to start sessions\n")
283 nb_cli_enqueue_change(vty
, "./passive-mode", NB_OP_MODIFY
,
284 no
? "false" : "true");
285 return nb_cli_apply_changes(vty
, NULL
);
288 void bfd_cli_show_passive(struct vty
*vty
, struct lyd_node
*dnode
,
292 vty_out(vty
, " no passive-mode\n");
294 vty_out(vty
, " %spassive-mode\n",
295 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
299 bfd_peer_minimum_ttl
, bfd_peer_minimum_ttl_cmd
,
300 "[no] minimum-ttl (1-254)$ttl",
302 "Expect packets with at least this TTL\n"
303 "Minimum TTL expected\n")
305 if (bfd_cli_is_single_hop(vty
)) {
306 vty_out(vty
, "%% Minimum TTL is only available for multi hop sessions.\n");
307 return CMD_WARNING_CONFIG_FAILED
;
311 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_DESTROY
,
314 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_MODIFY
,
316 return nb_cli_apply_changes(vty
, NULL
);
320 no_bfd_peer_minimum_ttl
, no_bfd_peer_minimum_ttl_cmd
,
323 "Expect packets with at least this TTL\n")
325 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_DESTROY
, NULL
);
326 return nb_cli_apply_changes(vty
, NULL
);
329 void bfd_cli_show_minimum_ttl(struct vty
*vty
, struct lyd_node
*dnode
,
333 vty_out(vty
, " minimum-ttl 254\n");
335 vty_out(vty
, " minimum-ttl %s\n",
336 yang_dnode_get_string(dnode
, NULL
));
340 bfd_peer_mult
, bfd_peer_mult_cmd
,
341 "detect-multiplier (2-255)$multiplier",
342 "Configure peer detection multiplier\n"
343 "Configure peer detection multiplier value\n")
345 nb_cli_enqueue_change(vty
, "./detection-multiplier", NB_OP_MODIFY
,
347 return nb_cli_apply_changes(vty
, NULL
);
350 void bfd_cli_show_mult(struct vty
*vty
, struct lyd_node
*dnode
,
354 vty_out(vty
, " detect-multiplier %d\n",
357 vty_out(vty
, " detect-multiplier %s\n",
358 yang_dnode_get_string(dnode
, NULL
));
362 bfd_peer_rx
, bfd_peer_rx_cmd
,
363 "receive-interval (10-60000)$interval",
364 "Configure peer receive interval\n"
365 "Configure peer receive interval value in milliseconds\n")
369 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
370 nb_cli_enqueue_change(vty
, "./required-receive-interval", NB_OP_MODIFY
,
373 return nb_cli_apply_changes(vty
, NULL
);
376 void bfd_cli_show_rx(struct vty
*vty
, struct lyd_node
*dnode
,
382 vty_out(vty
, " receive-interval %d\n",
383 BFD_DEFREQUIREDMINRX
);
385 value
= yang_dnode_get_uint32(dnode
, NULL
);
386 vty_out(vty
, " receive-interval %u\n", value
/ 1000);
391 bfd_peer_tx
, bfd_peer_tx_cmd
,
392 "transmit-interval (10-60000)$interval",
393 "Configure peer transmit interval\n"
394 "Configure peer transmit interval value in milliseconds\n")
398 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
399 nb_cli_enqueue_change(vty
, "./desired-transmission-interval",
400 NB_OP_MODIFY
, value
);
402 return nb_cli_apply_changes(vty
, NULL
);
405 void bfd_cli_show_tx(struct vty
*vty
, struct lyd_node
*dnode
,
411 vty_out(vty
, " transmit-interval %d\n",
412 BFD_DEFDESIREDMINTX
);
414 value
= yang_dnode_get_uint32(dnode
, NULL
);
415 vty_out(vty
, " transmit-interval %u\n", value
/ 1000);
420 bfd_peer_echo
, bfd_peer_echo_cmd
,
423 "Configure echo mode\n")
425 if (!bfd_cli_is_single_hop(vty
)) {
426 vty_out(vty
, "%% Echo mode is only available for single hop sessions.\n");
427 return CMD_WARNING_CONFIG_FAILED
;
430 nb_cli_enqueue_change(vty
, "./echo-mode", NB_OP_MODIFY
,
431 no
? "false" : "true");
432 return nb_cli_apply_changes(vty
, NULL
);
435 void bfd_cli_show_echo(struct vty
*vty
, struct lyd_node
*dnode
,
439 vty_out(vty
, " no echo-mode\n");
441 vty_out(vty
, " %secho-mode\n",
442 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
446 bfd_peer_echo_interval
, bfd_peer_echo_interval_cmd
,
447 "echo-interval (10-60000)$interval",
448 "Configure peer echo interval\n"
449 "Configure peer echo interval value in milliseconds\n")
453 if (!bfd_cli_is_single_hop(vty
)) {
454 vty_out(vty
, "%% Echo mode is only available for single hop sessions.\n");
455 return CMD_WARNING_CONFIG_FAILED
;
458 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
459 nb_cli_enqueue_change(vty
, "./desired-echo-transmission-interval",
460 NB_OP_MODIFY
, value
);
462 return nb_cli_apply_changes(vty
, NULL
);
465 void bfd_cli_show_echo_interval(struct vty
*vty
, struct lyd_node
*dnode
,
471 vty_out(vty
, " echo-interval %d\n",
472 BFD_DEF_REQ_MIN_ECHO
);
474 value
= yang_dnode_get_uint32(dnode
, NULL
);
475 vty_out(vty
, " echo-interval %u\n", value
/ 1000);
482 DEFPY_YANG_NOSH(bfd_profile
, bfd_profile_cmd
,
485 BFD_PROFILE_NAME_STR
)
487 char xpath
[XPATH_MAXLEN
];
490 snprintf(xpath
, sizeof(xpath
), "/frr-bfdd:bfdd/bfd/profile[name='%s']",
493 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
495 /* Apply settings immediately. */
496 rv
= nb_cli_apply_changes(vty
, NULL
);
497 if (rv
== CMD_SUCCESS
)
498 VTY_PUSH_XPATH(BFD_PROFILE_NODE
, xpath
);
503 DEFPY_YANG(no_bfd_profile
, no_bfd_profile_cmd
,
504 "no profile BFDPROF$name",
507 BFD_PROFILE_NAME_STR
)
509 char xpath
[XPATH_MAXLEN
];
511 snprintf(xpath
, sizeof(xpath
), "/frr-bfdd:bfdd/bfd/profile[name='%s']",
514 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
516 /* Apply settings immediately. */
517 return nb_cli_apply_changes(vty
, NULL
);
520 void bfd_cli_show_profile(struct vty
*vty
, struct lyd_node
*dnode
,
523 vty_out(vty
, " profile %s\n", yang_dnode_get_string(dnode
, "./name"));
526 ALIAS_YANG(bfd_peer_mult
, bfd_profile_mult_cmd
,
527 "detect-multiplier (2-255)$multiplier",
528 "Configure peer detection multiplier\n"
529 "Configure peer detection multiplier value\n")
531 ALIAS_YANG(bfd_peer_tx
, bfd_profile_tx_cmd
,
532 "transmit-interval (10-60000)$interval",
533 "Configure peer transmit interval\n"
534 "Configure peer transmit interval value in milliseconds\n")
536 ALIAS_YANG(bfd_peer_rx
, bfd_profile_rx_cmd
,
537 "receive-interval (10-60000)$interval",
538 "Configure peer receive interval\n"
539 "Configure peer receive interval value in milliseconds\n")
541 ALIAS_YANG(bfd_peer_shutdown
, bfd_profile_shutdown_cmd
,
544 "Disable BFD peer\n")
546 ALIAS_YANG(bfd_peer_passive
, bfd_profile_passive_cmd
,
549 "Don't attempt to start sessions\n")
551 ALIAS_YANG(bfd_peer_minimum_ttl
, bfd_profile_minimum_ttl_cmd
,
552 "[no] minimum-ttl (1-254)$ttl",
554 "Expect packets with at least this TTL\n"
555 "Minimum TTL expected\n")
557 ALIAS_YANG(no_bfd_peer_minimum_ttl
, no_bfd_profile_minimum_ttl_cmd
,
560 "Expect packets with at least this TTL\n")
562 ALIAS_YANG(bfd_peer_echo
, bfd_profile_echo_cmd
,
565 "Configure echo mode\n")
567 ALIAS_YANG(bfd_peer_echo_interval
, bfd_profile_echo_interval_cmd
,
568 "echo-interval (10-60000)$interval",
569 "Configure peer echo interval\n"
570 "Configure peer echo interval value in milliseconds\n")
572 DEFPY_YANG(bfd_peer_profile
, bfd_peer_profile_cmd
,
573 "[no] profile BFDPROF$pname",
575 "Use BFD profile settings\n"
576 BFD_PROFILE_NAME_STR
)
579 nb_cli_enqueue_change(vty
, "./profile", NB_OP_DESTROY
, NULL
);
581 nb_cli_enqueue_change(vty
, "./profile", NB_OP_MODIFY
, pname
);
583 return nb_cli_apply_changes(vty
, NULL
);
586 void bfd_cli_peer_profile_show(struct vty
*vty
, struct lyd_node
*dnode
,
589 vty_out(vty
, " profile %s\n", yang_dnode_get_string(dnode
, NULL
));
592 struct cmd_node bfd_profile_node
= {
593 .name
= "bfd profile",
594 .node
= BFD_PROFILE_NODE
,
595 .parent_node
= BFD_NODE
,
596 .prompt
= "%s(config-bfd-profile)# ",
599 static void bfd_profile_var(vector comps
, struct cmd_token
*token
)
601 extern struct bfdproflist bplist
;
602 struct bfd_profile
*bp
;
604 TAILQ_FOREACH (bp
, &bplist
, entry
) {
605 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, bp
->name
));
609 static const struct cmd_variable_handler bfd_vars
[] = {
610 {.tokenname
= "BFDPROF", .completions
= bfd_profile_var
},
611 {.completions
= NULL
}
617 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
618 install_element(CONFIG_NODE
, &bfd_config_reset_cmd
);
620 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
621 install_element(BFD_NODE
, &bfd_no_peer_cmd
);
623 install_element(BFD_PEER_NODE
, &bfd_peer_shutdown_cmd
);
624 install_element(BFD_PEER_NODE
, &bfd_peer_mult_cmd
);
625 install_element(BFD_PEER_NODE
, &bfd_peer_rx_cmd
);
626 install_element(BFD_PEER_NODE
, &bfd_peer_tx_cmd
);
627 install_element(BFD_PEER_NODE
, &bfd_peer_echo_cmd
);
628 install_element(BFD_PEER_NODE
, &bfd_peer_echo_interval_cmd
);
629 install_element(BFD_PEER_NODE
, &bfd_peer_profile_cmd
);
630 install_element(BFD_PEER_NODE
, &bfd_peer_passive_cmd
);
631 install_element(BFD_PEER_NODE
, &bfd_peer_minimum_ttl_cmd
);
632 install_element(BFD_PEER_NODE
, &no_bfd_peer_minimum_ttl_cmd
);
634 /* Profile commands. */
635 cmd_variable_handler_register(bfd_vars
);
637 install_node(&bfd_profile_node
);
638 install_default(BFD_PROFILE_NODE
);
640 install_element(BFD_NODE
, &bfd_profile_cmd
);
641 install_element(BFD_NODE
, &no_bfd_profile_cmd
);
643 install_element(BFD_PROFILE_NODE
, &bfd_profile_mult_cmd
);
644 install_element(BFD_PROFILE_NODE
, &bfd_profile_tx_cmd
);
645 install_element(BFD_PROFILE_NODE
, &bfd_profile_rx_cmd
);
646 install_element(BFD_PROFILE_NODE
, &bfd_profile_shutdown_cmd
);
647 install_element(BFD_PROFILE_NODE
, &bfd_profile_echo_cmd
);
648 install_element(BFD_PROFILE_NODE
, &bfd_profile_echo_interval_cmd
);
649 install_element(BFD_PROFILE_NODE
, &bfd_profile_passive_cmd
);
650 install_element(BFD_PROFILE_NODE
, &bfd_profile_minimum_ttl_cmd
);
651 install_element(BFD_PROFILE_NODE
, &no_bfd_profile_minimum_ttl_cmd
);