summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas.abraitis@gmail.com>2021-04-21 21:34:12 +0200
committerDonatas Abraitis <donatas.abraitis@gmail.com>2021-05-05 15:37:00 +0200
commited0e57e3f079352714c3a3a8a5b0dddf4aadfe1d (patch)
tree8c9cc817cb849107898633eb5d1d3201135fba10
parentMerge pull request #8619 from donaldsharp/sharp_redistribute (diff)
downloadfrr-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.c5
-rw-r--r--bgpd/bgp_community_alias.c154
-rw-r--r--bgpd/bgp_community_alias.h46
-rw-r--r--bgpd/bgp_lcommunity.c5
-rw-r--r--bgpd/bgp_main.c4
-rw-r--r--bgpd/bgp_memory.c2
-rw-r--r--bgpd/bgp_memory.h2
-rw-r--r--bgpd/bgp_route.c1
-rw-r--r--bgpd/bgp_vty.c74
-rw-r--r--bgpd/bgp_vty.h1
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/subdir.am2
-rw-r--r--lib/command.h1
-rw-r--r--vtysh/vtysh_config.c14
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)