]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Create BGP alias names for community/large-community
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Wed, 21 Apr 2021 19:34:12 +0000 (22:34 +0300)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Wed, 5 May 2021 13:37:00 +0000 (16:37 +0300)
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>
14 files changed:
bgpd/bgp_community.c
bgpd/bgp_community_alias.c [new file with mode: 0644]
bgpd/bgp_community_alias.h [new file with mode: 0644]
bgpd/bgp_lcommunity.c
bgpd/bgp_main.c
bgpd/bgp_memory.c
bgpd/bgp_memory.h
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgpd.c
bgpd/subdir.am
lib/command.h
vtysh/vtysh_config.c

index 43138b82f68fe32e8d6b09c55d942ea1805b4274..b034ec9f7bf9da119745a6ab652cb474af660582 100644 (file)
@@ -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 (file)
index 0000000..6e510a0
--- /dev/null
@@ -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 (file)
index 0000000..c84119a
--- /dev/null
@@ -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 */
index 88a85c979e74c06c330a51c51bd139718df11cc3..ff34937efc73dabf686838f80732a2ff97882191 100644 (file)
@@ -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) {
index ea74a82cec5576ef15561eadc590d488dd47da48..995917b6bdc5c62727a90bdee194a441e014e3dc 100644 (file)
@@ -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();
 
index 36bdc05eb784a503228f8f0a8851dcbed9a2f867..fc508496cca86d1f392f3f9fd81093fc7552e034 100644 (file)
@@ -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");
index 29923424e33c46a8f4aa4df9700370110a4662fb..40802480381cafe2bf1d00cc780721d81c89180e 100644 (file)
@@ -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);
index 49b94e6d7c85954ab066dbd4481ed86d7cd909d5..77a0b5fea7f103486ea381336b8f13735771e325 100644 (file)
@@ -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"
index 0347f49cb8295e5e3fa27a5c5b4067c2375d5b66..7cd36ef5382f93c815f2a8614cdf0fb1328a1a99 100644 (file)
@@ -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);
+}
index 251bdc3fe3a2e11375608833db23fed16a438eda..051b2e958010d9063fb9fd9621dacfff627d11ab 100644 (file)
@@ -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);
index 2c9aad5d2103beac91cb62a901fd67a58e5d1f7f..73c1cbbbd9e096bbca63b0021a422618285967f2 100644 (file)
@@ -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();
index 2c73f1459452a25eb66551a35fb586c5618e7cb6..b54c41cabee9b6f60877ce839f941088fbae267f 100644 (file)
@@ -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 \
index 7e135dbcf6129175c04d1a3b2e5c0bd4c210d65d..51da4c52e63a18dde2832e99c73e73193405c796 100644 (file)
@@ -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. */
index 3414c764ce39783c5902e8663db87ef2e96c6487..f92b0e920bb17fcd6420174e0dd99e9009a4fd05 100644 (file)
@@ -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)