From ae19d7dd48477ea14dcadb94f07374a5fb2b5fda Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Thu, 20 Oct 2016 20:31:24 +0000 Subject: [PATCH] lib: Add helper function for working with argv, update bgpd to use it Signed-off-by: Quentin Young --- bgpd/bgp_route.c | 261 +++++++++++++++++++++++++++++------------------ bgpd/bgp_vty.c | 199 ++++++++++++++++++++++-------------- lib/command.c | 20 ++++ lib/command.h | 1 + 4 files changed, 304 insertions(+), 177 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6362b48b54..b03b296ea8 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8015,7 +8015,20 @@ bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str, /* BGP route print out function. */ DEFUN (show_ip_bgp_ipv4, show_ip_bgp_ipv4_cmd, - "show [ip] bgp [ WORD] [] [|route-map WORD|prefix-list WORD|filter-list WORD|community [exact-match]|community-list <(1-500)|WORD> [exact-match]|A.B.C.D/M longer-prefixes|X:X::X:X/M longer-prefixes>] [json]", + "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>]\ + [<\ + cidr-only\ + |community\ + |dampening \ + |route-map WORD\ + |prefix-list WORD\ + |filter-list WORD\ + |community [exact-match]\ + |community-list <(1-500)|WORD> [exact-match]\ + |A.B.C.D/M longer-prefixes\ + |X:X::X:X/M longer-prefixes\ + >]\ + [json]", SHOW_STR IP_STR BGP_STR @@ -8056,92 +8069,108 @@ DEFUN (show_ip_bgp_ipv4, "Display route and more specific routes\n" "JavaScript Object Notation\n") { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_afi; - int idx_safi; - int idx_sh_type; - int exact_match = 0; char *vrf = NULL; - afi_t afi; - safi_t safi; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int exact_match; enum bgp_show_type sh_type = bgp_show_type_normal; - struct bgp *bgp; - u_char uj = use_json(argc, argv); - vrf = bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_afi); - idx_safi = idx_afi + 1; - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, &idx_sh_type); + int idx = 0; - bgp = bgp_lookup_by_name (vrf); + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } + + int uj = use_json (argc, argv); + if (uj) argc--; + + struct bgp *bgp = bgp_lookup_by_name (vrf); if (bgp == NULL) { vty_out (vty, "Can't find BGP instance %s%s", vrf, VTY_NEWLINE); return CMD_WARNING; } - if (strmatch(argv[idx_sh_type]->text, "cidr-only")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); + if (++idx < argc) + { + if (strmatch(argv[idx]->text, "cidr-only")) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); - else if (strmatch(argv[idx_sh_type]->text, "dampening")) - { - if (strmatch(argv[idx_sh_type + 1]->text, "dampened-paths")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); - - else if (strmatch(argv[idx_sh_type + 1]->text, "flap-statistics")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); - } - - else if (strmatch(argv[idx_sh_type]->text, "dampened-paths")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); - - else if (strmatch(argv[idx_sh_type]->text, "flap-statistics")) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); - - else if (strmatch(argv[idx_sh_type]->text, "regexp")) - return bgp_show_regexp (vty, argc, argv, afi, safi, bgp_show_type_regexp); - - else if (strmatch(argv[idx_sh_type]->text, "prefix-list")) - return bgp_show_prefix_list (vty, vrf, argv[idx_sh_type + 1]->arg, afi, safi, bgp_show_type_prefix_list); - - else if (strmatch(argv[idx_sh_type]->text, "filter-list")) - return bgp_show_filter_list (vty, vrf, argv[idx_sh_type + 1]->arg, afi, safi, bgp_show_type_filter_list); - - else if (strmatch(argv[idx_sh_type]->text, "route-map")) - return bgp_show_route_map (vty, vrf, argv[idx_sh_type + 1]->arg, afi, safi, bgp_show_type_route_map); - - else if (strmatch(argv[idx_sh_type]->text, "community")) - /* show a specific community */ - if (argv[idx_sh_type + 1]->type == VARIABLE_TKN || - strmatch(argv[idx_sh_type + 1]->text, "local-AS") || - strmatch(argv[idx_sh_type + 1]->text, "no-advertise") || - strmatch(argv[idx_sh_type + 1]->text, "no-export")) + else if (strmatch(argv[idx]->text, "dampening")) { - if (strmatch(argv[idx_sh_type + 2]->text, "exact_match")) - exact_match = 1; - return bgp_show_community (vty, vrf, argc, argv, exact_match, afi, safi); + if (strmatch(argv[idx + 1]->text, "dampened-paths")) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); + + else if (strmatch(argv[idx + 1]->text, "flap-statistics")) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); } - /* show all communities */ - else - return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); - else if (strmatch(argv[idx_sh_type]->text, "community-list")) + else if (strmatch(argv[idx]->text, "dampened-paths")) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); + + else if (strmatch(argv[idx]->text, "flap-statistics")) + return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); + + else if (strmatch(argv[idx]->text, "regexp")) + return bgp_show_regexp (vty, argc, argv, afi, safi, bgp_show_type_regexp); + + else if (strmatch(argv[idx]->text, "prefix-list")) + return bgp_show_prefix_list (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list); + + else if (strmatch(argv[idx]->text, "filter-list")) + return bgp_show_filter_list (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); + + else if (strmatch(argv[idx]->text, "route-map")) + return bgp_show_route_map (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); + + else if (strmatch(argv[idx]->text, "community")) { - if (strmatch(argv[idx_sh_type + 2]->text, "exact_match")) - exact_match = 1; - return bgp_show_community_list (vty, vrf, argv[idx_sh_type + 1]->arg, exact_match, afi, safi); + /* show a specific community */ + if (argv[idx + 1]->type == VARIABLE_TKN || + strmatch(argv[idx + 1]->text, "local-AS") || + strmatch(argv[idx + 1]->text, "no-advertise") || + strmatch(argv[idx + 1]->text, "no-export")) + { + if (strmatch(argv[idx + 2]->text, "exact_match")) + exact_match = 1; + return bgp_show_community (vty, vrf, argc, argv, exact_match, afi, safi); + } + /* show all communities */ + else + return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); } - - /* prefix-longer */ - else if (argv[idx_sh_type]->type == IPV4_TKN || argv[idx_sh_type]->type == IPV6_TKN) - return bgp_show_prefix_longer (vty, vrf, argv[idx_sh_type + 1]->arg, afi, safi, bgp_show_type_prefix_longer); + else if (strmatch(argv[idx]->text, "community-list")) + { + if (strmatch(argv[idx + 2]->text, "exact_match")) + exact_match = 1; + return bgp_show_community_list (vty, vrf, argv[idx + 1]->arg, exact_match, afi, safi); + } + /* prefix-longer */ + else if (argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV6_TKN) + return bgp_show_prefix_longer (vty, vrf, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_longer); + } return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj); } DEFUN (show_ip_bgp_route, show_ip_bgp_route_cmd, - "show [ip] bgp [ WORD] [] [] [json]", + "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>]" + " [] [json]", SHOW_STR IP_STR BGP_STR @@ -8165,68 +8194,102 @@ DEFUN (show_ip_bgp_route, "Display only multipaths\n" "JavaScript Object Notation\n") { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_afi; - int idx_safi; - int idx_prefix; - int idx_path_type; int prefix_check = 0; + + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; char *vrf = NULL; - afi_t afi; - safi_t safi; + char *prefix = NULL; + enum bgp_path_type path_type; - struct prefix_rd prd; - struct prefix_rd *prd_ptr = NULL; u_char uj = use_json(argc, argv); - vrf = bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_afi); - idx_safi = idx_afi + 1; - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, &idx_prefix); + int idx = 0; - if (strmatch(argv[idx_afi]->text, "encap") && strmatch(argv[idx_safi + 1]->text, "rd")) - { - str2prefix_rd (argv[idx_safi + 2]->arg, &prd); - prd_ptr = &prd; - } + /* show [ip] bgp */ + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ WORD] */ + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } - if (argv[idx_prefix]->type == IPV4_TKN || argv[idx_prefix]->type == IPV6_TKN) + /* */ + if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx)) prefix_check = 0; - else if (argv[idx_prefix]->type == IPV4_PREFIX_TKN || argv[idx_prefix]->type == IPV6_PREFIX_TKN) + else if (argv_find (argv, argc, "A.B.C.D/M", &idx) || argv_find (argv, argc, "X:X::X:X/M", &idx)) prefix_check = 1; - idx_path_type = idx_prefix + 1; + if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) && afi != AFI_IP6) + { + vty_out (vty, "%% Cannot specify IPv6 address or prefix with IPv4 AFI%s", VTY_NEWLINE); + return CMD_WARNING; + } + if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) && afi != AFI_IP) + { + vty_out (vty, "%% Cannot specify IPv4 address or prefix with IPv6 AFI%s", VTY_NEWLINE); + return CMD_WARNING; + } - if (strmatch(argv[idx_path_type]->text, "bestpath")) + prefix = argv[idx]->arg; + + /* [] */ + if (argv_find (argv, argc, "bestpath", &idx)) path_type = BGP_PATH_BESTPATH; - else if (strmatch(argv[idx_path_type]->text, "bestpath")) + else if (argv_find (argv, argc, "multipath", &idx)) path_type = BGP_PATH_MULTIPATH; else path_type = BGP_PATH_ALL; - return bgp_show_route (vty, vrf, argv[idx_prefix]->arg, afi, safi, prd_ptr, prefix_check, path_type, uj); + return bgp_show_route (vty, vrf, prefix, afi, safi, NULL, prefix_check, path_type, uj); } DEFUN (show_ip_bgp_instance_all, show_ip_bgp_instance_all_cmd, - "show [ip] bgp all [] [json]", + "show [ip] bgp all []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_ALL_HELP_STR "JavaScript Object Notation\n") { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_afi; - int idx_safi; - afi_t afi; - safi_t safi; + afi_t afi = AFI_IP; + safi_t safi = SAFI_UNICAST; + + int idx = 0; + + /* show [ip] bgp */ + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } u_char uj = use_json(argc, argv); - bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_afi); - idx_safi = idx_afi + 1; - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, NULL); bgp_show_all_instances_routes_vty (vty, afi, safi, uj); return CMD_SUCCESS; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 0f8d0c76dd..cd61252a0c 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -5969,7 +5969,7 @@ bgp_get_argv_afi_safi (int argc, struct cmd_token **argv, /* one clear bgp command to rule them all */ DEFUN (clear_ip_bgp_all, clear_ip_bgp_all_cmd, - "clear [ip] bgp [ WORD] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [] []|in [prefix-filter]|out>]", + "clear [ip] bgp [ WORD] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] []|in [prefix-filter]|out>]", CLEAR_STR IP_STR BGP_STR @@ -6002,63 +6002,57 @@ DEFUN (clear_ip_bgp_all, BGP_SOFT_IN_STR BGP_SOFT_OUT_STR) { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_clr_sort = 5; - int idx_soft_in_out; - int idx_afi; - int idx_safi; char *vrf = NULL; - afi_t afi; - safi_t safi; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; enum clear_sort clr_sort = clear_peer; enum bgp_clear_type clr_type; char *clr_arg = NULL; - vrf = bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_clr_sort); + int idx = 0; - /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external> */ - if (strmatch(argv[idx_clr_sort]->text, "*")) + /* clear [ip] bgp */ + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ WORD] */ + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + { + vrf = argv[idx + 1]->arg; + idx += 2; + } + /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> */ + if (argv_find (argv, argc, "*", &idx)) { clr_sort = clear_all; } - else if (argv[idx_clr_sort]->type == IPV4_TKN) + else if (argv_find (argv, argc, "A.B.C.D", &idx)) { clr_sort = clear_peer; - clr_arg = argv[idx_clr_sort]->arg; + clr_arg = argv[idx]->arg; } - else if (argv[idx_clr_sort]->type == IPV6_TKN) + else if (argv_find (argv, argc, "X:X::X:X", &idx)) { clr_sort = clear_peer; - clr_arg = argv[idx_clr_sort]->arg; + clr_arg = argv[idx]->arg; } - else if (argv[idx_clr_sort]->type == RANGE_TKN) - { - clr_sort = clear_as; - clr_arg = argv[idx_clr_sort]->arg; - } - else if (strmatch(argv[idx_clr_sort]->text, "external")) - { - clr_sort = clear_external; - } - else if (strmatch(argv[idx_clr_sort]->text, "peer-group")) + else if (argv_find (argv, argc, "peer-group", &idx)) { clr_sort = clear_group; - idx_clr_sort++; - clr_arg = argv[idx_clr_sort]->arg; + idx++; + clr_arg = argv[idx]->arg; if (! peer_group_lookup (vty->index, clr_arg)) { vty_out (vty, "%% No such peer-group%s", VTY_NEWLINE); - return CMD_WARNING; + return CMD_WARNING; } } - else if (argv[idx_clr_sort]->type == WORD_TKN) + else if (argv_find (argv, argc, "WORD", &idx)) { - if (peer_lookup_by_conf_if (vty->index, argv[idx_clr_sort]->arg)) + if (peer_lookup_by_conf_if (vty->index, argv[idx]->arg)) { clr_sort = clear_peer; - clr_arg = argv[idx_clr_sort]->arg; + clr_arg = argv[idx]->arg; } else { @@ -6066,27 +6060,47 @@ DEFUN (clear_ip_bgp_all, return CMD_WARNING; } } - - /* afi safi */ - idx_afi = idx_clr_sort + 1; - idx_safi = idx_clr_sort + 2; - idx_soft_in_out = 0; - if (argc > idx_afi) - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, &idx_soft_in_out); - - clr_type = BGP_CLEAR_SOFT_NONE; - if (idx_soft_in_out && argc > idx_soft_in_out) - { - /* soft, soft in, or soft out */ - if (strmatch(argv[idx_soft_in_out]->text, "in")) - clr_type = BGP_CLEAR_SOFT_IN; - else if (strmatch(argv[idx_soft_in_out]->text, "out")) + else if (argv_find (argv, argc, "(1-4294967295)", &idx)) + { + clr_sort = clear_as; + clr_arg = argv[idx]->arg; + } + else if (argv_find (argv, argc, "external", &idx)) + { + clr_sort = clear_external; + } + /* []|ipv6 []|encap [unicast]||vpnv4 [unicast]>] */ + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } + /* []|in [prefix-filter]|out>] */ + if (argv_find (argv, argc, "soft", &idx)) + { + if (argv_find (argv, argc, "in", &idx) || argv_find (argv, argc, "out", &idx)) + clr_type = strmatch (argv[idx]->text, "in") ? BGP_CLEAR_SOFT_IN : BGP_CLEAR_SOFT_OUT; + else + clr_type = BGP_CLEAR_SOFT_BOTH; + } + else if (argv_find (argv, argc, "in", &idx)) + { + clr_type = argv_find (argv, argc, "prefix-filter", &idx) ? BGP_CLEAR_SOFT_IN_ORF_PREFIX : BGP_CLEAR_SOFT_IN; + } + else if (argv_find (argv, argc, "out", &idx)) + { clr_type = BGP_CLEAR_SOFT_OUT; - else if (strmatch(argv[idx_soft_in_out]->text, "soft")) - clr_type = BGP_CLEAR_SOFT_BOTH; - else if (strmatch(argv[idx_soft_in_out]->text, "prefix-filter")) - clr_type = BGP_CLEAR_SOFT_IN_ORF_PREFIX; - } + } + else + clr_type = BGP_CLEAR_SOFT_NONE; return bgp_clear_vty (vty, vrf, afi, safi, clr_sort, clr_type, clr_arg); } @@ -6843,7 +6857,7 @@ bgp_show_summary_vty (struct vty *vty, const char *name, /* `show ip bgp summary' commands. */ DEFUN (show_ip_bgp_summary, show_ip_bgp_summary_cmd, - "show [ip] bgp [ WORD] [] summary [json]", + "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] summary [json]", SHOW_STR IP_STR BGP_STR @@ -6861,18 +6875,33 @@ DEFUN (show_ip_bgp_summary, "Summary of BGP neighbor status\n" "JavaScript Object Notation\n") { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_afi; - int idx_safi; char *vrf = NULL; - afi_t afi; - safi_t safi; - u_char uj = use_json(argc, argv); + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; - vrf = bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_afi); - idx_safi = idx_afi + 1; - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, NULL); + int idx = 0; + + /* show [ip] bgp */ + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ WORD] */ + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } + int uj = use_json (argc, argv); return bgp_show_summary_vty (vty, vrf, afi, safi, uj); } @@ -8889,7 +8918,7 @@ bgp_show_update_groups(struct vty *vty, const char *name, DEFUN (show_ip_bgp_updgrps, show_ip_bgp_updgrps_cmd, - "show [ip] bgp [ WORD] [] update-groups [SUBGROUP-ID]", + "show [ip] bgp [ WORD] []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] update-groups [SUBGROUP-ID]", SHOW_STR IP_STR BGP_STR @@ -8907,24 +8936,38 @@ DEFUN (show_ip_bgp_updgrps, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - int idx_view_vrf = 3; - int idx_vrf = 4; - int idx_afi; - int idx_safi; - int idx_updgrp; - int idx_subgroup_id; char *vrf = NULL; - afi_t afi; - safi_t safi; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; uint64_t subgrp_id = 0; - vrf = bgp_get_argv_vrf (argc, argv, &afi, &safi, &idx_view_vrf, &idx_vrf, &idx_afi); - idx_safi = idx_afi + 1; - bgp_get_argv_afi_safi (argc, argv, idx_afi, idx_safi, &afi, &safi, &idx_updgrp); - idx_subgroup_id = idx_updgrp + 1; + int idx = 0; - if (! strmatch(argv[idx_subgroup_id]->text, "update-groups")) - VTY_GET_ULL("subgroup-id", subgrp_id, argv[idx_subgroup_id]->arg); + /* show [ip] bgp */ + if (argv_find (argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ WORD] */ + if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + /* []|ipv6 []|encap [unicast]|vpnv4 [unicast]>] */ + if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) + { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) + safi = strmatch (argv[idx]->text, "unicast") ? SAFI_UNICAST : SAFI_MULTICAST; + } + else if (argv_find (argv, argc, "encap", &idx) || argv_find (argv, argc, "vpnv4", &idx)) + { + afi = AFI_IP; + safi = strmatch (argv[idx]->text, "encap") ? SAFI_ENCAP : SAFI_MPLS_VPN; + // advance idx if necessary + argv_find (argv, argc, "unicast", &idx); + } + + /* get subgroup id, if provided */ + idx = argc - 1; + if (argv[idx]->type == VARIABLE_TKN) + VTY_GET_ULL("subgroup-id", subgrp_id, argv[idx]->arg); return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id)); } diff --git a/lib/command.c b/lib/command.c index 914641724f..3416bcd1c7 100644 --- a/lib/command.c +++ b/lib/command.c @@ -193,6 +193,26 @@ argv_concat (struct cmd_token **argv, int argc, int shift) return str; } +/** + * Convenience function for accessing argv data. + * + * @param argc + * @param argv + * @param text definition snippet of the desired token + * @param index the starting index, and where to store the + * index of the found token if it exists + * @return 1 if found, 0 otherwise + */ +int +argv_find (struct cmd_token **argv, int argc, const char *text, int *index) +{ + int found = 0; + for (int i = *index; i < argc && found == 0; i++) + if ((found = strmatch (text, argv[i]->text))) + *index = i; + return found; +} + /* Install top node of command vector. */ void install_node (struct cmd_node *node, diff --git a/lib/command.h b/lib/command.h index aad0c6b3e6..0e2d27f19c 100644 --- a/lib/command.h +++ b/lib/command.h @@ -408,6 +408,7 @@ extern void install_element (enum node_type, struct cmd_element *); string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ extern char *argv_concat (struct cmd_token **argv, int argc, int shift); +extern int argv_find (struct cmd_token **argv, int argc, const char *text, int *index); extern vector cmd_make_strvec (const char *); extern void cmd_free_strvec (vector);