diff options
author | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-04-21 21:34:12 +0200 |
---|---|---|
committer | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-05-05 15:37:00 +0200 |
commit | ed0e57e3f079352714c3a3a8a5b0dddf4aadfe1d (patch) | |
tree | 8c9cc817cb849107898633eb5d1d3201135fba10 | |
parent | Merge pull request #8619 from donaldsharp/sharp_redistribute (diff) | |
download | frr-ed0e57e3f079352714c3a3a8a5b0dddf4aadfe1d.tar.xz frr-ed0e57e3f079352714c3a3a8a5b0dddf4aadfe1d.zip |
bgpd: Create BGP alias names for community/large-community
Show alias name instead of numerical value in `show bgp <prefix>. E.g.:
```
root@exit1-debian-9:~/frr# vtysh -c 'sh run' | grep 'bgp community alias'
bgp community alias 65001:123 community-1
bgp community alias 65001:123:1 lcommunity-1
root@exit1-debian-9:~/frr#
```
```
exit1-debian-9# sh ip bgp 172.16.16.1/32
BGP routing table entry for 172.16.16.1/32, version 21
Paths: (2 available, best #2, table default)
Advertised to non peer-group peers:
65030
192.168.0.2 from home-spine1.donatas.net(192.168.0.2) (172.16.16.1)
Origin incomplete, metric 0, valid, external, best (Neighbor IP)
Community: 65001:12 65001:13 community-1 65001:65534
Large Community: lcommunity-1 65001:123:2
Last update: Fri Apr 16 12:51:27 2021
exit1-debian-9#
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
-rw-r--r-- | bgpd/bgp_community.c | 5 | ||||
-rw-r--r-- | bgpd/bgp_community_alias.c | 154 | ||||
-rw-r--r-- | bgpd/bgp_community_alias.h | 46 | ||||
-rw-r--r-- | bgpd/bgp_lcommunity.c | 5 | ||||
-rw-r--r-- | bgpd/bgp_main.c | 4 | ||||
-rw-r--r-- | bgpd/bgp_memory.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_memory.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 1 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 74 | ||||
-rw-r--r-- | bgpd/bgp_vty.h | 1 | ||||
-rw-r--r-- | bgpd/bgpd.c | 2 | ||||
-rw-r--r-- | bgpd/subdir.am | 2 | ||||
-rw-r--r-- | lib/command.h | 1 | ||||
-rw-r--r-- | vtysh/vtysh_config.c | 14 |
14 files changed, 304 insertions, 9 deletions
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index 43138b82f..b034ec9f7 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -28,6 +28,7 @@ #include "bgpd/bgp_memory.h" #include "bgpd/bgp_community.h" +#include "bgpd/bgp_community_alias.h" /* Hash of community attribute. */ static struct hash *comhash; @@ -292,7 +293,7 @@ static void set_community_string(struct community *com, bool make_json) len += strlen(" no-peer"); break; default: - len += strlen(" 65536:65535"); + len = BUFSIZ; break; } } @@ -450,7 +451,7 @@ static void set_community_string(struct community *com, bool make_json) val = comval & 0xFFFF; char buf[32]; snprintf(buf, sizeof(buf), "%u:%d", as, val); - strlcat(str, buf, len); + strlcat(str, bgp_community2alias(buf), len); if (make_json) { json_string = json_object_new_string(buf); json_object_array_add(json_community_list, diff --git a/bgpd/bgp_community_alias.c b/bgpd/bgp_community_alias.c new file mode 100644 index 000000000..6e510a0a0 --- /dev/null +++ b/bgpd/bgp_community_alias.c @@ -0,0 +1,154 @@ +/* BGP community, large-community aliasing. + * + * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com> + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "memory.h" +#include "lib/jhash.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_community_alias.h" + +static struct hash *bgp_ca_alias_hash; +static struct hash *bgp_ca_community_hash; + +static unsigned int bgp_ca_community_hash_key(const void *p) +{ + const struct community_alias *ca = p; + + return jhash(ca->community, sizeof(ca->community), 0); +} + +static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2) +{ + const struct community_alias *ca1 = p1; + const struct community_alias *ca2 = p2; + + return (strncmp(ca1->community, ca2->community, + sizeof(struct community_alias)) + == 0); +} + +static unsigned int bgp_ca_alias_hash_key(const void *p) +{ + const struct community_alias *ca = p; + + return jhash(ca->alias, sizeof(ca->alias), 0); +} + +static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2) +{ + const struct community_alias *ca1 = p1; + const struct community_alias *ca2 = p2; + + return (strncmp(ca1->alias, ca2->alias, sizeof(struct community_alias)) + == 0); +} + +static void *bgp_community_alias_alloc(void *p) +{ + const struct community_alias *ca = p; + struct communtiy_alias *new; + + new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias)); + memcpy(new, ca, sizeof(struct community_alias)); + + return new; +} + +void bgp_community_alias_init(void) +{ + bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key, + bgp_ca_community_hash_cmp, + "BGP community alias (community)"); + bgp_ca_alias_hash = + hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp, + "BGP community alias (alias)"); +} + +void bgp_community_alias_finish(void) +{ + hash_free(bgp_ca_community_hash); + hash_free(bgp_ca_alias_hash); +} + +static void bgp_community_alias_show_iterator(struct hash_bucket *hb, + struct vty *vty) +{ + struct community_alias *ca = hb->data; + + vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias); +} + +int bgp_community_alias_write(struct vty *vty) +{ + hash_iterate(bgp_ca_community_hash, + (void (*)(struct hash_bucket *, + void *))bgp_community_alias_show_iterator, + vty); + return 1; +} + +void bgp_ca_community_insert(struct community_alias *ca) +{ + hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc); +} + +void bgp_ca_alias_insert(struct community_alias *ca) +{ + hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc); +} + +void bgp_ca_community_delete(struct community_alias *ca) +{ + struct community_alias *data = hash_release(bgp_ca_community_hash, ca); + + XFREE(MTYPE_COMMUNITY_ALIAS, data); +} + +void bgp_ca_alias_delete(struct community_alias *ca) +{ + struct community_alias *data = hash_release(bgp_ca_alias_hash, ca); + + XFREE(MTYPE_COMMUNITY_ALIAS, data); +} + +struct community_alias *bgp_ca_community_lookup(struct community_alias *ca) +{ + return hash_lookup(bgp_ca_community_hash, ca); +} + +struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca) +{ + return hash_lookup(bgp_ca_alias_hash, ca); +} + +const char *bgp_community2alias(char *community) +{ + struct community_alias ca; + struct community_alias *find; + + memset(&ca, 0, sizeof(ca)); + strlcpy(ca.community, community, sizeof(ca.community)); + + find = bgp_ca_community_lookup(&ca); + if (find) + return find->alias; + + return community; +} diff --git a/bgpd/bgp_community_alias.h b/bgpd/bgp_community_alias.h new file mode 100644 index 000000000..c84119a0d --- /dev/null +++ b/bgpd/bgp_community_alias.h @@ -0,0 +1,46 @@ +/* BGP community, large-community aliasing. + * + * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com> + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bgpd/bgp_lcommunity.h" + +#ifndef FRR_BGP_COMMUNITY_ALIAS_H +#define FRR_BGP_COMMUNITY_ALIAS_H + +struct community_alias { + /* Human readable community string */ + char community[LCOMMUNITY_SIZE * 3]; + + /* Human readable community alias */ + char alias[BUFSIZ]; +}; + +extern void bgp_community_alias_init(void); +extern void bgp_community_alias_finish(void); +extern struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca); +extern struct community_alias * +bgp_ca_community_lookup(struct community_alias *ca); +extern void bgp_ca_community_insert(struct community_alias *ca); +extern void bgp_ca_alias_insert(struct community_alias *ca); +extern void bgp_ca_community_delete(struct community_alias *ca); +extern void bgp_ca_alias_delete(struct community_alias *ca); +extern int bgp_community_alias_write(struct vty *vty); +extern const char *bgp_community2alias(char *community); + +#endif /* FRR_BGP_COMMUNITY_ALIAS_H */ diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 88a85c979..ff34937ef 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -30,6 +30,7 @@ #include "bgpd/bgpd.h" #include "bgpd/bgp_lcommunity.h" +#include "bgpd/bgp_community_alias.h" #include "bgpd/bgp_aspath.h" /* Hash of community attribute. */ @@ -213,7 +214,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) } /* 1 space + lcom->size lcom strings + null terminator */ - size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2; + size_t str_buf_sz = BUFSIZ; str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz); for (i = 0; i < lcom->size; i++) { @@ -231,7 +232,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1, local2); - len = strlcat(str_buf, lcsb, str_buf_sz); + len = strlcat(str_buf, bgp_community2alias(lcsb), str_buf_sz); assert((unsigned int)len < str_buf_sz); if (make_json) { diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index ea74a82ce..995917b6b 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -66,6 +66,7 @@ #include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_routemap_nb.h" +#include "bgpd/bgp_community_alias.h" #ifdef ENABLE_BGP_VNC #include "bgpd/rfapi/rfapi_backend.h" @@ -220,6 +221,9 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) /* reverse bgp_dump_init */ bgp_dump_finish(); + /* BGP community aliases */ + bgp_community_alias_finish(); + /* reverse bgp_route_init */ bgp_route_finish(); diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 36bdc05eb..fc508496c 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -65,6 +65,8 @@ DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list"); DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter"); DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str"); +DEFINE_MTYPE(BGPD, COMMUNITY_ALIAS, "community"); + DEFINE_MTYPE(BGPD, COMMUNITY, "community"); DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val"); DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str"); diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index 29923424e..408024803 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -61,6 +61,8 @@ DECLARE_MTYPE(AS_LIST); DECLARE_MTYPE(AS_FILTER); DECLARE_MTYPE(AS_FILTER_STR); +DECLARE_MTYPE(COMMUNITY_ALIAS); + DECLARE_MTYPE(COMMUNITY); DECLARE_MTYPE(COMMUNITY_VAL); DECLARE_MTYPE(COMMUNITY_STR); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 49b94e6d7..77a0b5fea 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -51,6 +51,7 @@ #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_regex.h" #include "bgpd/bgp_community.h" +#include "bgpd/bgp_community_alias.h" #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_clist.h" diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 0347f49cb..7cd36ef53 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -46,6 +46,7 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_community.h" +#include "bgpd/bgp_community_alias.h" #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_lcommunity.h" #include "bgpd/bgp_damp.h" @@ -1497,6 +1498,62 @@ void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " bgp router-id %s\n", yang_dnode_get_string(dnode, NULL)); } +DEFPY(bgp_community_alias, bgp_community_alias_cmd, + "[no$no] bgp community alias WORD$community WORD$alias", + NO_STR BGP_STR + "Add community specific parameters\n" + "Create an alias for a community\n" + "Community (AA:BB or AA:BB:CC)\n" + "Alias name\n") +{ + struct community_alias ca1; + struct community_alias ca2; + struct community_alias *lookup_community; + struct community_alias *lookup_alias; + + if (!community_str2com(community) && !lcommunity_str2com(community)) { + vty_out(vty, "Invalid community format\n"); + return CMD_WARNING; + } + + memset(&ca1, 0, sizeof(ca1)); + memset(&ca2, 0, sizeof(ca2)); + strlcpy(ca1.community, community, sizeof(ca1.community)); + strlcpy(ca1.alias, alias, sizeof(ca1.alias)); + + lookup_community = bgp_ca_community_lookup(&ca1); + lookup_alias = bgp_ca_alias_lookup(&ca1); + + if (no) { + bgp_ca_alias_delete(&ca1); + bgp_ca_community_delete(&ca1); + } else { + if (lookup_alias) { + /* Lookup if community hash table has an item + * with the same alias name. + */ + strlcpy(ca2.community, lookup_alias->community, + sizeof(ca2.community)); + if (bgp_ca_community_lookup(&ca2)) { + vty_out(vty, + "community (%s) already has this alias (%s)\n", + lookup_alias->community, + lookup_alias->alias); + return CMD_WARNING; + } + bgp_ca_alias_delete(&ca1); + } + + if (lookup_community) + bgp_ca_community_delete(&ca1); + + bgp_ca_alias_insert(&ca1); + bgp_ca_community_insert(&ca1); + } + + return CMD_SUCCESS; +} + DEFPY (bgp_global_suppress_fib_pending, bgp_global_suppress_fib_pending_cmd, "[no] bgp suppress-fib-pending", @@ -19261,6 +19318,8 @@ void bgp_vty_init(void) /* Community-list. */ community_list_vty(); + community_alias_vty(); + /* vpn-policy commands */ install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd); install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd); @@ -20467,3 +20526,18 @@ static void community_list_vty(void) install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd); install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd); } + +static struct cmd_node community_alias_node = { + .name = "community alias", + .node = COMMUNITY_ALIAS_NODE, + .prompt = "", + .config_write = bgp_community_alias_write, +}; + +void community_alias_vty(void) +{ + install_node(&community_alias_node); + + /* Community-list. */ + install_element(CONFIG_NODE, &bgp_community_alias_cmd); +} diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 251bdc3fe..051b2e958 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -154,6 +154,7 @@ struct bgp; } while (0) extern void bgp_vty_init(void); +extern void community_alias_vty(void); extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json); extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, enum bgp_instance_type inst_type); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2c9aad5d2..73c1cbbbd 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -55,6 +55,7 @@ #include "bgpd/bgp_debug.h" #include "bgpd/bgp_errors.h" #include "bgpd/bgp_community.h" +#include "bgpd/bgp_community_alias.h" #include "bgpd/bgp_conditional_adv.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_regex.h" @@ -7697,6 +7698,7 @@ void bgp_init(unsigned short instance) /* BGP inits. */ bgp_attr_init(); bgp_debug_init(); + bgp_community_alias_init(); bgp_dump_init(); bgp_route_init(); bgp_route_map_init(); diff --git a/bgpd/subdir.am b/bgpd/subdir.am index 2c73f1459..b54c41cab 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -57,6 +57,7 @@ bgpd_libbgp_a_SOURCES = \ bgpd/bgp_bfd.c \ bgpd/bgp_clist.c \ bgpd/bgp_community.c \ + bgpd/bgp_community_alias.c \ bgpd/bgp_conditional_adv.c \ bgpd/bgp_damp.c \ bgpd/bgp_debug.c \ @@ -137,6 +138,7 @@ noinst_HEADERS += \ bgpd/bgp_bfd.h \ bgpd/bgp_clist.h \ bgpd/bgp_community.h \ + bgpd/bgp_community_alias.h \ bgpd/bgp_conditional_adv.h \ bgpd/bgp_damp.h \ bgpd/bgp_debug.h \ diff --git a/lib/command.h b/lib/command.h index 7e135dbcf..51da4c52e 100644 --- a/lib/command.h +++ b/lib/command.h @@ -137,6 +137,7 @@ enum node_type { PREFIX_IPV6_NODE, /* Prefix list node. */ AS_LIST_NODE, /* AS list node. */ COMMUNITY_LIST_NODE, /* Community list node. */ + COMMUNITY_ALIAS_NODE, /* Community alias node. */ RMAP_NODE, /* Route map node. */ PBRMAP_NODE, /* PBR map node. */ SMUX_NODE, /* SNMP configuration node. */ diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 3414c764c..f92b0e920 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -380,6 +380,9 @@ void vtysh_config_parse_line(void *arg, const char *line) strlen("bgp large-community-list")) == 0) config = config_get(COMMUNITY_LIST_NODE, line); + else if (strncmp(line, "bgp community alias", + strlen("bgp community alias")) == 0) + config = config_get(COMMUNITY_ALIAS_NODE, line); else if (strncmp(line, "ip route", strlen("ip route")) == 0) config = config_get(IP_NODE, line); else if (strncmp(line, "ipv6 route", strlen("ipv6 route")) == 0) @@ -452,11 +455,12 @@ void vtysh_config_parse_line(void *arg, const char *line) #define NO_DELIMITER(I) \ ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \ || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE \ - || (I) == ACCESS_IPV6_NODE || (I) == ACCESS_MAC_NODE \ - || (I) == PREFIX_IPV6_NODE || (I) == FORWARDING_NODE \ - || (I) == DEBUG_NODE || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE \ - || (I) == NORTHBOUND_DEBUG_NODE || (I) == RMAP_DEBUG_NODE \ - || (I) == RESOLVER_DEBUG_NODE || (I) == MPLS_NODE) + || (I) == COMMUNITY_ALIAS_NODE || (I) == ACCESS_IPV6_NODE \ + || (I) == ACCESS_MAC_NODE || (I) == PREFIX_IPV6_NODE \ + || (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE \ + || (I) == VRF_DEBUG_NODE || (I) == NORTHBOUND_DEBUG_NODE \ + || (I) == RMAP_DEBUG_NODE || (I) == RESOLVER_DEBUG_NODE \ + || (I) == MPLS_NODE) /* Display configuration to file pointer. */ void vtysh_config_dump(void) |