]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd:support of color extended community color-only types
authorguozhongfeng.gzf <guozhongfeng.gzf@alibaba-inc.com>
Thu, 24 Oct 2024 12:05:23 +0000 (20:05 +0800)
committerguozhongfeng.gzf <guozhongfeng.gzf@alibaba-inc.com>
Thu, 7 Nov 2024 11:02:11 +0000 (19:02 +0800)
Add support of color extended community color-only types, RFC 9256.
The type only support 00 01 10.

configuration example:
!
frr version 10.3-dev-my-manual-build
frr defaults traditional
hostname router3
!
route-map color permit 1
 set extcommunity color 10:100 01:200 00:300
exit
!
vrf Vrf1
exit-vrf
!
interface lo
 ipv6 address 3::3/128
exit
!
router bgp 3
 bgp router-id 3.3.3.3
 bgp log-neighbor-changes
 no bgp ebgp-requires-policy
 no bgp default ipv4-unicast
 bgp bestpath as-path multipath-relax
 timers bgp 10 30
 neighbor 100.13.13.1 remote-as 1
 neighbor 100.13.13.1 advertisement-interval 0
 neighbor 100.23.23.2 remote-as 2
 neighbor 100.23.23.2 advertisement-interval 0
 neighbor 1000:3000::1 remote-as 1
 neighbor 1000:3000::1 ebgp-multihop
 neighbor 1000:3000::1 update-source 1000:3000::3
 neighbor 1000:3000::1 capability extended-nexthop
 neighbor 2000:3000::2 remote-as 2
 neighbor 2000:3000::2 ebgp-multihop
 neighbor 2000:3000::2 update-source 2000:3000::3
 neighbor 2000:3000::2 capability extended-nexthop
 !
 address-family ipv4 unicast
  neighbor 100.13.13.1 activate
  neighbor 100.23.23.2 activate
 exit-address-family
 !
 address-family ipv6 unicast
  redistribute connected route-map color
  neighbor 1000:3000::1 activate
  neighbor 2000:3000::2 activate
 exit-address-family
exit
!
end

Signed-off-by: guozhongfeng.gzf <guozhongfeng.gzf@alibaba-inc.com>
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h
yang/frr-bgp-route-map.yang

index df32d751031683205e6e32204b40e0bdaf47c8d5..065f4fef3772b5f6e1a075dc29d6119ff7a2e117 100644 (file)
@@ -361,16 +361,22 @@ static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr)
 {
        /*
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-        *  | 0x03         | Sub-Type(0x0b) |    Flags                      |
+        *  | 0x03         | Sub-Type(0x0b) | CO|    Flags                  |
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         *  |                          Color Value                          |
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *  https://datatracker.ietf.org/doc/rfc9256/, Section 8.8.1
+        *  The CO bits can have 4 different values: 00 01 10 11
         */
        uint32_t colorid;
+       uint8_t color_type;
+       /* get the color type */
+       ptr++;
+       color_type = (*ptr) >> 6;
 
-       memcpy(&colorid, ptr + 3, 4);
+       memcpy(&colorid, ptr + 2, 4);
        colorid = ntohl(colorid);
-       snprintf(buf, bufsz, "Color:%d", colorid);
+       snprintf(buf, bufsz, "Color:%d%d:%d", (color_type & 0x2) >> 1, color_type & 0x1, colorid);
 }
 
 /* Initialize Extended Comminities related hash. */
@@ -531,7 +537,7 @@ static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type,
                eval6->val[19] = val & 0xff;
        } else if (type == ECOMMUNITY_ENCODE_OPAQUE &&
                   sub_type == ECOMMUNITY_COLOR) {
-               encode_color(val, eval);
+               encode_color(val, as, eval);
        } else {
                encode_route_target_as4(as, val, eval, trans);
        }
@@ -739,6 +745,13 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
                                 */
                                if (!asn_str2asn(buf, &as))
                                        goto error;
+                       } else if (type == ECOMMUNITY_COLOR) {
+                               /* If extcommunity is color, only support 00/01/10/11, max value is 3 */
+                               /* color value */
+                               as = strtoul(buf, &endptr, 2);
+                               if (*endptr != '\0' || as > 3)
+                                       goto error;
+                               val_color = 0;
                        } else {
                                /* Parsing A AS number in A:MN */
                                errno = 0;
@@ -753,6 +766,8 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
                                if (*endptr != '\0' || tmp_as > BGP_AS4_MAX ||
                                    errno)
                                        goto error;
+                               if (*token == ecommunity_token_color && as > 3)
+                                       goto error;
                                as = (as_t)tmp_as;
                        }
                } else if (*p == '.') {
@@ -791,13 +806,15 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
                /* Encode result into extended community for AS format or color.  */
                if (as > BGP_AS_MAX)
                        ecomm_type = ECOMMUNITY_ENCODE_AS4;
-               else if (as > 0)
-                       ecomm_type = ECOMMUNITY_ENCODE_AS;
-               else if (val_color) {
+               else if (type == ECOMMUNITY_COLOR) {
                        ecomm_type = ECOMMUNITY_ENCODE_OPAQUE;
                        sub_type = ECOMMUNITY_COLOR;
-                       val = val_color;
-               }
+                       if (val_color) {
+                               val = val_color;
+                               as = 1;
+                       }
+               } else if (as > 0)
+                       ecomm_type = ECOMMUNITY_ENCODE_AS;
        }
        if (ecommunity_encode(ecomm_type, sub_type, 1, as, ip, val, eval))
                goto error;
@@ -1419,7 +1436,15 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
                        else if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH)
                                ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf),
                                                       pnt, len);
-                       else
+                       else if (sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_COLOR) {
+                               uint32_t color;
+                               /* get the color type */
+                               uint8_t color_type = (*pnt) >> 6;
+                               memcpy(&color, pnt + 2, 4);
+                               color = ntohl(color);
+                               snprintf(encbuf, sizeof(encbuf), "Color:%d%d:%u",
+                                        (color_type & 0x2) >> 1, color_type & 0x1, color);
+                       } else
                                unk_ecom = true;
                } else if (CHECK_FLAG(type, ECOMMUNITY_ENCODE_IP_NON_TRANS)) {
                        sub_type = *pnt++;
@@ -1439,6 +1464,7 @@ unknown:
                                 sub_type);
 
                int r = strlcat(str_buf, encbuf, str_size);
+
                assert(r < str_size);
        }
 
index 0544cbd316e0f6fdd55a0900333eb6b2cb5e921d..af9d481c19aedd8455c2b284be4404505205ef70 100644 (file)
@@ -85,6 +85,7 @@
 
 /* Low-order octet of the Extended Communities type field for OPAQUE types */
 #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP     0x0c
+#define ECOMMUNITY_OPAQUE_SUBTYPE_COLOR            0x0b
 
 /* Extended communities attribute string format.  */
 #define ECOMMUNITY_FORMAT_ROUTE_MAP            0
@@ -328,26 +329,25 @@ static inline void encode_node_target(struct in_addr *node_id,
 
 /*
  * Encode BGP Color extended community
- * is's a transitive opaque Extended community (RFC 9012 4.3)
+ * is's a transitive opaque Extended community (RFC 9256  8.8.1)
  * flag is set to 0
- * RFC 9012 14.10: No values have currently been registered.
- *            4.3: this field MUST be set to zero by the originator
- *                 and ignored by the receiver;
  *
  */
-static inline void encode_color(uint32_t color_id, struct ecommunity_val *eval)
+static inline void encode_color(uint32_t color_id, uint32_t flags, struct ecommunity_val *eval)
 {
        /*
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-        *  | 0x03         | Sub-Type(0x0b) |    Flags                      |
+        *  | 0x03         | Sub-Type(0x0b) |CO |         Flags             |
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         *  |                          Color Value                          |
         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        *  https://datatracker.ietf.org/doc/rfc9256/, Section 8.8.1
+        *  The CO bits can have 4 different values: 00 01 10 11
         */
        memset(eval, 0, sizeof(*eval));
        eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE;
        eval->val[1] = ECOMMUNITY_COLOR;
-       eval->val[2] = 0x00;
+       eval->val[2] = (flags << 6) & 0xff;
        eval->val[3] = 0x00;
        eval->val[4] = (color_id >> 24) & 0xff;
        eval->val[5] = (color_id >> 16) & 0xff;
index 4ed80d7d07006f1b806e0ffd86caf6f5d2ae104c..5f701d514c807d838df7ee331de8e848218d0e5e 100644 (file)
@@ -532,7 +532,7 @@ identity set-extcommunity-color {
 
   typedef color-list {
     type string {
-      pattern '((429496729[0-5]|42949672[0-8][0-9]|'
+      pattern '((00|01|10|11):(429496729[0-5]|42949672[0-8][0-9]|'
       +            '4294967[0-1][0-9]{2}|429496[0-6][0-9]{3}|'
       +            '42949[0-5][0-9]{4}|4294[0-8][0-9]{5}|'
       +            '429[0-3][0-9]{6}|42[0-8][0-9]{7}|'
@@ -540,10 +540,11 @@ identity set-extcommunity-color {
       +            '[1-9][0-9]{0,8})(\s*))+';
     }
     description
-      "The color-list type represent a set of colors of value (1..4294967295)
+      "The color-list type represent a set of colors of value (examples 00:200 01:200 10:200)
        values are separated by white spaces";
     reference
-      "RFC 9012 - The BGP Tunnel Encapsulation Attribute";
+      "RFC 9012 - The BGP Tunnel Encapsulation Attribute.
+       RFC 9256 - Segment Routing Policy Architecture.";
   }
 
   augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:rmap-match-condition/frr-route-map:match-condition" {