Commit bd33f1cca7 for frr
commit bd33f1cca7d0fa3357bcf3bc1e4853fa9a98eac3
Author: Srinivasan Koona Lokabiraman <srinivasan@nexthop.ai>
Date: Fri Oct 23 05:34:38 2026 +0000
bgpd: make color extcommunity config output re-enterable
The color extended-community formatter ignores the 'format' argument
and always emits the ECOMMUNITY_FORMAT_DISPLAY spelling
(Color:CC:VALUE), including when rendering re-parseable config.
bgp extcommunity-list standard TEST permit color 00:100
is written back to running-config as 'permit Color:00:100', which the
parser rejects with '% Malformed community-list value', because
ecommunity_gettoken() requires the color keyword to be followed by
whitespace, not ':'. Pasting back a saved running-config therefore
loses the extcommunity-list entry.
Branch on the format, as ecommunity_rt_soo_str_internal() does. Unlike
rt/soo, no caller prints a 'color' keyword ahead of the value, so both
re-parseable formats carry the keyword themselves. Display output is
unchanged.
Signed-off-by: Srinivasan Koona Lokabiraman <srinivasan@nexthop.ai>
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 6e035b7ea1..6897096fcf 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -422,7 +422,23 @@ bool ecommunity_cmp(const void *arg1, const void *arg2)
ecom1->unit_size) == 0);
}
-static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr)
+/* Unlike rt/soo, no caller emits a "color" keyword ahead of the value, so
+ * the re-parseable formats have to carry it themselves.
+ */
+static const char *ecommunity_color_prefix(int format)
+{
+ switch (format) {
+ case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
+ case ECOMMUNITY_FORMAT_ROUTE_MAP:
+ return "color ";
+ case ECOMMUNITY_FORMAT_DISPLAY:
+ default:
+ return "Color:";
+ }
+}
+
+static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr,
+ int format)
{
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -441,7 +457,8 @@ static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr)
memcpy(&colorid, ptr + 2, 4);
colorid = ntohl(colorid);
- snprintf(buf, bufsz, "Color:%d%d:%d", (color_type & 0x2) >> 1, color_type & 0x1, colorid);
+ snprintfrr(buf, bufsz, "%s%d%d:%u", ecommunity_color_prefix(format),
+ (color_type & 0x2) >> 1, color_type & 0x1, colorid);
}
/* Initialize Extended Comminities related hash. */
@@ -1350,7 +1367,7 @@ static char *_ecommunity_ecom2str(struct ecommunity *ecom, int format, int filte
sizeof(encbuf));
} else if (*pnt == ECOMMUNITY_COLOR) {
ecommunity_color_str(encbuf, sizeof(encbuf),
- pnt);
+ pnt, format);
} else if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_UPA) {
struct in_addr rid = {};
uint8_t flags = data[BGP_UPA_EXTCOM_OFF_FLAGS];