]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Add function to filter extended communities
authorXiao Liang <shaw.leon@gmail.com>
Fri, 11 Apr 2025 07:28:54 +0000 (15:28 +0800)
committerXiao Liang <shaw.leon@gmail.com>
Tue, 15 Apr 2025 03:17:45 +0000 (11:17 +0800)
Support filtering extended communities with a callback. So that we can
strip multiple values in one pass.

Signed-off-by: Xiao Liang <shaw.leon@gmail.com>
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h

index 95c78cc49d4541767a76cd9eceb59690d3af2d7c..046ed0f854c3f3772d3fecf776ccfa2eaa65d44b 100644 (file)
@@ -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.
index d3708d53d4863a96fb68dbc9161877879b66ee5c..d8c98f5925d094fd3c22b4c6b474e219bad7455e 100644 (file)
@@ -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;