diff options
| author | Ryoga Saito <contact@proelbtn.com> | 2021-08-31 06:31:44 +0000 |
|---|---|---|
| committer | Ryoga Saito <contact@proelbtn.com> | 2021-09-03 01:18:50 +0000 |
| commit | a45cd34e544ed3b3d342cc57e8fa5fa0832764c0 (patch) | |
| tree | e249c3fd7d4ebf2b1357f3909423e1d642b86c3e | |
| parent | 2dc1fa13226b820f972a54d2b805dfc53ab25fd0 (diff) | |
bgpd: introduce new alloc algorithm for SRv6 SID
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>
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 38 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.h | 2 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 1 |
3 files changed, 29 insertions, 12 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 1af2ab384f..24f28ba733 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -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; diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 38193721b3..8e286527d9 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -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, diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index d39743a152..9aaf120859 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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; }; |
