From f84e89ec0d503820e13eac431a7a6dfbf744edd5 Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Fri, 11 Apr 2025 15:28:54 +0800 Subject: [PATCH] bgpd: Add function to filter extended communities Support filtering extended communities with a callback. So that we can strip multiple values in one pass. Signed-off-by: Xiao Liang --- bgpd/bgp_ecommunity.c | 40 ++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_ecommunity.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 95c78cc49d..046ed0f854 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -1712,6 +1712,46 @@ bool ecommunity_strip_non_transitive(struct ecommunity *ecom) return true; } +/* + * Filter source Extended Communities Attribute. May return NULL if the result + * is empty, or the source ecommunity, if not modified. + */ +struct ecommunity *ecommunity_filter(struct ecommunity *ecom, + bool (*filter)(uint8_t *, uint8_t, void *), void *arg) +{ + struct ecommunity *new; + uint8_t *new_val, *p, *q; + uint32_t c, new_size; + + if (!ecom || !ecom->size) + return NULL; + + new_val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size); + new_size = 0; + for (c = 0, p = ecom->val, q = new_val; c < ecom->size; c++, p += ecom->unit_size) { + if (filter(p, ecom->unit_size, arg)) { + memcpy(q, p, ecom->unit_size); + q += ecom->unit_size; + new_size++; + } + } + if (!new_size) { + XFREE(MTYPE_ECOMMUNITY_VAL, new_val); + return NULL; + } + if (new_size == ecom->size) { + XFREE(MTYPE_ECOMMUNITY_VAL, new_val); + return ecom; + } + + new = XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity)); + new->size = new_size; + new->unit_size = ecom->unit_size; + new->val = new_val; + + return new; +} + /* * Remove specified extended community value from extended community. * Returns 1 if value was present (and hence, removed), 0 otherwise. diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index d3708d53d4..d8c98f5925 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -405,6 +405,9 @@ extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type, uint8_t subtype); extern struct ecommunity *ecommunity_new(void); extern bool ecommunity_strip_non_transitive(struct ecommunity *ecom); +extern struct ecommunity *ecommunity_filter(struct ecommunity *ecom, + bool (*filter)(uint8_t *val, uint8_t usize, void *arg), + void *arg); extern bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval); struct bgp_pbr_entry_action; -- 2.39.5