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 snprintf(source_str
, sizeof(source_str
), "[source-addr='%s']",
126 slen
= snprintf(xpath
, sizeof(xpath
),
127 "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
128 multihop
? "multi-hop" : "single-hop", source_str
,
131 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
132 "[interface='%s']", ifname
);
134 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
137 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']", vrf
);
139 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']",
142 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
143 if (multihop
== NULL
&& local_address_str
!= NULL
) {
144 snprintf(xpath_srcaddr
, sizeof(xpath_srcaddr
),
145 "%s/source-addr", xpath
);
146 nb_cli_enqueue_change(vty
, xpath_srcaddr
, NB_OP_MODIFY
,
150 /* Apply settings immediately. */
151 ret
= nb_cli_apply_changes(vty
, NULL
);
152 if (ret
== CMD_SUCCESS
)
153 VTY_PUSH_XPATH(BFD_PEER_NODE
, xpath
);
159 bfd_no_peer
, bfd_no_peer_cmd
,
160 "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}]",
175 char xpath
[XPATH_MAXLEN
];
176 char source_str
[INET6_ADDRSTRLEN
+ 32];
179 snprintf(source_str
, sizeof(source_str
), "[source-addr='%s']",
184 slen
= snprintf(xpath
, sizeof(xpath
),
185 "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
186 multihop
? "multi-hop" : "single-hop", source_str
,
189 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
190 "[interface='%s']", ifname
);
192 slen
+= snprintf(xpath
+ slen
, sizeof(xpath
) - slen
,
195 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']", vrf
);
197 snprintf(xpath
+ slen
, sizeof(xpath
) - slen
, "[vrf='%s']",
200 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
202 /* Apply settings immediatly. */
203 return nb_cli_apply_changes(vty
, NULL
);
206 static void _bfd_cli_show_peer(struct vty
*vty
, struct lyd_node
*dnode
,
207 bool show_defaults
__attribute__((__unused__
)),
210 const char *vrf
= yang_dnode_get_string(dnode
, "./vrf");
211 const char *ifname
= yang_dnode_get_string(dnode
, "./interface");
213 vty_out(vty
, " peer %s",
214 yang_dnode_get_string(dnode
, "./dest-addr"));
217 vty_out(vty
, " multihop");
219 if (yang_dnode_exists(dnode
, "./source-addr"))
220 vty_out(vty
, " local-address %s",
221 yang_dnode_get_string(dnode
, "./source-addr"));
223 if (strcmp(vrf
, VRF_DEFAULT_NAME
))
224 vty_out(vty
, " vrf %s", vrf
);
226 if (strcmp(ifname
, "*"))
227 vty_out(vty
, " interface %s", ifname
);
232 void bfd_cli_show_single_hop_peer(struct vty
*vty
,
233 struct lyd_node
*dnode
,
236 _bfd_cli_show_peer(vty
, dnode
, show_defaults
, false);
239 void bfd_cli_show_multi_hop_peer(struct vty
*vty
,
240 struct lyd_node
*dnode
,
243 _bfd_cli_show_peer(vty
, dnode
, show_defaults
, true);
246 void bfd_cli_show_peer_end(struct vty
*vty
,
247 struct lyd_node
*dnode
__attribute__((__unused__
)))
249 vty_out(vty
, " !\n");
253 bfd_peer_shutdown
, bfd_peer_shutdown_cmd
,
256 "Disable BFD peer\n")
258 nb_cli_enqueue_change(vty
, "./administrative-down", NB_OP_MODIFY
,
259 no
? "false" : "true");
260 return nb_cli_apply_changes(vty
, NULL
);
263 void bfd_cli_show_shutdown(struct vty
*vty
, struct lyd_node
*dnode
,
267 vty_out(vty
, " shutdown\n");
269 vty_out(vty
, " %sshutdown\n",
270 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
274 bfd_peer_passive
, bfd_peer_passive_cmd
,
277 "Don't attempt to start sessions\n")
279 nb_cli_enqueue_change(vty
, "./passive-mode", NB_OP_MODIFY
,
280 no
? "false" : "true");
281 return nb_cli_apply_changes(vty
, NULL
);
284 void bfd_cli_show_passive(struct vty
*vty
, struct lyd_node
*dnode
,
288 vty_out(vty
, " no passive-mode\n");
290 vty_out(vty
, " %spassive-mode\n",
291 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
295 bfd_peer_minimum_ttl
, bfd_peer_minimum_ttl_cmd
,
296 "[no] minimum-ttl (1-254)$ttl",
298 "Expect packets with at least this TTL\n"
299 "Minimum TTL expected\n")
301 if (bfd_cli_is_single_hop(vty
)) {
302 vty_out(vty
, "%% Minimum TTL is only available for multi hop sessions.\n");
303 return CMD_WARNING_CONFIG_FAILED
;
307 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_DESTROY
,
310 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_MODIFY
,
312 return nb_cli_apply_changes(vty
, NULL
);
316 no_bfd_peer_minimum_ttl
, no_bfd_peer_minimum_ttl_cmd
,
319 "Expect packets with at least this TTL\n")
321 nb_cli_enqueue_change(vty
, "./minimum-ttl", NB_OP_DESTROY
, NULL
);
322 return nb_cli_apply_changes(vty
, NULL
);
325 void bfd_cli_show_minimum_ttl(struct vty
*vty
, struct lyd_node
*dnode
,
329 vty_out(vty
, " minimum-ttl 254\n");
331 vty_out(vty
, " minimum-ttl %s\n",
332 yang_dnode_get_string(dnode
, NULL
));
336 bfd_peer_mult
, bfd_peer_mult_cmd
,
337 "detect-multiplier (2-255)$multiplier",
338 "Configure peer detection multiplier\n"
339 "Configure peer detection multiplier value\n")
341 nb_cli_enqueue_change(vty
, "./detection-multiplier", NB_OP_MODIFY
,
343 return nb_cli_apply_changes(vty
, NULL
);
346 void bfd_cli_show_mult(struct vty
*vty
, struct lyd_node
*dnode
,
350 vty_out(vty
, " detect-multiplier %d\n",
353 vty_out(vty
, " detect-multiplier %s\n",
354 yang_dnode_get_string(dnode
, NULL
));
358 bfd_peer_rx
, bfd_peer_rx_cmd
,
359 "receive-interval (10-60000)$interval",
360 "Configure peer receive interval\n"
361 "Configure peer receive interval value in milliseconds\n")
365 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
366 nb_cli_enqueue_change(vty
, "./required-receive-interval", NB_OP_MODIFY
,
369 return nb_cli_apply_changes(vty
, NULL
);
372 void bfd_cli_show_rx(struct vty
*vty
, struct lyd_node
*dnode
,
378 vty_out(vty
, " receive-interval %d\n",
379 BFD_DEFREQUIREDMINRX
);
381 value
= yang_dnode_get_uint32(dnode
, NULL
);
382 vty_out(vty
, " receive-interval %u\n", value
/ 1000);
387 bfd_peer_tx
, bfd_peer_tx_cmd
,
388 "transmit-interval (10-60000)$interval",
389 "Configure peer transmit interval\n"
390 "Configure peer transmit interval value in milliseconds\n")
394 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
395 nb_cli_enqueue_change(vty
, "./desired-transmission-interval",
396 NB_OP_MODIFY
, value
);
398 return nb_cli_apply_changes(vty
, NULL
);
401 void bfd_cli_show_tx(struct vty
*vty
, struct lyd_node
*dnode
,
407 vty_out(vty
, " transmit-interval %d\n",
408 BFD_DEFDESIREDMINTX
);
410 value
= yang_dnode_get_uint32(dnode
, NULL
);
411 vty_out(vty
, " transmit-interval %u\n", value
/ 1000);
416 bfd_peer_echo
, bfd_peer_echo_cmd
,
419 "Configure echo mode\n")
421 if (!bfd_cli_is_single_hop(vty
)) {
422 vty_out(vty
, "%% Echo mode is only available for single hop sessions.\n");
423 return CMD_WARNING_CONFIG_FAILED
;
426 nb_cli_enqueue_change(vty
, "./echo-mode", NB_OP_MODIFY
,
427 no
? "false" : "true");
428 return nb_cli_apply_changes(vty
, NULL
);
431 void bfd_cli_show_echo(struct vty
*vty
, struct lyd_node
*dnode
,
435 vty_out(vty
, " no echo-mode\n");
437 vty_out(vty
, " %secho-mode\n",
438 yang_dnode_get_bool(dnode
, NULL
) ? "" : "no ");
442 bfd_peer_echo_interval
, bfd_peer_echo_interval_cmd
,
443 "echo-interval (10-60000)$interval",
444 "Configure peer echo interval\n"
445 "Configure peer echo interval value in milliseconds\n")
449 if (!bfd_cli_is_single_hop(vty
)) {
450 vty_out(vty
, "%% Echo mode is only available for single hop sessions.\n");
451 return CMD_WARNING_CONFIG_FAILED
;
454 snprintf(value
, sizeof(value
), "%ld", interval
* 1000);
455 nb_cli_enqueue_change(vty
, "./desired-echo-transmission-interval",
456 NB_OP_MODIFY
, value
);
458 return nb_cli_apply_changes(vty
, NULL
);
461 void bfd_cli_show_echo_interval(struct vty
*vty
, struct lyd_node
*dnode
,
467 vty_out(vty
, " echo-interval %d\n",
468 BFD_DEF_REQ_MIN_ECHO
);
470 value
= yang_dnode_get_uint32(dnode
, NULL
);
471 vty_out(vty
, " echo-interval %u\n", value
/ 1000);
478 DEFPY_YANG_NOSH(bfd_profile
, bfd_profile_cmd
,
481 BFD_PROFILE_NAME_STR
)
483 char xpath
[XPATH_MAXLEN
];
486 snprintf(xpath
, sizeof(xpath
), "/frr-bfdd:bfdd/bfd/profile[name='%s']",
489 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
491 /* Apply settings immediately. */
492 rv
= nb_cli_apply_changes(vty
, NULL
);
493 if (rv
== CMD_SUCCESS
)
494 VTY_PUSH_XPATH(BFD_PROFILE_NODE
, xpath
);
499 DEFPY_YANG(no_bfd_profile
, no_bfd_profile_cmd
,
500 "no profile BFDPROF$name",
503 BFD_PROFILE_NAME_STR
)
505 char xpath
[XPATH_MAXLEN
];
507 snprintf(xpath
, sizeof(xpath
), "/frr-bfdd:bfdd/bfd/profile[name='%s']",
510 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
512 /* Apply settings immediately. */
513 return nb_cli_apply_changes(vty
, NULL
);
516 void bfd_cli_show_profile(struct vty
*vty
, struct lyd_node
*dnode
,
519 vty_out(vty
, " profile %s\n", yang_dnode_get_string(dnode
, "./name"));
522 ALIAS_YANG(bfd_peer_mult
, bfd_profile_mult_cmd
,
523 "detect-multiplier (2-255)$multiplier",
524 "Configure peer detection multiplier\n"
525 "Configure peer detection multiplier value\n")
527 ALIAS_YANG(bfd_peer_tx
, bfd_profile_tx_cmd
,
528 "transmit-interval (10-60000)$interval",
529 "Configure peer transmit interval\n"
530 "Configure peer transmit interval value in milliseconds\n")
532 ALIAS_YANG(bfd_peer_rx
, bfd_profile_rx_cmd
,
533 "receive-interval (10-60000)$interval",
534 "Configure peer receive interval\n"
535 "Configure peer receive interval value in milliseconds\n")
537 ALIAS_YANG(bfd_peer_shutdown
, bfd_profile_shutdown_cmd
,
540 "Disable BFD peer\n")
542 ALIAS_YANG(bfd_peer_passive
, bfd_profile_passive_cmd
,
545 "Don't attempt to start sessions\n")
547 ALIAS_YANG(bfd_peer_minimum_ttl
, bfd_profile_minimum_ttl_cmd
,
548 "[no] minimum-ttl (1-254)$ttl",
550 "Expect packets with at least this TTL\n"
551 "Minimum TTL expected\n")
553 ALIAS_YANG(no_bfd_peer_minimum_ttl
, no_bfd_profile_minimum_ttl_cmd
,
556 "Expect packets with at least this TTL\n")
558 ALIAS_YANG(bfd_peer_echo
, bfd_profile_echo_cmd
,
561 "Configure echo mode\n")
563 ALIAS_YANG(bfd_peer_echo_interval
, bfd_profile_echo_interval_cmd
,
564 "echo-interval (10-60000)$interval",
565 "Configure peer echo interval\n"
566 "Configure peer echo interval value in milliseconds\n")
568 DEFPY_YANG(bfd_peer_profile
, bfd_peer_profile_cmd
,
569 "[no] profile BFDPROF$pname",
571 "Use BFD profile settings\n"
572 BFD_PROFILE_NAME_STR
)
575 nb_cli_enqueue_change(vty
, "./profile", NB_OP_DESTROY
, NULL
);
577 nb_cli_enqueue_change(vty
, "./profile", NB_OP_MODIFY
, pname
);
579 return nb_cli_apply_changes(vty
, NULL
);
582 void bfd_cli_peer_profile_show(struct vty
*vty
, struct lyd_node
*dnode
,
585 vty_out(vty
, " profile %s\n", yang_dnode_get_string(dnode
, NULL
));
588 struct cmd_node bfd_profile_node
= {
589 .name
= "bfd profile",
590 .node
= BFD_PROFILE_NODE
,
591 .parent_node
= BFD_NODE
,
592 .prompt
= "%s(config-bfd-profile)# ",
595 static void bfd_profile_var(vector comps
, struct cmd_token
*token
)
597 extern struct bfdproflist bplist
;
598 struct bfd_profile
*bp
;
600 TAILQ_FOREACH (bp
, &bplist
, entry
) {
601 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, bp
->name
));
605 static const struct cmd_variable_handler bfd_vars
[] = {
606 {.tokenname
= "BFDPROF", .completions
= bfd_profile_var
},
607 {.completions
= NULL
}
613 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
614 install_element(CONFIG_NODE
, &bfd_config_reset_cmd
);
616 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
617 install_element(BFD_NODE
, &bfd_no_peer_cmd
);
619 install_element(BFD_PEER_NODE
, &bfd_peer_shutdown_cmd
);
620 install_element(BFD_PEER_NODE
, &bfd_peer_mult_cmd
);
621 install_element(BFD_PEER_NODE
, &bfd_peer_rx_cmd
);
622 install_element(BFD_PEER_NODE
, &bfd_peer_tx_cmd
);
623 install_element(BFD_PEER_NODE
, &bfd_peer_echo_cmd
);
624 install_element(BFD_PEER_NODE
, &bfd_peer_echo_interval_cmd
);
625 install_element(BFD_PEER_NODE
, &bfd_peer_profile_cmd
);
626 install_element(BFD_PEER_NODE
, &bfd_peer_passive_cmd
);
627 install_element(BFD_PEER_NODE
, &bfd_peer_minimum_ttl_cmd
);
628 install_element(BFD_PEER_NODE
, &no_bfd_peer_minimum_ttl_cmd
);
630 /* Profile commands. */
631 cmd_variable_handler_register(bfd_vars
);
633 install_node(&bfd_profile_node
);
634 install_default(BFD_PROFILE_NODE
);
636 install_element(BFD_NODE
, &bfd_profile_cmd
);
637 install_element(BFD_NODE
, &no_bfd_profile_cmd
);
639 install_element(BFD_PROFILE_NODE
, &bfd_profile_mult_cmd
);
640 install_element(BFD_PROFILE_NODE
, &bfd_profile_tx_cmd
);
641 install_element(BFD_PROFILE_NODE
, &bfd_profile_rx_cmd
);
642 install_element(BFD_PROFILE_NODE
, &bfd_profile_shutdown_cmd
);
643 install_element(BFD_PROFILE_NODE
, &bfd_profile_echo_cmd
);
644 install_element(BFD_PROFILE_NODE
, &bfd_profile_echo_interval_cmd
);
645 install_element(BFD_PROFILE_NODE
, &bfd_profile_passive_cmd
);
646 install_element(BFD_PROFILE_NODE
, &bfd_profile_minimum_ttl_cmd
);
647 install_element(BFD_PROFILE_NODE
, &no_bfd_profile_minimum_ttl_cmd
);