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 }