From c0945b78286ae88644e6e423b1b4ef0d783d1063 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Fri, 8 Apr 2022 22:57:47 +0300 Subject: [PATCH] bgpd: Allow setting BGP [large]community in route-maps Before: ``` spine1-debian-11(config-route-map)# bgp community alias 65001:65001 test1 spine1-debian-11(config)# route-map rm permit 10 spine1-debian-11(config-route-map)# set community 65001:65001 % Malformed communities attribute ``` After: ``` spine1-debian-11(config)# bgp community alias 65001:65001 test1 spine1-debian-11(config)# route-map rm permit 10 spine1-debian-11(config-route-map)# set community 65001:65001 spine1-debian-11(config-route-map)# ``` Same for large-communities. Signed-off-by: Donatas Abraitis --- bgpd/bgp_clist.c | 4 ++-- bgpd/bgp_community.c | 13 ++++++++----- bgpd/bgp_community.h | 3 ++- bgpd/bgp_debug.c | 6 ++++-- bgpd/bgp_lcommunity.c | 13 ++++++++----- bgpd/bgp_lcommunity.h | 3 ++- bgpd/bgp_route.c | 4 ++-- bgpd/bgp_routemap.c | 10 +++++----- bgpd/bgp_vty.c | 8 ++++---- 9 files changed, 37 insertions(+), 27 deletions(-) diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 0e590a463c..0631f8b95a 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -557,7 +557,7 @@ static bool community_regexp_match(struct community *com, regex_t *reg) if (com == NULL || com->size == 0) str = ""; else - str = community_str(com, false); + str = community_str(com, false, true); regstr = bgp_alias2community_str(str); @@ -631,7 +631,7 @@ static bool lcommunity_regexp_match(struct lcommunity *com, regex_t *reg) if (com == NULL || com->size == 0) str = ""; else - str = lcommunity_str(com, false); + str = lcommunity_str(com, false, true); regstr = bgp_alias2community_str(str); diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index 6e6a3cd587..78cf9ea76c 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -200,7 +200,8 @@ struct community *community_uniq_sort(struct community *com) 0xFFFFFF04 "no-peer" For other values, "AS:VAL" format is used. */ -static void set_community_string(struct community *com, bool make_json) +static void set_community_string(struct community *com, bool make_json, + bool translate_alias) { int i; char *str; @@ -447,7 +448,9 @@ 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); - const char *com2alias = bgp_community2alias(buf); + const char *com2alias = + translate_alias ? bgp_community2alias(buf) + : buf; strlcat(str, com2alias, len); if (make_json) { @@ -487,7 +490,7 @@ struct community *community_intern(struct community *com) /* Make string. */ if (!find->str) - set_community_string(find, false); + set_community_string(find, false, true); return find; } @@ -548,7 +551,7 @@ struct community *community_dup(struct community *com) } /* Return string representation of communities attribute. */ -char *community_str(struct community *com, bool make_json) +char *community_str(struct community *com, bool make_json, bool translate_alias) { if (!com) return NULL; @@ -557,7 +560,7 @@ char *community_str(struct community *com, bool make_json) XFREE(MTYPE_COMMUNITY_STR, com->str); if (!com->str) - set_community_string(com, make_json); + set_community_string(com, make_json, translate_alias); return com->str; } diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index 2a1fbf526a..6f0ae0235c 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -76,7 +76,8 @@ extern struct community *community_uniq_sort(struct community *); extern struct community *community_parse(uint32_t *, unsigned short); extern struct community *community_intern(struct community *); extern void community_unintern(struct community **); -extern char *community_str(struct community *, bool make_json); +extern char *community_str(struct community *, bool make_json, + bool translate_alias); extern unsigned int community_hash_make(const struct community *); extern struct community *community_str2com(const char *); extern bool community_match(const struct community *, const struct community *); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 5d14ff0fa6..49003e9428 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -411,12 +411,14 @@ bool bgp_dump_attr(struct attr *attr, char *buf, size_t size) if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) snprintf(buf + strlen(buf), size - strlen(buf), ", community %s", - community_str(bgp_attr_get_community(attr), false)); + community_str(bgp_attr_get_community(attr), false, + true)); if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) snprintf(buf + strlen(buf), size - strlen(buf), ", large-community %s", - lcommunity_str(bgp_attr_get_lcommunity(attr), false)); + lcommunity_str(bgp_attr_get_lcommunity(attr), false, + true)); if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) snprintf(buf + strlen(buf), size - strlen(buf), diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 60ad75c73b..8720170013 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -175,7 +175,8 @@ struct lcommunity *lcommunity_merge(struct lcommunity *lcom1, return lcom1; } -static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) +static void set_lcommunity_string(struct lcommunity *lcom, bool make_json, + bool translate_alias) { int i; int len; @@ -228,7 +229,8 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1, local2); - const char *com2alias = bgp_community2alias(lcsb); + const char *com2alias = + translate_alias ? bgp_community2alias(lcsb) : lcsb; len = strlcat(str_buf, com2alias, str_buf_sz); assert((unsigned int)len < str_buf_sz); @@ -264,7 +266,7 @@ struct lcommunity *lcommunity_intern(struct lcommunity *lcom) find->refcnt++; if (!find->str) - set_lcommunity_string(find, false); + set_lcommunity_string(find, false, true); return find; } @@ -291,7 +293,8 @@ void lcommunity_unintern(struct lcommunity **lcom) } /* Return string representation of lcommunities attribute. */ -char *lcommunity_str(struct lcommunity *lcom, bool make_json) +char *lcommunity_str(struct lcommunity *lcom, bool make_json, + bool translate_alias) { if (!lcom) return NULL; @@ -300,7 +303,7 @@ char *lcommunity_str(struct lcommunity *lcom, bool make_json) XFREE(MTYPE_LCOMMUNITY_STR, lcom->str); if (!lcom->str) - set_lcommunity_string(lcom, make_json); + set_lcommunity_string(lcom, make_json, translate_alias); return lcom->str; } diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index 6ccb6b7879..b9b5fe35d5 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -69,7 +69,8 @@ extern struct hash *lcommunity_hash(void); extern struct lcommunity *lcommunity_str2com(const char *); extern bool lcommunity_match(const struct lcommunity *, const struct lcommunity *); -extern char *lcommunity_str(struct lcommunity *, bool make_json); +extern char *lcommunity_str(struct lcommunity *, bool make_json, + bool translate_alias); extern bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr); extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 72eba2c3be..a5a57bdc7f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -10506,7 +10506,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, if (json_paths) { if (!bgp_attr_get_community(attr)->json) community_str(bgp_attr_get_community(attr), - true); + true, true); json_object_lock(bgp_attr_get_community(attr)->json); json_object_object_add( json_path, "community", @@ -10537,7 +10537,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, if (json_paths) { if (!bgp_attr_get_lcommunity(attr)->json) lcommunity_str(bgp_attr_get_lcommunity(attr), - true); + true, true); json_object_lock(bgp_attr_get_lcommunity(attr)->json); json_object_object_add( json_path, "largeCommunity", diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 1d87641a2d..2ed73ddb68 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -5562,19 +5562,19 @@ DEFUN_YANG (set_community, str = buffer_getstr(b); buffer_free(b); - if (str) { + if (str) com = community_str2com(str); - XFREE(MTYPE_TMP, str); - } /* Can't compile user input into communities attribute. */ if (!com) { - vty_out(vty, "%% Malformed communities attribute\n"); + vty_out(vty, "%% Malformed communities attribute '%s'\n", str); + XFREE(MTYPE_TMP, str); return CMD_WARNING_CONFIG_FAILED; } + XFREE(MTYPE_TMP, str); /* Set communites attribute string. */ - str = community_str(com, false); + str = community_str(com, false, false); if (additive) { size_t argstr_sz = strlen(str) + strlen(" additive") + 1; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 941696ab74..f0a4a56f41 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -14473,7 +14473,7 @@ static void community_show_all_iterator(struct hash_bucket *bucket, com = (struct community *)bucket->data; vty_out(vty, "[%p] (%ld) %s\n", (void *)com, com->refcnt, - community_str(com, false)); + community_str(com, false, false)); } /* Show BGP's community internal data. */ @@ -14502,7 +14502,7 @@ static void lcommunity_show_all_iterator(struct hash_bucket *bucket, lcom = (struct lcommunity *)bucket->data; vty_out(vty, "[%p] (%ld) %s\n", (void *)lcom, lcom->refcnt, - lcommunity_str(lcom, false)); + lcommunity_str(lcom, false, false)); } /* Show BGP's community internal data. */ @@ -19354,9 +19354,9 @@ static const char *community_list_config_str(struct community_entry *entry) str = ""; else { if (entry->style == COMMUNITY_LIST_STANDARD) - str = community_str(entry->u.com, false); + str = community_str(entry->u.com, false, false); else if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) - str = lcommunity_str(entry->u.lcom, false); + str = lcommunity_str(entry->u.lcom, false, false); else str = entry->config; } -- 2.39.5