]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Add a function to strip non-transitive extended communities
authorDonatas Abraitis <donatas@opensourcerouting.org>
Thu, 17 Oct 2024 08:31:10 +0000 (11:31 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Tue, 22 Oct 2024 06:01:04 +0000 (09:01 +0300)
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h

index e0bf196e796a373f903a7f940b665852bfe9d6b8..e2292bb963d75a9ed9b2b34837271fc55d4daf93 100644 (file)
@@ -1588,6 +1588,50 @@ bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
        return true;
 }
 
+/* Delete all non-transitive extended communities */
+bool ecommunity_strip_non_transitive(struct ecommunity *ecom)
+{
+       uint8_t *p, *q, *new;
+       uint32_t c, found = 0;
+
+       if (!ecom || !ecom->val)
+               return false;
+
+       /* Certain extended communities like the Route Target can be present
+        * multiple times, handle that.
+        */
+       c = 0;
+       for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++)
+               if (CHECK_FLAG(*p, ECOMMUNITY_FLAG_NON_TRANSITIVE))
+                       found++;
+
+       if (!found)
+               return false;
+
+       /* Handle the case where everything needs to be stripped. */
+       if (found == ecom->size) {
+               XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+               ecom->size = 0;
+               return true;
+       }
+
+       /* Strip extended communities with non-transitive flag set */
+       new = XMALLOC(MTYPE_ECOMMUNITY_VAL, (ecom->size - found) * ecom->unit_size);
+       q = new;
+       for (c = 0, p = ecom->val; c < ecom->size; c++, p += ecom->unit_size) {
+               if (!CHECK_FLAG(*p, ECOMMUNITY_FLAG_NON_TRANSITIVE)) {
+                       memcpy(q, p, ecom->unit_size);
+                       q += ecom->unit_size;
+               }
+       }
+
+       XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+       ecom->val = new;
+       ecom->size -= found;
+
+       return true;
+}
+
 /*
  * Remove specified extended community value from extended community.
  * Returns 1 if value was present (and hence, removed), 0 otherwise.
index 67c16aeb9e82188945a3a30c5ec68c0467903547..e076885fb57c2205499b9a63a7fc5027984f1d07 100644 (file)
@@ -398,6 +398,7 @@ extern struct ecommunity *ecommunity_new(void);
 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 bool ecommunity_del_val(struct ecommunity *ecom,
                               struct ecommunity_val *eval);
 struct bgp_pbr_entry_action;