github.com/osrg/gobgp/v3@v3.30.0/pkg/packet/bgp/mup.go (about)

     1  package bgp
     2  
     3  import (
     4  	"encoding/binary"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/netip"
     8  )
     9  
    10  // MUPExtended represents BGP MUP Extended Community as described in
    11  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.2
    12  type MUPExtended struct {
    13  	SubType    ExtendedCommunityAttrSubType
    14  	SegmentID2 uint16
    15  	SegmentID4 uint32
    16  }
    17  
    18  func (e *MUPExtended) Serialize() ([]byte, error) {
    19  	buf := make([]byte, 8)
    20  	buf[0] = byte(EC_TYPE_MUP)
    21  	buf[1] = byte(EC_SUBTYPE_MUP_DIRECT_SEG)
    22  	binary.BigEndian.PutUint16(buf[2:4], e.SegmentID2)
    23  	binary.BigEndian.PutUint32(buf[4:8], e.SegmentID4)
    24  	return buf, nil
    25  }
    26  
    27  func (e *MUPExtended) String() string {
    28  	return fmt.Sprintf("%d:%d", e.SegmentID2, e.SegmentID4)
    29  }
    30  
    31  func (e *MUPExtended) MarshalJSON() ([]byte, error) {
    32  	t, s := e.GetTypes()
    33  	return json.Marshal(struct {
    34  		Type      ExtendedCommunityAttrType    `json:"type"`
    35  		Subtype   ExtendedCommunityAttrSubType `json:"subtype"`
    36  		SegmentID string                       `json:"segmend_id"`
    37  	}{
    38  		Type:      t,
    39  		Subtype:   s,
    40  		SegmentID: fmt.Sprintf("%d:%d", e.SegmentID2, e.SegmentID4),
    41  	})
    42  }
    43  
    44  func (e *MUPExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) {
    45  	return EC_TYPE_MUP, EC_SUBTYPE_MUP_DIRECT_SEG
    46  }
    47  
    48  func (e *MUPExtended) Flat() map[string]string {
    49  	return map[string]string{}
    50  }
    51  
    52  func NewMUPExtended(sid2 uint16, sid4 uint32) *MUPExtended {
    53  	return &MUPExtended{
    54  		SubType:    EC_SUBTYPE_MUP_DIRECT_SEG,
    55  		SegmentID2: sid2,
    56  		SegmentID4: sid4,
    57  	}
    58  }
    59  
    60  func parseMUPExtended(data []byte) (ExtendedCommunityInterface, error) {
    61  	typ := ExtendedCommunityAttrType(data[0])
    62  	if typ != EC_TYPE_MUP {
    63  		return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("ext comm type is not EC_TYPE_MUP: %d", data[0]))
    64  	}
    65  	subType := ExtendedCommunityAttrSubType(data[1])
    66  	if subType == EC_SUBTYPE_MUP_DIRECT_SEG {
    67  		sid2 := binary.BigEndian.Uint16(data[2:4])
    68  		sid4 := binary.BigEndian.Uint32(data[4:8])
    69  		return NewMUPExtended(sid2, sid4), nil
    70  	}
    71  	return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("unknown mup subtype: %d", subType))
    72  }
    73  
    74  // BGP MUP SAFI Architecture Type as described in
    75  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1
    76  const (
    77  	MUP_ARCH_TYPE_UNDEFINED = iota
    78  	MUP_ARCH_TYPE_3GPP_5G
    79  )
    80  
    81  // BGP MUP SAFI Route Type as described in
    82  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1
    83  const (
    84  	_ = iota
    85  	MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY
    86  	MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY
    87  	MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED
    88  	MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED
    89  )
    90  
    91  type MUPRouteTypeInterface interface {
    92  	DecodeFromBytes([]byte, uint16) error
    93  	Serialize() ([]byte, error)
    94  	AFI() uint16
    95  	Len() int
    96  	String() string
    97  	MarshalJSON() ([]byte, error)
    98  	rd() RouteDistinguisherInterface
    99  }
   100  
   101  func getMUPRouteType(at uint8, rt uint16) (MUPRouteTypeInterface, error) {
   102  	switch rt {
   103  	case MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY:
   104  		if at == MUP_ARCH_TYPE_3GPP_5G {
   105  			return &MUPInterworkSegmentDiscoveryRoute{}, nil
   106  		}
   107  	case MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY:
   108  		if at == MUP_ARCH_TYPE_3GPP_5G {
   109  			return &MUPDirectSegmentDiscoveryRoute{}, nil
   110  		}
   111  	case MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED:
   112  		if at == MUP_ARCH_TYPE_3GPP_5G {
   113  			return &MUPType1SessionTransformedRoute{}, nil
   114  		}
   115  	case MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED:
   116  		if at == MUP_ARCH_TYPE_3GPP_5G {
   117  			return &MUPType2SessionTransformedRoute{}, nil
   118  		}
   119  	}
   120  	return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Unknown MUP Architecture and Route type: %d, %d", at, rt))
   121  }
   122  
   123  type MUPNLRI struct {
   124  	PrefixDefault
   125  	Afi              uint16
   126  	ArchitectureType uint8
   127  	RouteType        uint16
   128  	Length           uint8
   129  	RouteTypeData    MUPRouteTypeInterface
   130  }
   131  
   132  func (n *MUPNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
   133  	if len(data) < 4 {
   134  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all MUPNLRI bytes available")
   135  	}
   136  	n.ArchitectureType = data[0]
   137  	n.RouteType = binary.BigEndian.Uint16(data[1:3])
   138  	n.Length = data[3]
   139  	data = data[4:]
   140  	if len(data) < int(n.Length) {
   141  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all MUPNLRI Route type bytes available")
   142  	}
   143  	r, err := getMUPRouteType(n.ArchitectureType, n.RouteType)
   144  	if err != nil {
   145  		return err
   146  	}
   147  	n.RouteTypeData = r
   148  	return n.RouteTypeData.DecodeFromBytes(data[:n.Length], n.Afi)
   149  }
   150  
   151  func (n *MUPNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
   152  	buf := make([]byte, 4)
   153  	buf[0] = n.ArchitectureType
   154  	binary.BigEndian.PutUint16(buf[1:3], n.RouteType)
   155  	buf[3] = n.Length
   156  	tbuf, err := n.RouteTypeData.Serialize()
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	return append(buf, tbuf...), nil
   161  }
   162  
   163  func (n *MUPNLRI) AFI() uint16 {
   164  	return n.Afi
   165  }
   166  
   167  func (n *MUPNLRI) SAFI() uint8 {
   168  	return SAFI_MUP
   169  }
   170  
   171  func (n *MUPNLRI) Len(options ...*MarshallingOption) int {
   172  	return int(n.Length) + 4
   173  }
   174  
   175  func (n *MUPNLRI) String() string {
   176  	if n.RouteTypeData != nil {
   177  		return n.RouteTypeData.String()
   178  	}
   179  	return fmt.Sprintf("%d:%d:%d", n.ArchitectureType, n.RouteType, n.Length)
   180  }
   181  
   182  func (n *MUPNLRI) MarshalJSON() ([]byte, error) {
   183  	return json.Marshal(struct {
   184  		ArchitectureType uint8                 `json:"arch_type"`
   185  		RouteType        uint16                `json:"route_type"`
   186  		Value            MUPRouteTypeInterface `json:"value"`
   187  	}{
   188  		ArchitectureType: n.ArchitectureType,
   189  		RouteType:        n.RouteType,
   190  		Value:            n.RouteTypeData,
   191  	})
   192  }
   193  
   194  func (n *MUPNLRI) RD() RouteDistinguisherInterface {
   195  	return n.RouteTypeData.rd()
   196  }
   197  
   198  func (l *MUPNLRI) Flat() map[string]string {
   199  	return map[string]string{}
   200  }
   201  
   202  func NewMUPNLRI(afi uint16, at uint8, rt uint16, data MUPRouteTypeInterface) *MUPNLRI {
   203  	var l uint8
   204  	if data != nil {
   205  		l = uint8(data.Len())
   206  	}
   207  	return &MUPNLRI{
   208  		Afi:              afi,
   209  		ArchitectureType: at,
   210  		RouteType:        rt,
   211  		Length:           l,
   212  		RouteTypeData:    data,
   213  	}
   214  }
   215  
   216  func TEIDString(nlri AddrPrefixInterface) string {
   217  	s := ""
   218  	switch n := nlri.(type) {
   219  	case *MUPNLRI:
   220  		switch route := n.RouteTypeData.(type) {
   221  		case *MUPType1SessionTransformedRoute:
   222  			s = route.TEID.String()
   223  		default:
   224  			s = ""
   225  		}
   226  	}
   227  	return s
   228  }
   229  
   230  func QFIString(nlri AddrPrefixInterface) string {
   231  	s := ""
   232  	switch n := nlri.(type) {
   233  	case *MUPNLRI:
   234  		switch route := n.RouteTypeData.(type) {
   235  		case *MUPType1SessionTransformedRoute:
   236  			s = fmt.Sprintf("%d", route.QFI)
   237  		default:
   238  			s = ""
   239  		}
   240  	}
   241  	return s
   242  }
   243  
   244  func EndpointString(nlri AddrPrefixInterface) string {
   245  	s := ""
   246  	switch n := nlri.(type) {
   247  	case *MUPNLRI:
   248  		switch route := n.RouteTypeData.(type) {
   249  		case *MUPType1SessionTransformedRoute:
   250  			s = route.EndpointAddress.String()
   251  		default:
   252  			s = ""
   253  		}
   254  	}
   255  	return s
   256  }
   257  
   258  // MUPInterworkSegmentDiscoveryRoute represents BGP Interwork Segment Discovery route as described in
   259  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1.1
   260  type MUPInterworkSegmentDiscoveryRoute struct {
   261  	RD     RouteDistinguisherInterface
   262  	Prefix netip.Prefix
   263  }
   264  
   265  func NewMUPInterworkSegmentDiscoveryRoute(rd RouteDistinguisherInterface, prefix netip.Prefix) *MUPNLRI {
   266  	afi := uint16(AFI_IP)
   267  	if prefix.Addr().Is6() {
   268  		afi = AFI_IP6
   269  	}
   270  	return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, &MUPInterworkSegmentDiscoveryRoute{
   271  		RD:     rd,
   272  		Prefix: prefix,
   273  	})
   274  }
   275  
   276  func (r *MUPInterworkSegmentDiscoveryRoute) DecodeFromBytes(data []byte, afi uint16) error {
   277  	r.RD = GetRouteDistinguisher(data)
   278  	p := r.RD.Len()
   279  	if len(data) < p {
   280  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid Interwork Segment Discovery Route length")
   281  	}
   282  	bits := int(data[p])
   283  	p += 1
   284  	byteLen := (bits + 7) / 8
   285  	if len(data[p:]) < byteLen {
   286  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "prefix bytes is short")
   287  	}
   288  	addrLen := 4
   289  	if afi == AFI_IP6 {
   290  		addrLen = 16
   291  	}
   292  	if bits > addrLen*8 {
   293  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "prefix length is too long")
   294  	}
   295  	b := make([]byte, addrLen)
   296  	copy(b[0:byteLen], data[p:p+byteLen])
   297  	addr, ok := netip.AddrFromSlice(b)
   298  	if !ok {
   299  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %x", data[p:]))
   300  	}
   301  	r.Prefix = netip.PrefixFrom(addr, bits)
   302  	if r.Prefix.Bits() == -1 {
   303  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %s", r.Prefix))
   304  	}
   305  	return nil
   306  }
   307  
   308  func (r *MUPInterworkSegmentDiscoveryRoute) Serialize() ([]byte, error) {
   309  	var buf []byte
   310  	var err error
   311  	if r.RD != nil {
   312  		buf, err = r.RD.Serialize()
   313  		if err != nil {
   314  			return nil, err
   315  		}
   316  	} else {
   317  		buf = make([]byte, 8)
   318  	}
   319  	buf = append(buf, uint8(r.Prefix.Bits()))
   320  	byteLen := (r.Prefix.Bits() + 7) / 8
   321  	buf = append(buf, r.Prefix.Addr().AsSlice()[:byteLen]...)
   322  	return buf, nil
   323  }
   324  
   325  func (r *MUPInterworkSegmentDiscoveryRoute) AFI() uint16 {
   326  	if r.Prefix.Addr().Is6() {
   327  		return AFI_IP6
   328  	}
   329  	return AFI_IP
   330  }
   331  
   332  func (r *MUPInterworkSegmentDiscoveryRoute) Len() int {
   333  	// RD(8) + PrefixLength(1) + Prefix(variable)
   334  	return 9 + (r.Prefix.Bits()+7)/8
   335  }
   336  
   337  func (r *MUPInterworkSegmentDiscoveryRoute) String() string {
   338  	// I-D.draft-mpmz-bess-mup-safi-01
   339  	// 3.1.1.  BGP Interwork Segment Discovery route
   340  	// For the purpose of BGP route key processing, only the RD, Prefix Length and Prefix are considered to be part of the prefix in the NLRI.
   341  	return fmt.Sprintf("[type:isd][rd:%s][prefix:%s]", r.RD, r.Prefix)
   342  }
   343  
   344  func (r *MUPInterworkSegmentDiscoveryRoute) MarshalJSON() ([]byte, error) {
   345  	return json.Marshal(struct {
   346  		RD     RouteDistinguisherInterface `json:"rd"`
   347  		Prefix string                      `json:"prefix"`
   348  	}{
   349  		RD:     r.RD,
   350  		Prefix: r.Prefix.String(),
   351  	})
   352  }
   353  
   354  func (r *MUPInterworkSegmentDiscoveryRoute) rd() RouteDistinguisherInterface {
   355  	return r.RD
   356  }
   357  
   358  // MUPDirectSegmentDiscoveryRoute represents BGP Direct Segment Discovery route as described in
   359  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1.2
   360  type MUPDirectSegmentDiscoveryRoute struct {
   361  	RD      RouteDistinguisherInterface
   362  	Address netip.Addr
   363  }
   364  
   365  func NewMUPDirectSegmentDiscoveryRoute(rd RouteDistinguisherInterface, address netip.Addr) *MUPNLRI {
   366  	afi := uint16(AFI_IP)
   367  	if address.Is6() {
   368  		afi = AFI_IP6
   369  	}
   370  	return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY, &MUPDirectSegmentDiscoveryRoute{
   371  		RD:      rd,
   372  		Address: address,
   373  	})
   374  }
   375  
   376  func (r *MUPDirectSegmentDiscoveryRoute) DecodeFromBytes(data []byte, afi uint16) error {
   377  	r.RD = GetRouteDistinguisher(data)
   378  	rdLen := r.RD.Len()
   379  	if len(data) != 12 && len(data) != 24 {
   380  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid Direct Segment Discovery Route length")
   381  	}
   382  	if len(data) == 12 {
   383  		address, ok := netip.AddrFromSlice(data[rdLen : rdLen+4])
   384  		if !ok {
   385  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Address: %s", data[rdLen:rdLen+4]))
   386  		}
   387  		r.Address = address
   388  	} else if len(data) == 24 {
   389  		address, ok := netip.AddrFromSlice(data[rdLen : rdLen+16])
   390  		if !ok {
   391  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Address: %d", data[rdLen:rdLen+16]))
   392  		}
   393  		r.Address = address
   394  	}
   395  	return nil
   396  }
   397  
   398  func (r *MUPDirectSegmentDiscoveryRoute) Serialize() ([]byte, error) {
   399  	var buf []byte
   400  	var err error
   401  	if r.RD != nil {
   402  		buf, err = r.RD.Serialize()
   403  		if err != nil {
   404  			return nil, err
   405  		}
   406  	} else {
   407  		buf = make([]byte, 8)
   408  	}
   409  	buf = append(buf, r.Address.AsSlice()...)
   410  	return buf, nil
   411  }
   412  
   413  func (r *MUPDirectSegmentDiscoveryRoute) AFI() uint16 {
   414  	if r.Address.Is6() {
   415  		return AFI_IP6
   416  	}
   417  	return AFI_IP
   418  }
   419  
   420  func (r *MUPDirectSegmentDiscoveryRoute) Len() int {
   421  	// RD(8) + Address(4 or 16)
   422  	return 8 + r.Address.BitLen()/8
   423  }
   424  
   425  func (r *MUPDirectSegmentDiscoveryRoute) String() string {
   426  	// I-D.draft-mpmz-bess-mup-safi-01
   427  	// 3.1.2.  BGP Direct Segment Discovery route
   428  	// For the purpose of BGP route key processing, only the RD and Address are considered to be part of the prefix in the NLRI.
   429  	return fmt.Sprintf("[type:dsd][rd:%s][prefix:%s]", r.RD, r.Address)
   430  }
   431  
   432  func (r *MUPDirectSegmentDiscoveryRoute) MarshalJSON() ([]byte, error) {
   433  	return json.Marshal(struct {
   434  		RD      RouteDistinguisherInterface `json:"rd"`
   435  		Address string                      `json:"address"`
   436  	}{
   437  		RD:      r.RD,
   438  		Address: r.Address.String(),
   439  	})
   440  }
   441  
   442  func (r *MUPDirectSegmentDiscoveryRoute) rd() RouteDistinguisherInterface {
   443  	return r.RD
   444  }
   445  
   446  // MUPType1SessionTransformedRoute3GPP5G represents 3GPP 5G specific Type 1 Session Transformed (ST) Route as described in
   447  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-03#section-3.1.3
   448  type MUPType1SessionTransformedRoute struct {
   449  	RD                    RouteDistinguisherInterface
   450  	Prefix                netip.Prefix
   451  	TEID                  netip.Addr
   452  	QFI                   uint8
   453  	EndpointAddressLength uint8
   454  	EndpointAddress       netip.Addr
   455  	SourceAddressLength   uint8
   456  	SourceAddress         *netip.Addr
   457  }
   458  
   459  func NewMUPType1SessionTransformedRoute(rd RouteDistinguisherInterface, prefix netip.Prefix, teid netip.Addr, qfi uint8, ea netip.Addr, sa *netip.Addr) *MUPNLRI {
   460  	afi := uint16(AFI_IP)
   461  	if prefix.Addr().Is6() {
   462  		afi = uint16(AFI_IP6)
   463  	}
   464  	r := &MUPType1SessionTransformedRoute{
   465  		RD:                    rd,
   466  		Prefix:                prefix,
   467  		TEID:                  teid,
   468  		QFI:                   qfi,
   469  		EndpointAddressLength: uint8(ea.BitLen()),
   470  		EndpointAddress:       ea,
   471  	}
   472  	if sa != nil {
   473  		r.SourceAddressLength = uint8(sa.BitLen())
   474  		r.SourceAddress = sa
   475  	}
   476  	return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED, r)
   477  }
   478  
   479  func (r *MUPType1SessionTransformedRoute) DecodeFromBytes(data []byte, afi uint16) error {
   480  	r.RD = GetRouteDistinguisher(data)
   481  	p := r.RD.Len()
   482  	if len(data) < p {
   483  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid 3GPP 5G specific Type 1 Session Transformed Route length")
   484  	}
   485  	prefixLength := int(data[p])
   486  	p += 1
   487  	addrLen := 0
   488  	switch afi {
   489  	case AFI_IP:
   490  		if prefixLength > 32 {
   491  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix length: %d", prefixLength))
   492  		}
   493  		addrLen = 4
   494  	case AFI_IP6:
   495  		if prefixLength > 128 {
   496  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix length: %d", prefixLength))
   497  		}
   498  		addrLen = 16
   499  	default:
   500  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid AFI: %d", afi))
   501  	}
   502  	byteLen := (prefixLength + 7) / 8
   503  	b := make([]byte, addrLen)
   504  	copy(b[0:byteLen], data[p:p+byteLen])
   505  	addr, ok := netip.AddrFromSlice(b)
   506  	if !ok {
   507  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %x", b))
   508  	}
   509  	r.Prefix = netip.PrefixFrom(addr, prefixLength)
   510  	p += byteLen
   511  	r.TEID, ok = netip.AddrFromSlice(data[p : p+4])
   512  	if !ok {
   513  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid TEID: %x", r.TEID))
   514  	}
   515  	p += 4
   516  	r.QFI = data[p]
   517  	p += 1
   518  	r.EndpointAddressLength = data[p]
   519  	p += 1
   520  	if r.EndpointAddressLength == 32 || r.EndpointAddressLength == 128 {
   521  		ea, ok := netip.AddrFromSlice(data[p : p+int(r.EndpointAddressLength/8)])
   522  		if !ok {
   523  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address: %x", data[p:p+int(r.EndpointAddressLength/8)]))
   524  		}
   525  		r.EndpointAddress = ea
   526  	} else {
   527  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address length: %d", r.EndpointAddressLength))
   528  	}
   529  	p += int(r.EndpointAddressLength / 8)
   530  	r.SourceAddressLength = data[p]
   531  	p += 1
   532  	if r.SourceAddressLength == 32 || r.SourceAddressLength == 128 {
   533  		sa, ok := netip.AddrFromSlice(data[p : p+int(r.SourceAddressLength/8)])
   534  		if !ok {
   535  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Source Address: %x", data[p:p+int(r.SourceAddressLength/8)]))
   536  		}
   537  		r.SourceAddress = &sa
   538  	}
   539  	return nil
   540  }
   541  
   542  func (r *MUPType1SessionTransformedRoute) Serialize() ([]byte, error) {
   543  	var buf []byte
   544  	var err error
   545  	if r.RD != nil {
   546  		buf, err = r.RD.Serialize()
   547  		if err != nil {
   548  			return nil, err
   549  		}
   550  	} else {
   551  		buf = make([]byte, 8)
   552  	}
   553  	buf = append(buf, byte(r.Prefix.Bits()))
   554  	byteLen := (r.Prefix.Bits() + 7) / 8
   555  	buf = append(buf, r.Prefix.Addr().AsSlice()[:byteLen]...)
   556  	buf = append(buf, r.TEID.AsSlice()...)
   557  	buf = append(buf, r.QFI)
   558  	buf = append(buf, r.EndpointAddressLength)
   559  	buf = append(buf, r.EndpointAddress.AsSlice()...)
   560  	buf = append(buf, r.SourceAddressLength)
   561  	if r.SourceAddressLength > 0 {
   562  		buf = append(buf, r.SourceAddress.AsSlice()...)
   563  	}
   564  	return buf, nil
   565  }
   566  
   567  func (r *MUPType1SessionTransformedRoute) AFI() uint16 {
   568  	if r.Prefix.Addr().Is6() {
   569  		return AFI_IP6
   570  	}
   571  	return AFI_IP
   572  }
   573  
   574  func (r *MUPType1SessionTransformedRoute) Len() int {
   575  	// RD(8) + PrefixLength(1) + Prefix(variable)
   576  	// + TEID(4) + QFI(1) + EndpointAddressLength(1) + EndpointAddress(4 or 16) + SourceAddressLength(1) + SourceAddress(4 or 16)
   577  	l := 16 + (r.Prefix.Bits()+7)/8 + int(r.EndpointAddressLength/8)
   578  	if r.SourceAddressLength > 0 {
   579  		l += int(r.SourceAddressLength / 8)
   580  	}
   581  	return l
   582  }
   583  
   584  func (r *MUPType1SessionTransformedRoute) String() string {
   585  	// I-D.draft-mpmz-bess-mup-safi-01
   586  	// 3.1.3.  BGP Type 1 Session Transformed (ST) Route
   587  	// For the purpose of BGP route key processing, only the RD, Prefix Length and Prefix are considered to be part of the prefix in the NLRI.
   588  	return fmt.Sprintf("[type:t1st][rd:%s][prefix:%s]", r.RD, r.Prefix)
   589  }
   590  
   591  func (r *MUPType1SessionTransformedRoute) MarshalJSON() ([]byte, error) {
   592  	d := struct {
   593  		RD              RouteDistinguisherInterface `json:"rd"`
   594  		Prefix          string                      `json:"prefix"`
   595  		TEID            string                      `json:"teid"`
   596  		QFI             uint8                       `json:"qfi"`
   597  		EndpointAddress string                      `json:"endpoint_address"`
   598  		SourceAddress   string                      `json:"source_address"`
   599  	}{
   600  		RD:              r.RD,
   601  		Prefix:          r.Prefix.String(),
   602  		TEID:            r.TEID.String(),
   603  		QFI:             r.QFI,
   604  		EndpointAddress: r.EndpointAddress.String(),
   605  	}
   606  	if r.SourceAddress != nil {
   607  		d.SourceAddress = r.SourceAddress.String()
   608  	}
   609  	return json.Marshal(d)
   610  }
   611  
   612  func (r *MUPType1SessionTransformedRoute) rd() RouteDistinguisherInterface {
   613  	return r.RD
   614  }
   615  
   616  // MUPType2SessionTransformedRoute represents 3GPP 5G specific Type 2 Session Transformed (ST) Route as described in
   617  // https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1.4
   618  type MUPType2SessionTransformedRoute struct {
   619  	RD                    RouteDistinguisherInterface
   620  	EndpointAddressLength uint8
   621  	EndpointAddress       netip.Addr
   622  	TEID                  netip.Addr
   623  }
   624  
   625  func NewMUPType2SessionTransformedRoute(rd RouteDistinguisherInterface, eaLen uint8, ea netip.Addr, teid netip.Addr) *MUPNLRI {
   626  	afi := uint16(AFI_IP)
   627  	if ea.Is6() {
   628  		afi = AFI_IP6
   629  	}
   630  	return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, &MUPType2SessionTransformedRoute{
   631  		RD:                    rd,
   632  		EndpointAddressLength: eaLen,
   633  		EndpointAddress:       ea,
   634  		TEID:                  teid,
   635  	})
   636  }
   637  
   638  func (r *MUPType2SessionTransformedRoute) DecodeFromBytes(data []byte, afi uint16) error {
   639  	r.RD = GetRouteDistinguisher(data)
   640  	p := r.RD.Len()
   641  	if len(data) < p {
   642  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid 3GPP 5G specific Type 2 Session Transformed Route length")
   643  	}
   644  	r.EndpointAddressLength = data[p]
   645  	if (afi == AFI_IP && r.EndpointAddressLength > 64) || (afi == AFI_IP6 && r.EndpointAddressLength > 160) {
   646  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address Length: %d", r.EndpointAddressLength))
   647  	}
   648  	p += 1
   649  	var ea netip.Addr
   650  	var ok bool
   651  	teidLen := 0
   652  	switch afi {
   653  	case AFI_IP:
   654  		ea, ok = netip.AddrFromSlice(data[p : p+4])
   655  		if !ok {
   656  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address: %x", data[p:p+int(r.EndpointAddressLength/8)]))
   657  		}
   658  		p += 4
   659  		teidLen = int(r.EndpointAddressLength) - 32
   660  	case AFI_IP6:
   661  		ea, ok = netip.AddrFromSlice(data[p : p+16])
   662  		if !ok {
   663  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address: %x", data[p:p+int(r.EndpointAddressLength/8)]))
   664  		}
   665  		p += 16
   666  		teidLen = int(r.EndpointAddressLength) - 128
   667  	default:
   668  		return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid AFI: %d", afi))
   669  	}
   670  	r.EndpointAddress = ea
   671  	if teidLen > 0 {
   672  		l := (teidLen + 7) / 8
   673  		b := make([]byte, 4)
   674  		copy(b[:l], data[p:p+l])
   675  		a, ok := netip.AddrFromSlice(b)
   676  		if !ok {
   677  			return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid TEID: %x", data[p:p+l]))
   678  		}
   679  		r.TEID = a
   680  	} else {
   681  		r.TEID = netip.AddrFrom4([4]byte{0, 0, 0, 0})
   682  	}
   683  	return nil
   684  }
   685  
   686  func (r *MUPType2SessionTransformedRoute) Serialize() ([]byte, error) {
   687  	var buf []byte
   688  	var err error
   689  	if r.RD != nil {
   690  		buf, err = r.RD.Serialize()
   691  		if err != nil {
   692  			return nil, err
   693  		}
   694  	} else {
   695  		buf = make([]byte, 8)
   696  	}
   697  	buf = append(buf, r.EndpointAddressLength)
   698  	buf = append(buf, r.EndpointAddress.AsSlice()...)
   699  	teidLen := int(r.EndpointAddressLength) - r.EndpointAddress.BitLen()
   700  	if teidLen > 0 {
   701  		byteLen := (teidLen + 7) / 8
   702  		buf = append(buf, r.TEID.AsSlice()[:byteLen]...)
   703  	}
   704  	return buf, nil
   705  }
   706  
   707  func (r *MUPType2SessionTransformedRoute) AFI() uint16 {
   708  	if r.EndpointAddress.Is6() {
   709  		return AFI_IP6
   710  	}
   711  	return AFI_IP
   712  }
   713  
   714  func (r *MUPType2SessionTransformedRoute) Len() int {
   715  	// RD(8) + EndpointAddressLength(1) + EndpointAddress(4 or 16)
   716  	// + TEID(4)
   717  	// Endpoint Address Length includes TEID Length
   718  	return 9 + int(r.EndpointAddressLength+7)/8
   719  }
   720  
   721  func (r *MUPType2SessionTransformedRoute) String() string {
   722  	// I-D.draft-mpmz-bess-mup-safi-01
   723  	// 3.1.4.  BGP Type 2 Session Transformed (ST) Route
   724  	// For the purpose of BGP route key processing, only the RD, Endpoint Address and Architecture specific Endpoint Identifier are considered to be part of the prefix in the NLRI.
   725  	return fmt.Sprintf("[type:t2st][rd:%s][endpoint-address-length:%d][endpoint:%s][teid:%s]", r.RD, r.EndpointAddressLength, r.EndpointAddress, r.TEID)
   726  }
   727  
   728  func (r *MUPType2SessionTransformedRoute) MarshalJSON() ([]byte, error) {
   729  	return json.Marshal(struct {
   730  		RD                    RouteDistinguisherInterface `json:"rd"`
   731  		EndpointAddressLength uint8                       `json:"endpoint_address_length"`
   732  		EndpointAddress       string                      `json:"endpoint_address"`
   733  		TEID                  string                      `json:"teid"`
   734  	}{
   735  		RD:                    r.RD,
   736  		EndpointAddressLength: r.EndpointAddressLength,
   737  		EndpointAddress:       r.EndpointAddress.String(),
   738  		TEID:                  r.TEID.String(),
   739  	})
   740  }
   741  
   742  func (r *MUPType2SessionTransformedRoute) rd() RouteDistinguisherInterface {
   743  	return r.RD
   744  }