diff options
Diffstat (limited to 'bgpd/bgp_vty.c')
-rw-r--r-- | bgpd/bgp_vty.c | 445 |
1 files changed, 433 insertions, 12 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6d23af03e..0797756f6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -41,6 +41,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_community.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_damp.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_fsm.h" @@ -3748,13 +3749,15 @@ DEFUN (no_neighbor_send_community, /* neighbor send-community extended. */ DEFUN (neighbor_send_community_type, neighbor_send_community_type_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|extended|standard>", + "neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n" "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" "Send Extended Community attributes\n" - "Send Standard Community attributes\n") + "Send Standard Community attributes\n" + "Send Large Community attributes\n") { int idx = 0; u_int32_t flag = 0; @@ -3765,25 +3768,35 @@ DEFUN (neighbor_send_community_type, SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); else if (argv_find (argv, argc, "extended", &idx)) SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + else if (argv_find (argv, argc, "large", &idx)) + SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + else if (argv_find (argv, argc, "both", &idx)) + { + SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + } else - { - SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); - } + { + SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + } return peer_af_flag_set_vty (vty, peer, bgp_node_afi (vty), bgp_node_safi (vty), flag); } DEFUN (no_neighbor_send_community_type, no_neighbor_send_community_type_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|extended|standard>", + "no neighbor <A.B.C.D|X:X::X:X|WORD> send-community <both|all|extended|standard|large>", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n" "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" "Send Extended Community attributes\n" - "Send Standard Community attributes\n") + "Send Standard Community attributes\n" + "Send Large Community attributes\n") { int idx_peer = 2; int idx_type = 4; @@ -3795,11 +3808,21 @@ DEFUN (no_neighbor_send_community_type, return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), bgp_node_safi (vty), PEER_FLAG_SEND_EXT_COMMUNITY); + if (strncmp (argv[idx_type]->arg, "l", 1) == 0) + return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_SEND_LARGE_COMMUNITY); + if (strncmp (argv[idx_type]->arg, "b", 1) == 0) + return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_SEND_COMMUNITY | + PEER_FLAG_SEND_EXT_COMMUNITY); return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), bgp_node_safi (vty), (PEER_FLAG_SEND_COMMUNITY | - PEER_FLAG_SEND_EXT_COMMUNITY)); + PEER_FLAG_SEND_EXT_COMMUNITY| + PEER_FLAG_SEND_LARGE_COMMUNITY)); } /* neighbor soft-reconfig. */ @@ -6132,6 +6155,12 @@ DEFUN (show_bgp_memory, mtype_memstr (memstrbuf, sizeof (memstrbuf), count * sizeof (struct ecommunity)), VTY_NEWLINE); + if ((count = mtype_stats_alloc (MTYPE_LCOMMUNITY))) + vty_out (vty, "%ld BGP large-community entries, using %s of memory%s", + count, + mtype_memstr (memstrbuf, sizeof (memstrbuf), + count * sizeof (struct lcommunity)), + VTY_NEWLINE); if ((count = mtype_stats_alloc (MTYPE_CLUSTER))) vty_out (vty, "%ld Cluster lists, using %s of memory%s", count, @@ -7109,12 +7138,16 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) vty_out (vty, " MED is propagated unchanged to this neighbor%s", VTY_NEWLINE); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) + || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) + || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) { vty_out (vty, " Community attribute sent to this neighbor"); if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, "(both)%s", VTY_NEWLINE); + && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) + && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out (vty, "(all)%s", VTY_NEWLINE); + else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out (vty, "(large)%s", VTY_NEWLINE); else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) vty_out (vty, "(extended)%s", VTY_NEWLINE); else @@ -8637,6 +8670,36 @@ DEFUN (show_ip_bgp_community_info, return CMD_SUCCESS; } +static void +lcommunity_show_all_iterator (struct hash_backet *backet, struct vty *vty) +{ + struct lcommunity *lcom; + + lcom = (struct lcommunity *) backet->data; + vty_out (vty, "[%p] (%ld) %s%s", (void *)backet, lcom->refcnt, + lcommunity_str (lcom), VTY_NEWLINE); +} + +/* Show BGP's community internal data. */ +DEFUN (show_ip_bgp_lcommunity_info, + show_ip_bgp_lcommunity_info_cmd, + "show ip bgp large-community-info", + SHOW_STR + IP_STR + BGP_STR + "List all bgp large-community information\n") +{ + vty_out (vty, "Address Refcnt Large-community%s", VTY_NEWLINE); + + hash_iterate (lcommunity_hash (), + (void (*) (struct hash_backet *, void *)) + lcommunity_show_all_iterator, + vty); + + return CMD_SUCCESS; +} + + DEFUN (show_ip_bgp_attr_info, show_ip_bgp_attr_info_cmd, "show [ip] bgp attribute-info", @@ -10738,6 +10801,8 @@ bgp_vty_init (void) /* "show [ip] bgp community" commands. */ install_element (VIEW_NODE, &show_ip_bgp_community_info_cmd); + /* "show ip bgp large-community" commands. */ + install_element (VIEW_NODE, &show_ip_bgp_lcommunity_info_cmd); /* "show [ip] bgp attribute-info" commands. */ install_element (VIEW_NODE, &show_ip_bgp_attr_info_cmd); @@ -11070,6 +11135,324 @@ DEFUN (show_ip_community_list_arg, return CMD_SUCCESS; } +/* + * Large Community code. + */ +static int +lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, + int style, int reject_all_digit_name) +{ + int ret; + int direct; + char *str; + int idx = 0; + char *cl_name; + + direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; + + /* All digit name check. */ + idx = 0; + argv_find (argv, argc, "WORD", &idx); + argv_find (argv, argc, "(1-99)", &idx); + argv_find (argv, argc, "(100-500)", &idx); + cl_name = argv[idx]->arg; + if (reject_all_digit_name && all_digit (cl_name)) + { + vty_out (vty, "%% Community name cannot have all digits%s", VTY_NEWLINE); + return CMD_WARNING; + } + + argv_find (argv, argc, "AA:BB:CC", &idx); + argv_find (argv, argc, "LINE", &idx); + /* Concat community string argument. */ + if (idx) + str = argv_concat (argv, argc, idx); + else + str = NULL; + + ret = lcommunity_list_set (bgp_clist, cl_name, str, direct, style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE (MTYPE_TMP, str); + + if (ret < 0) + { + community_list_perror (vty, ret); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +static int +lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, + int style) +{ + int ret; + int direct = 0; + char *str = NULL; + int idx = 0; + + argv_find (argv, argc, "permit", &idx); + argv_find (argv, argc, "deny", &idx); + + if (idx) + { + /* Check the list direct. */ + if (strncmp (argv[idx]->arg, "p", 1) == 0) + direct = COMMUNITY_PERMIT; + else + direct = COMMUNITY_DENY; + + idx = 0; + argv_find (argv, argc, "LINE", &idx); + argv_find (argv, argc, "AA:AA:NN", &idx); + /* Concat community string argument. */ + str = argv_concat (argv, argc, idx); + } + + idx = 0; + argv_find (argv, argc, "(1-99)", &idx); + argv_find (argv, argc, "(100-500)", &idx); + argv_find (argv, argc, "WORD", &idx); + + /* Unset community list. */ + ret = lcommunity_list_unset (bgp_clist, argv[idx]->arg, str, direct, style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE (MTYPE_TMP, str); + + if (ret < 0) + { + community_list_perror (vty, ret); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +/* "large-community-list" keyword help string. */ +#define LCOMMUNITY_LIST_STR "Add a large community list entry\n" +#define LCOMMUNITY_VAL_STR "large community in 'aa:bb:cc' format\n" + +DEFUN (ip_lcommunity_list_standard, + ip_lcommunity_list_standard_cmd, + "ip large-community-list (1-99) <deny|permit> [AA:BB:CC...]", + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 0); +} + +DEFUN (ip_lcommunity_list_expanded, + ip_lcommunity_list_expanded_cmd, + "ip large-community-list (100-500) <deny|permit> LINE...", + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 0); +} + +DEFUN (ip_lcommunity_list_name_standard, + ip_lcommunity_list_name_standard_cmd, + "ip large-community-list standard WORD <deny|permit> [AA:BB.CC...]", + IP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 1); +} + +DEFUN (ip_lcommunity_list_name_expanded, + ip_lcommunity_list_name_expanded_cmd, + "ip large-community-list expanded WORD <deny|permit> LINE...", + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 1); +} + +DEFUN (no_ip_lcommunity_list_standard_all, + no_ip_lcommunity_list_standard_all_cmd, + "no ip large-community-list <(1-99)|(100-500)|WORD>", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Large Community list number (expanded)\n" + "Large Community list name\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_name_expanded_all, + no_ip_lcommunity_list_name_expanded_all_cmd, + "no ip large-community-list expanded WORD", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +DEFUN (no_ip_lcommunity_list_standard, + no_ip_lcommunity_list_standard_cmd, + "no ip large-community-list (1-99) <deny|permit> AA:AA:NN...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_expanded, + no_ip_lcommunity_list_expanded_cmd, + "no ip large-community-list (100-500) <deny|permit> LINE...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +DEFUN (no_ip_lcommunity_list_name_standard, + no_ip_lcommunity_list_name_standard_cmd, + "no ip large-community-list standard WORD <deny|permit> AA:AA:NN...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); +} + +DEFUN (no_ip_lcommunity_list_name_expanded, + no_ip_lcommunity_list_name_expanded_cmd, + "no ip large-community-list expanded WORD <deny|permit> LINE...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") +{ + return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); +} + +static void +lcommunity_list_show (struct vty *vty, struct community_list *list) +{ + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) + { + if (entry == list->head) + { + if (all_digit (list->name)) + vty_out (vty, "Large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "(expanded) access", + list->name, VTY_NEWLINE); + else + vty_out (vty, "Named large community %s list %s%s", + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + "standard" : "expanded", + list->name, VTY_NEWLINE); + } + if (entry->any) + vty_out (vty, " %s%s", + community_direct_str (entry->direct), VTY_NEWLINE); + else + vty_out (vty, " %s %s%s", + community_direct_str (entry->direct), + entry->style == EXTCOMMUNITY_LIST_STANDARD ? + entry->u.ecom->str : entry->config, + VTY_NEWLINE); + } +} + +DEFUN (show_ip_lcommunity_list, + show_ip_lcommunity_list_cmd, + "show ip large-community-list", + SHOW_STR + IP_STR + "List large-community list\n") +{ + struct community_list *list; + struct community_list_master *cm; + + cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); + if (! cm) + return CMD_SUCCESS; + + for (list = cm->num.head; list; list = list->next) + lcommunity_list_show (vty, list); + + for (list = cm->str.head; list; list = list->next) + lcommunity_list_show (vty, list); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_lcommunity_list_arg, + show_ip_lcommunity_list_arg_cmd, + "show ip large-community-list <(1-500)|WORD>", + SHOW_STR + IP_STR + "List large-community list\n" + "large-community-list number\n" + "large-community-list name\n") +{ + struct community_list *list; + + list = community_list_lookup (bgp_clist, argv[3]->arg, LARGE_COMMUNITY_LIST_MASTER); + if (! list) + { + vty_out (vty, "%% Can't find extcommunity-list%s", VTY_NEWLINE); + return CMD_WARNING; + } + + lcommunity_list_show (vty, list); + + return CMD_SUCCESS; +} + /* "extcommunity-list" keyword help string. */ #define EXTCOMMUNITY_LIST_STR "Add a extended community list entry\n" #define EXTCOMMUNITY_VAL_STR "Extended community attribute in 'rt aa:nn_or_IPaddr:nn' OR 'soo aa:nn_or_IPaddr:nn' format\n" @@ -11379,6 +11762,30 @@ community_list_config_write (struct vty *vty) community_list_config_str (entry), VTY_NEWLINE); write++; } + + + /* lcommunity-list. */ + cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); + + for (list = cm->num.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) + { + vty_out (vty, "ip large-community-list %s %s %s%s", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; + } + for (list = cm->str.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) + { + vty_out (vty, "ip large-community-list %s %s %s %s%s", + entry->style == LARGE_COMMUNITY_LIST_STANDARD + ? "standard" : "expanded", + list->name, community_direct_str (entry->direct), + community_list_config_str (entry), VTY_NEWLINE); + write++; + } + return write; } @@ -11409,4 +11816,18 @@ community_list_vty (void) install_element (CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_cmd); install_element (VIEW_NODE, &show_ip_extcommunity_list_cmd); install_element (VIEW_NODE, &show_ip_extcommunity_list_arg_cmd); + + /* Large Community List */ + install_element (CONFIG_NODE, &ip_lcommunity_list_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); + install_element (CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_all_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_expanded_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_standard_cmd); + install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_cmd); + install_element (VIEW_NODE, &show_ip_lcommunity_list_cmd); + install_element (VIEW_NODE, &show_ip_lcommunity_list_arg_cmd); } |