diff options
author | Christian Hopps <chopps@labn.net> | 2021-08-26 17:57:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-26 17:57:33 +0200 |
commit | d448e2c5f96b3430fd643f52b9264ca87a45c291 (patch) | |
tree | d38574fb0ce8c936a003287d107eebf6eb718a8c | |
parent | Merge pull request #9492 from Jafaral/pim-cov (diff) | |
parent | *: explicitly print "exit" at the end of every node config (diff) | |
download | frr-d448e2c5f96b3430fd643f52b9264ca87a45c291.tar.xz frr-d448e2c5f96b3430fd643f52b9264ca87a45c291.zip |
Merge pull request #9331 from idryzhov/explicit-exit
*: explicitly print "exit" at the end of every node config
41 files changed, 250 insertions, 428 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index c1e5ffde3..615ed9fee 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1362,7 +1362,7 @@ interface_config_write (struct vty *vty) write++; } } - vty_endframe (vty, "!\n"); + vty_endframe (vty, "exit\n!\n"); write++; } return write; diff --git a/babeld/babeld.c b/babeld/babeld.c index b9623b64b..b9037423b 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -132,6 +132,8 @@ babel_config_write (struct vty *vty) lines += config_write_distribute (vty, babel_routing_process->distribute_ctx); + vty_out (vty, "exit\n"); + return lines; } diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 26ff4a758..384bb26fd 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -101,6 +101,7 @@ void bfd_cli_show_header(struct vty *vty, void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode __attribute__((__unused__))) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } @@ -275,6 +276,7 @@ void bfd_cli_show_multi_hop_peer(struct vty *vty, void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode __attribute__((__unused__))) { + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index dbc35de80..1bc3fd0db 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -2400,6 +2400,8 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) frr_each (bmp_actives, &bt->actives, ba) vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n", ba->hostname, ba->port, ba->minretry, ba->maxretry); + + vty_out(vty, " exit\n"); } return 0; diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 286612da1..ca3f93899 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -932,7 +932,7 @@ static int config_write(struct vty *vty) vty_out(vty, "preference %hhu\n", cache->preference); } - vty_out(vty, " exit\n"); + vty_out(vty, "exit\n"); return 1; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 27f147a4a..dd4a776a2 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -17213,6 +17213,7 @@ int bgp_config_write(struct vty *vty) bgp_rfapi_cfg_write(vty, bgp); #endif + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index cc6426138..2437bd8cf 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -4043,7 +4043,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) rfg->routemap_redist_name [ZEBRA_ROUTE_BGP_DIRECT_EXT]); } - vty_out(vty, " exit-vrf-policy\n"); + vty_out(vty, " exit-vrf-policy\n"); vty_out(vty, "!\n"); } if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) { @@ -4121,7 +4121,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_L2, rfgc->name, rfgc->rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } } @@ -4199,7 +4199,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_DEFAULT, NULL, bgp->rfapi_cfg->default_rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } @@ -4364,7 +4364,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_NVE, rfg->name, rfg->rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } } /* have listen ports */ diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c index 35536979e..d61f43586 100644 --- a/eigrpd/eigrp_cli.c +++ b/eigrpd/eigrp_cli.c @@ -96,6 +96,7 @@ void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode, void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index a78e4996b..6f4a91be6 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1290,7 +1290,7 @@ static int isis_interface_config_write(struct vty *vty) write += hook_call(isis_circuit_config_write, circuit, vty); } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return write; diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index ef86d47b2..70ec66fd7 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -146,6 +146,11 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, vty_out(vty, "\n"); } +void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + /* * XPath: /frr-interface:lib/interface/frr-isisd:isis/ * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index ecad16229..f62a8d481 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -32,6 +32,7 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-isisd:isis/instance", .cbs = { .cli_show = cli_show_router_isis, + .cli_show_end = cli_show_router_isis_end, .create = isis_instance_create, .destroy = isis_instance_destroy, }, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index 0c2f7b6b7..4680dd5de 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -415,6 +415,7 @@ void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish( /* Optional 'cli_show' callbacks. */ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode); void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, diff --git a/isisd/isisd.c b/isisd/isisd.c index 43efa0164..ebcc9985b 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -3011,6 +3011,8 @@ static int isis_config_write(struct vty *vty) write += area_write_mt_settings(area, vty); write += fabricd_write_settings(area, vty); + + vty_out(vty, "exit\n"); } } diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index b35d3dfa0..fbd718bb0 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -133,6 +133,8 @@ ldp_af_iface_config_write(struct vty *vty, int af) ia->hello_interval != 0) vty_out (vty, " discovery hello interval %u\n", ia->hello_interval); + + vty_out (vty, " exit\n"); } } @@ -314,6 +316,7 @@ ldp_config_write(struct vty *vty) ldp_af_config_write(vty, AF_INET, ldpd_conf, &ldpd_conf->ipv4); ldp_af_config_write(vty, AF_INET6, ldpd_conf, &ldpd_conf->ipv6); vty_out (vty, " !\n"); + vty_out (vty, "exit\n"); vty_out (vty, "!\n"); return (1); @@ -353,6 +356,8 @@ ldp_l2vpn_pw_config_write(struct vty *vty, struct l2vpn_pw *pw) " ! Incomplete config, specify a neighbor lsr-id\n"); if (missing_pwid) vty_out (vty," ! Incomplete config, specify a pw-id\n"); + + vty_out (vty, " exit\n"); } static int @@ -383,6 +388,7 @@ ldp_l2vpn_config_write(struct vty *vty) ldp_l2vpn_pw_config_write(vty, pw); vty_out (vty, " !\n"); + vty_out (vty, "exit\n"); vty_out (vty, "!\n"); } @@ -1291,6 +1291,11 @@ static void cli_show_interface(struct vty *vty, struct lyd_node *dnode, vty_out(vty, "\n"); } +static void cli_show_interface_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + /* * XPath: /frr-interface:lib/interface/description */ @@ -1652,6 +1657,7 @@ const struct frr_yang_module_info frr_interface_info = { .create = lib_interface_create, .destroy = lib_interface_destroy, .cli_show = cli_show_interface, + .cli_show_end = cli_show_interface_end, .get_next = lib_interface_get_next, .get_keys = lib_interface_get_keys, .lookup_entry = lib_interface_lookup_entry, diff --git a/lib/keychain.c b/lib/keychain.c index db5c23b1b..02f83ef0a 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -1044,6 +1044,7 @@ static int keychain_config_write(struct vty *vty) vty_out(vty, " exit\n"); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 4fee9bde3..97d70189f 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -1156,6 +1156,7 @@ static int nexthop_group_write(struct vty *vty) nexthop_group_write_nexthop_internal(vty, nh); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 58c62e614..045a8cddd 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -124,6 +124,7 @@ void route_map_instance_show(struct vty *vty, struct lyd_node *dnode, void route_map_instance_show_end(struct vty *vty, struct lyd_node *dnode) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } @@ -3040,7 +3040,7 @@ DEFPY (log_commands, /* Display current configuration. */ static int vty_config_write(struct vty *vty) { - vty_out(vty, "line vty\n"); + vty_frame(vty, "line vty\n"); if (vty_accesslist_name) vty_out(vty, " access-class %s\n", vty_accesslist_name); @@ -3058,6 +3058,8 @@ static int vty_config_write(struct vty *vty) if (no_password_check) vty_out(vty, " no login\n"); + vty_endframe(vty, "exit\n"); + if (do_log_commands) vty_out(vty, "log commands\n"); diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 60ce1e652..a77121448 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1225,7 +1225,7 @@ static int interface_config_write(struct vty *vty) } } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index bbb474ba1..b427a0c9b 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -2593,7 +2593,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) ospf6_bfd_write_config(vty, oi); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; } diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index fc181a6d1..b159f1139 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -2237,6 +2237,8 @@ static int config_write_ospf6(struct vty *vty) ospf6_distribute_config_write(vty, ospf6); ospf6_asbr_summary_config_write(vty, ospf6); config_write_ospf6_gr_helper(vty, ospf6); + + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4c248c0df..1843947db 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -11970,7 +11970,7 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) ospf_opaque_config_write_if(vty, ifp); - vty_endframe(vty, NULL); + vty_endframe(vty, "exit\n!\n"); } return write; @@ -12546,6 +12546,8 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) /* LDP-Sync print */ ospf_ldp_sync_write_config(vty, ospf); + vty_out(vty, "exit\n"); + write++; return write; } diff --git a/pathd/path_cli.c b/pathd/path_cli.c index d517d75e4..bd629a2b7 100644 --- a/pathd/path_cli.c +++ b/pathd/path_cli.c @@ -45,9 +45,6 @@ static int config_write_segment_routing(struct vty *vty); -static int config_write_traffic_eng(struct vty *vty); -static int config_write_segment_lists(struct vty *vty); -static int config_write_sr_policies(struct vty *vty); static int segment_list_has_src_dst( struct vty *vty, char *xpath, long index, const char *index_str, struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4, @@ -63,6 +60,8 @@ static int segment_list_has_prefix( DEFINE_MTYPE_STATIC(PATHD, PATH_CLI, "Client"); +DEFINE_HOOK(pathd_srte_config_write, (struct vty *vty), (vty)); + /* Vty node structures. */ static struct cmd_node segment_routing_node = { .name = "segment-routing", @@ -77,7 +76,6 @@ static struct cmd_node sr_traffic_eng_node = { .node = SR_TRAFFIC_ENG_NODE, .parent_node = SEGMENT_ROUTING_NODE, .prompt = "%s(config-sr-te)# ", - .config_write = config_write_traffic_eng, }; static struct cmd_node srte_segment_list_node = { @@ -85,7 +83,6 @@ static struct cmd_node srte_segment_list_node = { .node = SR_SEGMENT_LIST_NODE, .parent_node = SR_TRAFFIC_ENG_NODE, .prompt = "%s(config-sr-te-segment-list)# ", - .config_write = config_write_segment_lists, }; static struct cmd_node srte_policy_node = { @@ -93,7 +90,6 @@ static struct cmd_node srte_policy_node = { .node = SR_POLICY_NODE, .parent_node = SR_TRAFFIC_ENG_NODE, .prompt = "%s(config-sr-te-policy)# ", - .config_write = config_write_sr_policies, }; static struct cmd_node srte_candidate_dyn_node = { @@ -309,6 +305,11 @@ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./name")); } +void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, " exit\n"); +} + static int segment_list_has_src_dst( struct vty *vty, char *xpath, long index, const char *index_str, struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4, @@ -666,6 +667,11 @@ void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./endpoint")); } +void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, " exit\n"); +} + /* * XPath: /frr-pathd:pathd/srte/policy/name */ @@ -1237,6 +1243,15 @@ void cli_show_srte_policy_candidate_path(struct vty *vty, } } +void cli_show_srte_policy_candidate_path_end(struct vty *vty, + struct lyd_node *dnode) +{ + const char *type = yang_dnode_get_string(dnode, "./type"); + + if (strmatch(type, "dynamic")) + vty_out(vty, " exit\n"); +} + static int config_write_dnode(const struct lyd_node *dnode, void *arg) { struct vty *vty = arg; @@ -1249,29 +1264,20 @@ static int config_write_dnode(const struct lyd_node *dnode, void *arg) int config_write_segment_routing(struct vty *vty) { vty_out(vty, "segment-routing\n"); - return 1; -} - -int config_write_traffic_eng(struct vty *vty) -{ vty_out(vty, " traffic-eng\n"); + path_ted_config_write(vty); - return 1; -} -int config_write_segment_lists(struct vty *vty) -{ yang_dnode_iterate(config_write_dnode, vty, running_config->dnode, "/frr-pathd:pathd/srte/segment-list"); - - return 1; -} - -int config_write_sr_policies(struct vty *vty) -{ yang_dnode_iterate(config_write_dnode, vty, running_config->dnode, "/frr-pathd:pathd/srte/policy"); + hook_call(pathd_srte_config_write, vty); + + vty_out(vty, " exit\n"); + vty_out(vty, "exit\n"); + return 1; } diff --git a/pathd/path_nb.c b/pathd/path_nb.c index 9c622883b..1ab8b7f39 100644 --- a/pathd/path_nb.c +++ b/pathd/path_nb.c @@ -56,6 +56,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_segment_list_create, .cli_show = cli_show_srte_segment_list, + .cli_show_end = cli_show_srte_segment_list_end, .destroy = pathd_srte_segment_list_destroy, .get_next = pathd_srte_segment_list_get_next, .get_keys = pathd_srte_segment_list_get_keys, @@ -136,6 +137,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_policy_create, .cli_show = cli_show_srte_policy, + .cli_show_end = cli_show_srte_policy_end, .destroy = pathd_srte_policy_destroy, .get_next = pathd_srte_policy_get_next, .get_keys = pathd_srte_policy_get_keys, @@ -169,6 +171,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_policy_candidate_path_create, .cli_show = cli_show_srte_policy_candidate_path, + .cli_show_end = cli_show_srte_policy_candidate_path_end, .destroy = pathd_srte_policy_candidate_path_destroy, .get_next = pathd_srte_policy_candidate_path_get_next, .get_keys = pathd_srte_policy_candidate_path_get_keys, diff --git a/pathd/path_nb.h b/pathd/path_nb.h index caeadd9cc..6a918b8b8 100644 --- a/pathd/path_nb.h +++ b/pathd/path_nb.h @@ -112,10 +112,12 @@ void pathd_apply_finish(struct nb_cb_apply_finish_args *args); /* Optional 'cli_show' callbacks. */ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode); void cli_show_srte_segment_list_segment(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode); void cli_show_srte_policy_name(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_srte_policy_binding_sid(struct vty *vty, struct lyd_node *dnode, @@ -123,6 +125,8 @@ void cli_show_srte_policy_binding_sid(struct vty *vty, struct lyd_node *dnode, void cli_show_srte_policy_candidate_path(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_policy_candidate_path_end(struct vty *vty, + struct lyd_node *dnode); /* Utility functions */ typedef void (*of_pref_cp_t)(enum objfun_type type, void *arg); diff --git a/pathd/path_pcep_cli.c b/pathd/path_pcep_cli.c index db5f256a8..829df3179 100644 --- a/pathd/path_pcep_cli.c +++ b/pathd/path_pcep_cli.c @@ -175,7 +175,6 @@ static struct cmd_node pcep_node = { .name = "srte pcep", .node = PCEP_NODE, .parent_node = SR_TRAFFIC_ENG_NODE, - .config_write = pcep_cli_pcep_config_write, .prompt = "%s(config-sr-te-pcep)# " }; @@ -183,7 +182,6 @@ static struct cmd_node pcep_pcc_node = { .name = "srte pcep pcc", .node = PCEP_PCC_NODE, .parent_node = PCEP_NODE, - .config_write = pcep_cli_pcc_config_write, .prompt = "%s(config-sr-te-pcep-pcc)# " }; @@ -191,7 +189,6 @@ static struct cmd_node pcep_pce_node = { .name = "srte pcep pce", .node = PCEP_PCE_NODE, .parent_node = PCEP_NODE, - .config_write = pcep_cli_pce_config_write, .prompt = "%s(config-sr-te-pcep-pce)# " }; @@ -199,7 +196,6 @@ static struct cmd_node pcep_pce_config_node = { .name = "srte pcep pce-config", .node = PCEP_PCE_CONFIG_NODE, .parent_node = PCEP_NODE, - .config_write = pcep_cli_pcep_pce_config_write, .prompt = "%s(pce-sr-te-pcep-pce-config)# " }; @@ -1444,6 +1440,10 @@ int pcep_cli_debug_set_all(uint32_t flags, bool set) int pcep_cli_pcep_config_write(struct vty *vty) { vty_out(vty, " pcep\n"); + pcep_cli_pcep_pce_config_write(vty); + pcep_cli_pce_config_write(vty); + pcep_cli_pcc_config_write(vty); + vty_out(vty, " exit\n"); return 1; } @@ -1468,7 +1468,7 @@ int pcep_cli_pcc_config_write(struct vty *vty) } if (pce_connections_g.num_connections == 0) { - return lines; + goto exit; } buf[0] = 0; @@ -1495,6 +1495,8 @@ int pcep_cli_pcc_config_write(struct vty *vty) lines++; buf[0] = 0; } +exit: + vty_out(vty, " exit\n"); return lines; } @@ -1655,6 +1657,8 @@ int pcep_cli_pce_config_write(struct vty *vty) vty_out(vty, "%s", buf); buf[0] = '\0'; + + vty_out(vty, " exit\n"); } return lines; @@ -1679,6 +1683,8 @@ int pcep_cli_pcep_pce_config_write(struct vty *vty) pcep_cli_print_pce_config(group_opts, buf, sizeof(buf)); vty_out(vty, "%s", buf); buf[0] = 0; + + vty_out(vty, " exit\n"); } return lines; @@ -1999,6 +2005,7 @@ DEFPY(pcep_cli_clear_srte_pcep_session, void pcep_cli_init(void) { + hook_register(pathd_srte_config_write, pcep_cli_pcep_config_write); hook_register(nb_client_debug_config_write, pcep_cli_debug_config_write); hook_register(nb_client_debug_set_all, pcep_cli_debug_set_all); diff --git a/pathd/pathd.h b/pathd/pathd.h index f790a0e3c..81d7aa910 100644 --- a/pathd/pathd.h +++ b/pathd/pathd.h @@ -34,6 +34,8 @@ DECLARE_MGROUP(PATHD); +DECLARE_HOOK(pathd_srte_config_write, (struct vty *vty), (vty)); + enum srte_protocol_origin { SRTE_ORIGIN_UNDEFINED = 0, SRTE_ORIGIN_PCEP = 1, diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 2936d1e34..6c007acb5 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -1118,7 +1118,7 @@ static int pbr_interface_config_write(struct vty *vty) pbr_map_write_interfaces(vty, ifp); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } } @@ -1184,6 +1184,7 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty, pbrms_nexthop_group_write_individual_nexthop(vty, pbrms); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); return 1; } diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 6dda66b79..8a9527d7c 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -220,7 +220,7 @@ static int pim_vrf_config_write(struct vty *vty) pim_global_config_write_worker(pim, vty); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); } return 0; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 95882cf58..e4dec9ee8 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -451,7 +451,7 @@ int pim_interface_config_write(struct vty *vty) pim_bfd_write_config(vty, ifp); ++writes; } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); ++writes; } } diff --git a/ripd/ripd.c b/ripd/ripd.c index 3d1427c3b..97edd1c38 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3281,6 +3281,8 @@ static int config_write_rip(struct vty *vty) /* Interface routemap configuration */ config_write_if_rmap(vty, rip->if_rmap_ctx); + vty_out(vty, "exit\n"); + write = 1; } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index cbd2c2289..1f52abd0b 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2270,6 +2270,8 @@ static int ripng_config_write(struct vty *vty) config_write_distribute(vty, ripng->distribute_ctx); config_write_if_rmap(vty, ripng->if_rmap_ctx); + vty_out(vty, "exit\n"); + write = 1; } diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 96e5d37d6..0b3efd0b4 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -164,7 +164,7 @@ static int static_vrf_config_write(struct vty *vty) SAFI_UNICAST, "ipv6 route"); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); } return 0; diff --git a/tests/lib/cli/test_cli.refout.in b/tests/lib/cli/test_cli.refout.in index 8f9959cc4..1f38e08b2 100644 --- a/tests/lib/cli/test_cli.refout.in +++ b/tests/lib/cli/test_cli.refout.in @@ -315,7 +315,6 @@ domainname test.domain !
!
!
-line vty
!
end
test# conf t
@@ -332,7 +331,6 @@ domainname test.domain !
!
!
-line vty
!
end
foohost(config)# diff --git a/tools/frr-reload.py b/tools/frr-reload.py index a326ecc0f..7c6a83a51 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -513,9 +513,6 @@ class Config(object): Parse the configuration and create contexts for each appropriate block """ - current_context_lines = [] - ctx_keys = [] - """ The end of a context is flagged via the 'end' keyword: @@ -574,43 +571,80 @@ end # key of the context. So "router bgp 10" is the key for the non-address # family part of bgp, "router bgp 10, address-family ipv6 unicast" is # the key for the subcontext and so on. + + # This dictionary contains a tree of all commands that we know start a + # new multi-line context. All other commands are treated either as + # commands inside a multi-line context or as single-line contexts. This + # dictionary should be updated whenever a new node is added to FRR. + ctx_keywords = { + "router bgp ": { + "address-family ": { + "vni ": {}, + }, + "vnc ": {}, + "vrf-policy ": {}, + "bmp ": {}, + "segment-routing srv6": {}, + }, + "router rip": {}, + "router ripng": {}, + "router isis ": {}, + "router openfabric ": {}, + "router ospf": {}, + "router ospf6": {}, + "router eigrp ": {}, + "router babel": {}, + "mpls ldp": { + "address-family ": { + "interface ": {} + } + }, + "l2vpn ": { + "member pseudowire ": {} + }, + "key chain ": { + "key ": {} + }, + "vrf ": {}, + "interface ": { + "link-params": {} + }, + "pseudowire ": {}, + "segment-routing": { + "traffic-eng": { + "segment-list ": {}, + "policy ": { + "candidate-path ": {} + }, + "pcep": { + "pcc": {}, + "pce ": {}, + "pce-config ": {} + } + }, + "srv6": { + "locators": { + "locator ": {} + } + } + }, + "nexthop-group ": {}, + "route-map ": {}, + "pbr-map ": {}, + "rpki": {}, + "bfd": { + "peer ": {}, + "profile ": {} + }, + "line vty": {} + } + + # stack of context keys ctx_keys = [] - main_ctx_key = [] - new_ctx = True - - # the keywords that we know are single line contexts. bgp in this case - # is not the main router bgp block, but enabling multi-instance - oneline_ctx_keywords = ( - "access-list ", - "agentx", - "allow-external-route-update", - "bgp ", - "debug ", - "domainname ", - "dump ", - "enable ", - "evpn mh", - "frr ", - "fpm ", - "hostname ", - "ip ", - "ipv6 ", - "log ", - "mac access-list ", - "mpls lsp", - "mpls label", - "no ", - "password ", - "pbr ", - "ptm-enable", - "router-id ", - "service ", - "table ", - "username ", - "vni ", - "vrrp autoconfigure", - "zebra " - ) + # stack of context keywords + cur_ctx_keywords = [ctx_keywords] + # list of stored commands + cur_ctx_lines = [] for line in self.lines: @@ -620,357 +654,77 @@ end if line.startswith("!") or line.startswith("#"): continue - if ( - len(ctx_keys) == 2 - and ctx_keys[0].startswith("bfd") - and ctx_keys[1].startswith("profile ") - and line == "end" - ): - log.debug("LINE %-50s: popping from sub context, %-50s", line, ctx_keys) - - if main_ctx_key: - self.save_contexts(ctx_keys, current_context_lines) - ctx_keys = copy.deepcopy(main_ctx_key) - current_context_lines = [] + if line.startswith("exit"): + # ignore on top level + if len(ctx_keys) == 0: continue - # one line contexts - # there is one exception though: ldpd accepts a 'router-id' clause - # as part of its 'mpls ldp' config context. If we are processing - # ldp configuration and encounter a router-id we should NOT switch - # to a new context - if ( - new_ctx is True - and any(line.startswith(keyword) for keyword in oneline_ctx_keywords) - and not ( - ctx_keys - and ctx_keys[0].startswith("mpls ldp") - and line.startswith("router-id ") - ) - ): - self.save_contexts(ctx_keys, current_context_lines) - - # Start a new context - main_ctx_key = [] - ctx_keys = [ - line, - ] - current_context_lines = [] - - log.debug("LINE %-50s: entering new context, %-50s", line, ctx_keys) - self.save_contexts(ctx_keys, current_context_lines) - new_ctx = True - - elif line == "end": - self.save_contexts(ctx_keys, current_context_lines) - log.debug("LINE %-50s: exiting old context, %-50s", line, ctx_keys) - - # Start a new context - new_ctx = True - main_ctx_key = [] - ctx_keys = [] - current_context_lines = [] - - elif line == "exit" and ctx_keys[0].startswith("rpki"): - self.save_contexts(ctx_keys, current_context_lines) - log.debug("LINE %-50s: exiting old context, %-50s", line, ctx_keys) - - # Start a new context - new_ctx = True - main_ctx_key = [] - ctx_keys = [] - current_context_lines = [] - - elif line == "exit-vrf": - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines.append(line) - log.debug( - "LINE %-50s: append to current_context_lines, %-50s", line, ctx_keys - ) + # save current context + self.save_contexts(ctx_keys, cur_ctx_lines) - # Start a new context - new_ctx = True - main_ctx_key = [] - ctx_keys = [] - current_context_lines = [] + # exit current context + log.debug("LINE %-50s: exit context %-50s", line, ctx_keys) - elif ( - line == "exit" - and len(ctx_keys) > 1 - and ctx_keys[0].startswith("segment-routing") - ): - self.save_contexts(ctx_keys, current_context_lines) - - # Start a new context - ctx_keys = ctx_keys[:-1] - current_context_lines = [] - log.debug( - "LINE %-50s: popping segment routing sub-context to ctx%-50s", - line, - ctx_keys, - ) - - elif line in ["exit-address-family", "exit", "exit-vnc"]: - # if this exit is for address-family ipv4 unicast, ignore the pop - if main_ctx_key: - self.save_contexts(ctx_keys, current_context_lines) - - # Start a new context - ctx_keys = copy.deepcopy(main_ctx_key) - current_context_lines = [] - log.debug( - "LINE %-50s: popping from subcontext to ctx%-50s", - line, - ctx_keys, - ) + ctx_keys.pop() + cur_ctx_keywords.pop() + cur_ctx_lines = [] - elif line in ["exit-vni", "exit-ldp-if"]: - if sub_main_ctx_key: - self.save_contexts(ctx_keys, current_context_lines) - - # Start a new context - ctx_keys = copy.deepcopy(sub_main_ctx_key) - current_context_lines = [] - log.debug( - "LINE %-50s: popping from sub-subcontext to ctx%-50s", - line, - ctx_keys, - ) + continue - elif new_ctx is True: - if not main_ctx_key: - ctx_keys = [ - line, - ] - else: - ctx_keys = copy.deepcopy(main_ctx_key) - main_ctx_key = [] + if line.startswith("end"): + # exit all contexts + while len(ctx_keys) > 0: + # save current context + self.save_contexts(ctx_keys, cur_ctx_lines) - current_context_lines = [] - new_ctx = False - log.debug("LINE %-50s: entering new context, %-50s", line, ctx_keys) + # exit current context + log.debug("LINE %-50s: exit context %-50s", line, ctx_keys) - elif ( - line.startswith("address-family ") - or line.startswith("vnc defaults") - or line.startswith("vnc l2-group") - or line.startswith("vnc nve-group") - or line.startswith("peer") - or line.startswith("key ") - or line.startswith("member pseudowire") - ): - main_ctx_key = [] + ctx_keys.pop() + cur_ctx_keywords.pop() + cur_ctx_lines = [] - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug("LINE %-50s: entering sub-context, append to ctx_keys", line) + continue - if line == "address-family ipv6" and not ctx_keys[0].startswith( - "mpls ldp" - ): - ctx_keys.append("address-family ipv6 unicast") - elif line == "address-family ipv4" and not ctx_keys[0].startswith( - "mpls ldp" - ): - ctx_keys.append("address-family ipv4 unicast") - elif line == "address-family evpn": - ctx_keys.append("address-family l2vpn evpn") - else: + new_ctx = False + + # check if the line is a context-entering keyword + for k, v in cur_ctx_keywords[-1].items(): + if line.startswith(k): + # candidate-path is a special case. It may be a node and + # may be a single-line command. The distinguisher is the + # word "dynamic" or "explicit" at the middle of the line. + # It was perhaps not the best choice by the pathd authors + # but we have what we have. + if k == "candidate-path " and "explicit" in line: + # this is a single-line command + break + + # save current context + self.save_contexts(ctx_keys, cur_ctx_lines) + + # enter new context + new_ctx = True ctx_keys.append(line) + cur_ctx_keywords.append(v) + cur_ctx_lines = [] - elif ( - line.startswith("vni ") - and len(ctx_keys) == 2 - and ctx_keys[0].startswith("router bgp") - and ctx_keys[1] == "address-family l2vpn evpn" - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - sub_main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering sub-sub-context, append to ctx_keys", line - ) - ctx_keys.append(line) - - elif ( - line.startswith("interface ") - and len(ctx_keys) == 2 - and ctx_keys[0].startswith("mpls ldp") - and ctx_keys[1].startswith("address-family") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - sub_main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering sub-sub-context, append to ctx_keys", line - ) - ctx_keys.append(line) - - elif ( - line.startswith("traffic-eng") - and len(ctx_keys) == 1 - and ctx_keys[0].startswith("segment-routing") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - log.debug( - "LINE %-50s: entering segment routing sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) - - elif ( - line.startswith("segment-list ") - and len(ctx_keys) == 2 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - log.debug( - "LINE %-50s: entering segment routing sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) - - elif ( - line.startswith("policy ") - and len(ctx_keys) == 2 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - log.debug( - "LINE %-50s: entering segment routing sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) - - elif ( - line.startswith("candidate-path ") - and line.endswith(" dynamic") - and len(ctx_keys) == 3 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - and ctx_keys[2].startswith("policy") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering candidate-path sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) - - elif ( - line.startswith("pcep") - and len(ctx_keys) == 2 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering pcep sub-context, append to ctx_keys", line - ) - ctx_keys.append(line) - - elif ( - line.startswith("pce-config ") - and len(ctx_keys) == 3 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - and ctx_keys[2].startswith("pcep") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering pce-config sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) - - elif ( - line.startswith("pce ") - and len(ctx_keys) == 3 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - and ctx_keys[2].startswith("pcep") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering pce sub-context, append to ctx_keys", line - ) - ctx_keys.append(line) - - elif ( - line.startswith("pcc") - and len(ctx_keys) == 3 - and ctx_keys[0].startswith("segment-routing") - and ctx_keys[1].startswith("traffic-eng") - and ctx_keys[2].startswith("pcep") - ): - - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering pcc sub-context, append to ctx_keys", line - ) - ctx_keys.append(line) - - elif ( - line.startswith("profile ") - and len(ctx_keys) == 1 - and ctx_keys[0].startswith("bfd") - ): + log.debug("LINE %-50s: enter context %-50s", line, ctx_keys) + break - # Save old context first - self.save_contexts(ctx_keys, current_context_lines) - current_context_lines = [] - main_ctx_key = copy.deepcopy(ctx_keys) - log.debug( - "LINE %-50s: entering BFD profile sub-context, append to ctx_keys", - line, - ) - ctx_keys.append(line) + if new_ctx: + continue + if len(ctx_keys) == 0: + log.debug("LINE %-50s: single-line context", line) + self.save_contexts([line], []) else: - # Continuing in an existing context, add non-commented lines to it - current_context_lines.append(line) - log.debug( - "LINE %-50s: append to current_context_lines, %-50s", line, ctx_keys - ) + log.debug("LINE %-50s: add to current context %-50s", line, ctx_keys) + cur_ctx_lines.append(line) # Save the context of the last one - self.save_contexts(ctx_keys, current_context_lines) + if len(ctx_keys) > 0: + self.save_contexts(ctx_keys, cur_ctx_lines) def lines_to_config(ctx_keys, line, delete): diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index d22ec3113..2e1d7c5ba 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -272,16 +272,11 @@ void vtysh_config_parse_line(void *arg, const char *line) strlen(" ip igmp query-interval")) == 0) { config_add_line_uniq_end(config->line, line); } else if (config->index == LINK_PARAMS_NODE - && strncmp(line, " exit-link-params", - strlen(" exit")) + && strncmp(line, " exit-link-params", + strlen(" exit")) == 0) { config_add_line(config->line, line); config->index = INTERFACE_NODE; - } else if (config->index == VRF_NODE - && strncmp(line, " exit-vrf", - strlen(" exit-vrf")) - == 0) { - config_add_line_uniq_end(config->line, line); } else if (!strncmp(line, " vrrp", strlen(" vrrp")) || !strncmp(line, " no vrrp", strlen(" no vrrp"))) { @@ -300,7 +295,10 @@ void vtysh_config_parse_line(void *arg, const char *line) config_add_line(config_top, line); break; default: - if (strncmp(line, "interface", strlen("interface")) == 0) + if (strncmp(line, "exit", strlen("exit")) == 0) { + if (config) + config_add_line_uniq_end(config->line, line); + } else if (strncmp(line, "interface", strlen("interface")) == 0) config = config_get(INTERFACE_NODE, line); else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0) config = config_get(PW_NODE, line); @@ -496,7 +494,9 @@ void vtysh_config_dump(void) * are not under the VRF node. */ if (config->index == INTERFACE_NODE - && list_isempty(config->line)) { + && (listcount(config->line) == 1) + && (line = listnode_head(config->line)) + && strmatch(line, "exit")) { config_del(config); continue; } diff --git a/zebra/interface.c b/zebra/interface.c index 21eeb2054..18f7503f8 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -4096,7 +4096,7 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp) if (IS_PARAM_SET(iflp, LP_RMT_AS)) vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip, iflp->rmt_as); - vty_out(vty, " exit-link-params\n"); + vty_out(vty, " exit-link-params\n"); return 0; } @@ -4188,7 +4188,7 @@ static int if_config_write(struct vty *vty) zebra_evpn_mh_if_write(vty, ifp); link_params_config_write(vty, ifp); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; } diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 6b4a81515..d5083d4cb 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -836,6 +836,7 @@ static int zebra_pw_config(struct vty *vty) if (!(pw->flags & F_PSEUDOWIRE_CWORD)) vty_out(vty, " control-word exclude\n"); + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); write = 1; } diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index 97935f126..d2b91b6c0 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -320,10 +320,14 @@ static int zebra_sr_config(struct vty *vty) vty_out(vty, " locator %s\n", locator->name); vty_out(vty, " prefix %s/%u\n", str, locator->prefix.prefixlen); + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index a2a671e95..1c5fddae0 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -524,7 +524,7 @@ static int vrf_config_write(struct vty *vty) router_id_write(vty, zvrf); if (zvrf_id(zvrf) != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); else vty_out(vty, "!\n"); } |