]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: introduce new alloc algorithm for SRv6 SID
authorRyoga Saito <contact@proelbtn.com>
Tue, 31 Aug 2021 06:31:44 +0000 (06:31 +0000)
committerRyoga Saito <contact@proelbtn.com>
Fri, 3 Sep 2021 01:18:50 +0000 (01:18 +0000)
Current implementation of SRv6 SID allocation algorithm sets most least
2 bytes. But, according to RFC8986, function bits is located in the next
to locator. New allocation alogirithm respects this format.

Signed-off-by: Ryoga Saito <contact@proelbtn.com>
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgpd.h

index 1af2ab384f7eb910ba596d25ee997271b21f638b..24f28ba73370331ebfe59782d9a07abdbfc41546 100644 (file)
@@ -522,13 +522,14 @@ static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
  * if index != 0: try to allocate as index-mode
  * else: try to allocate as auto-mode
  */
-static bool alloc_new_sid(struct bgp *bgp, uint32_t index,
-                         struct in6_addr *sid)
+static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
+                             struct in6_addr *sid)
 {
        struct listnode *node;
        struct prefix_ipv6 *chunk;
        struct in6_addr sid_buf;
        bool alloced = false;
+       int label;
 
        if (!bgp || !sid)
                return false;
@@ -536,7 +537,8 @@ static bool alloc_new_sid(struct bgp *bgp, uint32_t index,
        for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
                sid_buf = chunk->prefix;
                if (index != 0) {
-                       sid_buf.s6_addr[15] = index;
+                       label = index << 12;
+                       transpose_sid(&sid_buf, label, 64, 16);
                        if (sid_exist(bgp, &sid_buf))
                                return false;
                        alloced = true;
@@ -544,9 +546,8 @@ static bool alloc_new_sid(struct bgp *bgp, uint32_t index,
                }
 
                for (size_t i = 1; i < 255; i++) {
-                       sid_buf.s6_addr[15] = (i & 0xff00) >> 8;
-                       sid_buf.s6_addr[14] = (i & 0x00ff);
-
+                       label = i << 12;
+                       transpose_sid(&sid_buf, label, 64, 16);
                        if (sid_exist(bgp, &sid_buf))
                                continue;
                        alloced = true;
@@ -555,20 +556,19 @@ static bool alloc_new_sid(struct bgp *bgp, uint32_t index,
        }
 
        if (!alloced)
-               return false;
+               return 0;
 
        sid_register(bgp, &sid_buf, bgp->srv6_locator_name);
        *sid = sid_buf;
-       return true;
+       return label;
 }
 
 void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
 {
        int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
-       bool alloced = false;
        char buf[256];
        struct in6_addr *sid;
-       uint32_t tovpn_sid_index = 0;
+       uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
        bool tovpn_sid_auto = false;
 
        if (debug)
@@ -602,8 +602,9 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
        }
 
        sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
-       alloced = alloc_new_sid(bgp_vpn, tovpn_sid_index, sid);
-       if (!alloced) {
+       tovpn_sid_transpose_label =
+               alloc_new_sid(bgp_vpn, tovpn_sid_index, sid);
+       if (tovpn_sid_transpose_label == 0) {
                zlog_debug("%s: not allocated new sid for vrf %s: afi %s",
                           __func__, bgp_vrf->name_pretty, afi2str(afi));
                return;
@@ -615,9 +616,22 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
                           __func__, buf, bgp_vrf->name_pretty,
                           afi2str(afi));
        }
+       bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label =
+               tovpn_sid_transpose_label;
        bgp_vrf->vpn_policy[afi].tovpn_sid = sid;
 }
 
+void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
+                  uint8_t len)
+{
+       for (uint8_t idx = 0; idx < len; idx++) {
+               uint8_t tidx = offset + idx;
+               sid->s6_addr[tidx / 8] &= ~(0x1 << (7 - tidx % 8));
+               if (label >> (19 - idx) & 0x1)
+                       sid->s6_addr[tidx / 8] |= 0x1 << (7 - tidx % 8);
+       }
+}
+
 static bool ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
 {
        uint32_t i, j;
index 38193721b3e04344f3ee667b13fd1e374e559390..8e286527d975388cf4d459f50ce1449daba36d7b 100644 (file)
@@ -81,6 +81,8 @@ extern void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi);
 extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi);
 extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
 extern void ensure_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
+extern void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
+                         uint8_t size);
 extern void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
                                afi_t afi, safi_t safi);
 void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
index d39743a152c0a727957049276661b52211e4a6b6..9aaf12085991af87375c4b1358d872f1797f50de 100644 (file)
@@ -241,6 +241,7 @@ struct vpn_policy {
         */
        uint32_t tovpn_sid_index; /* unset => set to 0 */
        struct in6_addr *tovpn_sid;
+       uint32_t tovpn_sid_transpose_label;
        struct in6_addr *tovpn_zebra_vrf_sid_last_sent;
 };