@@ -371,9 +371,11 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
371371 bgp -> vpn_policy [afi ].tovpn_sid_locator -> block_bits_length ;
372372 ctx .node_len =
373373 bgp -> vpn_policy [afi ].tovpn_sid_locator -> node_bits_length ;
374- ctx .function_len =
375- bgp -> vpn_policy [afi ]
376- .tovpn_sid_locator -> function_bits_length ;
374+ if (CHECK_FLAG (bgp -> vpn_policy [afi ].flags , BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE ))
375+ ctx .function_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
376+ else
377+ ctx .function_len =
378+ bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
377379 ctx .argument_len =
378380 bgp -> vpn_policy [afi ]
379381 .tovpn_sid_locator -> argument_bits_length ;
@@ -440,7 +442,10 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
440442 if (bgp -> tovpn_sid_locator ) {
441443 ctx .block_len = bgp -> tovpn_sid_locator -> block_bits_length ;
442444 ctx .node_len = bgp -> tovpn_sid_locator -> node_bits_length ;
443- ctx .function_len = bgp -> tovpn_sid_locator -> function_bits_length ;
445+ if (CHECK_FLAG (bgp -> vrf_flags , BGP_VRF_TOVPN_SID_FUNC_WIDE ))
446+ ctx .function_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
447+ else
448+ ctx .function_len = bgp -> tovpn_sid_locator -> function_bits_length ;
444449 ctx .argument_len = bgp -> tovpn_sid_locator -> argument_bits_length ;
445450 if (CHECK_FLAG (bgp -> tovpn_sid_locator -> flags , SRV6_LOCATOR_USID ))
446451 SET_SRV6_FLV_OP (ctx .flv .flv_ops , ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID );
@@ -508,9 +513,11 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
508513 bgp -> vpn_policy [afi ].tovpn_sid_locator -> block_bits_length ;
509514 seg6localctx .node_len =
510515 bgp -> vpn_policy [afi ].tovpn_sid_locator -> node_bits_length ;
511- seg6localctx .function_len =
512- bgp -> vpn_policy [afi ]
513- .tovpn_sid_locator -> function_bits_length ;
516+ if (CHECK_FLAG (bgp -> vpn_policy [afi ].flags , BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE ))
517+ seg6localctx .function_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
518+ else
519+ seg6localctx .function_len =
520+ bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
514521 seg6localctx .argument_len =
515522 bgp -> vpn_policy [afi ]
516523 .tovpn_sid_locator -> argument_bits_length ;
@@ -526,6 +533,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
526533 ctx .behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
527534 : ZEBRA_SEG6_LOCAL_ACTION_END_DT6 ;
528535 bgp_zebra_release_srv6_sid (& ctx , bgp -> vpn_policy [afi ].tovpn_sid_locator -> name );
536+ UNSET_FLAG (bgp -> vpn_policy [afi ].flags , BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE );
529537}
530538
531539/*
@@ -559,8 +567,10 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
559567 seg6localctx .block_len =
560568 bgp -> tovpn_sid_locator -> block_bits_length ;
561569 seg6localctx .node_len = bgp -> tovpn_sid_locator -> node_bits_length ;
562- seg6localctx .function_len =
563- bgp -> tovpn_sid_locator -> function_bits_length ;
570+ if (CHECK_FLAG (bgp -> vrf_flags , BGP_VRF_TOVPN_SID_FUNC_WIDE ))
571+ seg6localctx .function_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
572+ else
573+ seg6localctx .function_len = bgp -> tovpn_sid_locator -> function_bits_length ;
564574 seg6localctx .argument_len =
565575 bgp -> tovpn_sid_locator -> argument_bits_length ;
566576 }
@@ -573,6 +583,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
573583 ctx .vrf_id = bgp -> vrf_id ;
574584 ctx .behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46 ;
575585 bgp_zebra_release_srv6_sid (& ctx , bgp -> tovpn_sid_locator -> name );
586+ UNSET_FLAG (bgp -> vrf_flags , BGP_VRF_TOVPN_SID_FUNC_WIDE );
576587}
577588
578589/*
@@ -704,26 +715,37 @@ bool srv6_sid_compose(struct in6_addr *sid_value, struct srv6_locator *locator,
704715 uint8_t offset = 0 ;
705716 uint8_t func_len = 0 , shift_len = 0 ;
706717 uint32_t sid_func_max = 0 ;
718+ bool store_in_label = true;
707719
708720 if (!locator || !sid_value )
709721 return false;
710722
711- if (locator -> function_bits_length >
712- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH ) {
723+ if (locator -> function_bits_length > BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ) {
713724 if (debug )
714725 zlog_debug ("%s: invalid SRv6 Locator (%pFX): Function Length must be less or equal to %d" ,
715726 __func__ , & locator -> prefix ,
716- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH );
727+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL );
717728 return false;
718729 }
719730
720731 /* Max value that can be encoded in the Function part of the SID */
721- sid_func_max = (1 << locator -> function_bits_length ) - 1 ;
732+ if ((CHECK_FLAG (locator -> flags , SRV6_LOCATOR_F3216 ) ||
733+ CHECK_FLAG (locator -> flags , SRV6_LOCATOR_F4816 )) &&
734+ sid_func > 0xFFFF ) {
735+ /* f3216 and f4816 supports ewlib. increase sid_func_max */
736+ sid_func_max = 0xffffffff ;
737+ store_in_label = false;
738+ } else if (locator -> function_bits_length == BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP )
739+ /* shifting 32 bits over a 32 bit is not possible. directly encode func_max */
740+ sid_func_max = 0xffffffff ;
741+ else
742+ sid_func_max = (1 << locator -> function_bits_length ) - 1 ;
743+
722744
723745 if (sid_func > sid_func_max ) {
724746 if (debug )
725- zlog_debug ("%s: invalid SRv6 Locator (%pFX): Function Length is too short to support specified function (%u)" ,
726- __func__ , & locator -> prefix , sid_func );
747+ zlog_debug ("%s: invalid SRv6 Locator (%pFX): Function Length is too short (%u) to support specified function (%u)" ,
748+ __func__ , & locator -> prefix , sid_func_max , sid_func );
727749 return false;
728750 }
729751
@@ -735,38 +757,46 @@ bool srv6_sid_compose(struct in6_addr *sid_value, struct srv6_locator *locator,
735757 /* First, we put the locator (LOC) in the most significant bits of sid_value */
736758 * sid_value = locator -> prefix .prefix ;
737759
760+ if (sid_exist (bgp_get_default (), sid_value )) {
761+ zlog_warn ("%s: skipped to allocate SRv6 SID (%pFX): SID %pI6 already in use" ,
762+ __func__ , & locator -> prefix , sid_value );
763+ return false;
764+ }
765+
738766 /*
739767 * Then, we compute the offset at which we have to place the function (FUNC).
740768 * FUNC will be placed immediately after LOC, i.e. at block_bits_length + node_bits_length
741769 */
742770 offset = locator -> block_bits_length + locator -> node_bits_length ;
743771
744- /*
745- * The FUNC part of the SID is advertised in the label field of SRv6 Service TLV.
746- * (see SID Transposition Scheme, RFC 9252 section #4).
747- * Therefore, we need to encode the FUNC in the most significant bits of the
748- * 20-bit label.
749- */
750- func_len = locator -> function_bits_length ;
751- shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len ;
752-
753- label = sid_func << shift_len ;
754- if (label < MPLS_LABEL_UNRESERVED_MIN ) {
755- if (debug )
756- zlog_debug ("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use" ,
757- __func__ , & locator -> prefix , label );
758- return false;
759- }
760-
761- if (sid_exist (bgp_get_default (), sid_value )) {
762- zlog_warn ("%s: skipped to allocate SRv6 SID (%pFX): SID %pI6 already in use" ,
763- __func__ , & locator -> prefix , sid_value );
764- return false;
772+ if (store_in_label )
773+ func_len = locator -> function_bits_length ;
774+ else
775+ func_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
776+ if (store_in_label && func_len <= BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL ) {
777+ /*
778+ * The FUNC part of the SID is advertised in the label field of SRv6 Service TLV.
779+ * (see SID Transposition Scheme, RFC 9252 section #4).
780+ * Therefore, we need to encode the FUNC in the most significant bits of the
781+ * 20-bit label.
782+ */
783+ shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL - func_len ;
784+ label = sid_func << shift_len ;
785+ if (label < MPLS_LABEL_UNRESERVED_MIN ) {
786+ if (debug )
787+ zlog_debug ("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use" ,
788+ __func__ , & locator -> prefix , label );
789+ return false;
790+ }
791+ /* Finally, we put the FUNC in sid_value at the computed offset */
792+ transpose_sid (sid_value , label , offset , func_len ,
793+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL );
794+ } else {
795+ label = sid_func ;
796+ transpose_sid (sid_value , label , offset , func_len ,
797+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP );
765798 }
766799
767- /* Finally, we put the FUNC in sid_value at the computed offset */
768- transpose_sid (sid_value , label , offset , func_len );
769-
770800 return true;
771801}
772802
@@ -995,6 +1025,7 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
9951025 ctx .behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
9961026 : ZEBRA_SEG6_LOCAL_ACTION_END_DT6 ;
9971027 bgp_zebra_release_srv6_sid (& ctx , bgp_vrf -> vpn_policy [afi ].tovpn_sid_locator -> name );
1028+ UNSET_FLAG (bgp_vrf -> vpn_policy [afi ].flags , BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE );
9981029
9991030 sid_unregister (bgp_vpn , bgp_vrf -> vpn_policy [afi ].tovpn_sid );
10001031 XFREE (MTYPE_BGP_SRV6_SID , bgp_vrf -> vpn_policy [afi ].tovpn_sid );
@@ -1041,6 +1072,7 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
10411072 ctx .vrf_id = bgp_vrf -> vrf_id ;
10421073 ctx .behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46 ;
10431074 bgp_zebra_release_srv6_sid (& ctx , bgp_vrf -> tovpn_sid_locator -> name );
1075+ UNSET_FLAG (bgp_vrf -> vrf_flags , BGP_VRF_TOVPN_SID_FUNC_WIDE );
10441076
10451077 sid_unregister (bgp_vpn , bgp_vrf -> tovpn_sid );
10461078 XFREE (MTYPE_BGP_SRV6_SID , bgp_vrf -> tovpn_sid );
@@ -1086,13 +1118,13 @@ void delete_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
10861118 * |
10871119 * offset from MSB
10881120 */
1089- void transpose_sid (struct in6_addr * sid , uint32_t label , uint8_t offset ,
1090- uint8_t len )
1121+ void transpose_sid (struct in6_addr * sid , uint32_t label , uint8_t offset , uint8_t len ,
1122+ uint8_t len_max )
10911123{
10921124 for (uint8_t idx = 0 ; idx < len ; idx ++ ) {
10931125 uint8_t tidx = offset + idx ;
10941126 sid -> s6_addr [tidx / 8 ] &= ~(0x1 << (7 - tidx % 8 ));
1095- if (label >> (19 - idx ) & 0x1 )
1127+ if (label >> (len_max - 1 - idx ) & 0x1 )
10961128 sid -> s6_addr [tidx / 8 ] |= 0x1 << (7 - tidx % 8 );
10971129 }
10981130}
@@ -1716,7 +1748,7 @@ static bool vpn_leak_from_vrf_fill_srv6(struct attr *attr, struct bgp *from_bgp,
17161748 mpls_label_t * label )
17171749{
17181750 /* Set SID for SRv6 VPN */
1719- if (from_bgp -> vpn_policy [afi ].tovpn_sid_locator ) {
1751+ if (from_bgp -> vpn_policy [afi ].tovpn_sid_locator && from_bgp -> vpn_policy [ afi ]. tovpn_sid ) {
17201752 struct srv6_locator * locator = from_bgp -> vpn_policy [afi ].tovpn_sid_locator ;
17211753
17221754 encode_label (from_bgp -> vpn_policy [afi ].tovpn_sid_transpose_label , label );
@@ -1734,22 +1766,32 @@ static bool vpn_leak_from_vrf_fill_srv6(struct attr *attr, struct bgp *from_bgp,
17341766 from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> block_bits_length ;
17351767 attr -> srv6_l3service -> loc_node_len =
17361768 from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> node_bits_length ;
1737- attr -> srv6_l3service -> func_len =
1738- from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
1769+ if (CHECK_FLAG (from_bgp -> vpn_policy [afi ].flags , BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE ))
1770+ attr -> srv6_l3service -> func_len =
1771+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
1772+ else
1773+ attr -> srv6_l3service -> func_len =
1774+ from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
17391775 attr -> srv6_l3service -> arg_len =
17401776 from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> argument_bits_length ;
1741- attr -> srv6_l3service -> transposition_len =
1742- from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
1743- attr -> srv6_l3service -> transposition_offset =
1744- from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> block_bits_length +
1745- from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> node_bits_length ;
1746- ;
1747- memcpy (& attr -> srv6_l3service -> sid ,
1748- & from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> prefix .prefix ,
1749- sizeof (struct in6_addr ));
1777+ if (attr -> srv6_l3service -> func_len >
1778+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL ) {
1779+ attr -> srv6_l3service -> transposition_len = 0 ;
1780+ attr -> srv6_l3service -> transposition_offset = 0 ;
1781+ IPV6_ADDR_COPY (& attr -> srv6_l3service -> sid ,
1782+ from_bgp -> vpn_policy [afi ].tovpn_sid );
1783+ } else {
1784+ attr -> srv6_l3service -> transposition_len =
1785+ from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> function_bits_length ;
1786+ attr -> srv6_l3service -> transposition_offset =
1787+ from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> block_bits_length +
1788+ from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> node_bits_length ;
1789+ IPV6_ADDR_COPY (& attr -> srv6_l3service -> sid ,
1790+ & from_bgp -> vpn_policy [afi ].tovpn_sid_locator -> prefix .prefix );
1791+ }
17501792 return true;
17511793 }
1752- if (from_bgp -> tovpn_sid_locator ) {
1794+ if (from_bgp -> tovpn_sid_locator && from_bgp -> tovpn_sid ) {
17531795 struct srv6_locator * locator = from_bgp -> tovpn_sid_locator ;
17541796
17551797 encode_label (from_bgp -> tovpn_sid_transpose_label , label );
@@ -1763,15 +1805,27 @@ static bool vpn_leak_from_vrf_fill_srv6(struct attr *attr, struct bgp *from_bgp,
17631805 attr -> srv6_l3service -> loc_block_len =
17641806 from_bgp -> tovpn_sid_locator -> block_bits_length ;
17651807 attr -> srv6_l3service -> loc_node_len = from_bgp -> tovpn_sid_locator -> node_bits_length ;
1766- attr -> srv6_l3service -> func_len = from_bgp -> tovpn_sid_locator -> function_bits_length ;
1808+ if (CHECK_FLAG (from_bgp -> vrf_flags , BGP_VRF_TOVPN_SID_FUNC_WIDE ))
1809+ attr -> srv6_l3service -> func_len =
1810+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_BGP ;
1811+ else
1812+ attr -> srv6_l3service -> func_len =
1813+ from_bgp -> tovpn_sid_locator -> function_bits_length ;
17671814 attr -> srv6_l3service -> arg_len = from_bgp -> tovpn_sid_locator -> argument_bits_length ;
1768- attr -> srv6_l3service -> transposition_len =
1769- from_bgp -> tovpn_sid_locator -> function_bits_length ;
1770- attr -> srv6_l3service -> transposition_offset =
1771- from_bgp -> tovpn_sid_locator -> block_bits_length +
1772- from_bgp -> tovpn_sid_locator -> node_bits_length ;
1773- memcpy (& attr -> srv6_l3service -> sid , & from_bgp -> tovpn_sid_locator -> prefix .prefix ,
1774- sizeof (struct in6_addr ));
1815+ if (attr -> srv6_l3service -> func_len >
1816+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH_FOR_LABEL ) {
1817+ attr -> srv6_l3service -> transposition_len = 0 ;
1818+ attr -> srv6_l3service -> transposition_offset = 0 ;
1819+ IPV6_ADDR_COPY (& attr -> srv6_l3service -> sid , from_bgp -> tovpn_sid );
1820+ } else {
1821+ attr -> srv6_l3service -> transposition_len =
1822+ from_bgp -> tovpn_sid_locator -> function_bits_length ;
1823+ attr -> srv6_l3service -> transposition_offset =
1824+ from_bgp -> tovpn_sid_locator -> block_bits_length +
1825+ from_bgp -> tovpn_sid_locator -> node_bits_length ;
1826+ IPV6_ADDR_COPY (& attr -> srv6_l3service -> sid ,
1827+ & from_bgp -> tovpn_sid_locator -> prefix .prefix );
1828+ }
17751829 return true;
17761830 }
17771831 return false;
0 commit comments