From 41e195d47732fab800ce4f8bfd0b88561d2fab74 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 18 Jan 2019 22:58:58 -0200 Subject: [PATCH 1/2] lib: reset the vty xpath index when entering the config mode The CLI code uses the vty->xpath[] array and the vty->xpath_index variables to keep track of where the user is in the configuration hierarchy. As such, we were resetting vty->xpath_index to zero whenever the user exited from the configuration mode in order to keep the index valid. We weren't doing this in the vty_stop_input() function however, which is called when the user types ^C in the terminal. This was leading to bugs like this: zebra> en zebra# conf t zebra(config)# interface eth0 zebra(config-if)# ^C zebra# conf t zebra(config)# interface eth0 % Configuration failed. Schema node not found. YANG path: /frr-interface:lib/interface[name='eth0'][vrf='default']/frr-interface:lib To fix this, do something more clever: instead of resetting the XPath index whenever the user exits from the configuration mode, do that when the user enters in the configuration mode. This way the XPath index needs to be reset in a single place only, not to mention it's a more robust solution. Signed-off-by: Renato Westphal --- lib/command.c | 2 -- lib/vty.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/command.c b/lib/command.c index d1dafa3a1a..7d20bae62a 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1594,8 +1594,6 @@ DEFUN (config_end, break; } - vty->xpath_index = 0; - return CMD_SUCCESS; } diff --git a/lib/vty.c b/lib/vty.c index 085cbac742..f93301170a 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -828,8 +828,6 @@ static void vty_end_config(struct vty *vty) break; } - vty->xpath_index = 0; - vty_prompt(vty); vty->cp = 0; } @@ -2696,6 +2694,7 @@ int vty_config_enter(struct vty *vty, bool private_config, bool exclusive) vty->node = CONFIG_NODE; vty->config = true; vty->private_config = private_config; + vty->xpath_index = 0; if (private_config) { vty->candidate_config = nb_config_dup(running_config); From cf09d3ca45fa00c7474e5019534a339f48989c33 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 18 Jan 2019 23:23:45 -0200 Subject: [PATCH 2/2] lib: simplify detection of when the user is leaving the CLI config mode We can make use of the vty->config variable to know when the CLI user is in the configuration mode or not. This is much simpler than obtaining this information from the vty node, and also a more robust solution (the three switch statements below, for example, were out of sync). Also, fix a bug where vty->config wasn't being unset in the vty_config_exit() function (bug introduced by commit f344c66ea3). Signed-off-by: Renato Westphal --- lib/command.c | 56 +------------------------------- lib/vty.c | 89 +++------------------------------------------------ 2 files changed, 6 insertions(+), 139 deletions(-) diff --git a/lib/command.c b/lib/command.c index 7d20bae62a..05ccb52ab5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1535,63 +1535,9 @@ DEFUN (config_end, "end", "End current mode and change to enable mode.\n") { - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case LOGICALROUTER_NODE: - case VRF_NODE: - case NH_GROUP_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BABEL_NODE: - case BGP_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_FLOWSPECV4_NODE: - case BGP_FLOWSPECV6_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_EVPN_VNI_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case LINK_PARAMS_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - break; } return CMD_SUCCESS; diff --git a/lib/vty.c b/lib/vty.c index f93301170a..8450922c2b 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -775,57 +775,9 @@ static void vty_end_config(struct vty *vty) { vty_out(vty, "\n"); - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case BGP_EVPN_VNI_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; } vty_prompt(vty); @@ -1188,44 +1140,11 @@ static void vty_stop_input(struct vty *vty) vty_clear_buf(vty); vty_out(vty, "\n"); - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; } + vty_prompt(vty); /* Set history pointer to the latest one. */ @@ -2732,6 +2651,8 @@ void vty_config_exit(struct vty *vty) nb_config_free(vty->candidate_config_base); vty->candidate_config_base = NULL; } + + vty->config = false; } int vty_config_exclusive_lock(struct vty *vty)