github.com/osrg/gobgp/v3@v3.30.0/pkg/packet/bgp/prefix_sid.go (about) 1 package bgp 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/json" 7 "fmt" 8 "net" 9 "net/netip" 10 ) 11 12 const ( 13 prefixSIDtlvHdrLen = 4 14 ) 15 16 // BGP Prefix-SID TLV Types 17 // https://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-prefix-sid-tlv-types 18 type TLVType uint8 19 20 const ( 21 _ TLVType = iota // Reserved 22 TLVTypeLavelIndex 23 _ // Deprecated 24 TLVTypeOriginatorSRGB 25 _ // Deprecated 26 TLVTypeSRv6L3Service 27 TLVTypeSRv6L2Service 28 ) 29 30 type TLV struct { 31 Type TLVType 32 Length uint16 33 } 34 35 func (t *TLV) Len() int { 36 return int(t.Length) + 3 // Type(1) + Length(2) 37 } 38 39 func (t *TLV) Serialize(value []byte) ([]byte, error) { 40 if len(value) != int(t.Len()) { 41 return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") 42 } 43 p := 0 44 value[p] = byte(t.Type) 45 p++ 46 binary.BigEndian.PutUint16(value[p:p+2], uint16(t.Length)) 47 return value, nil 48 } 49 50 func (t *TLV) DecodeFromBytes(data []byte) ([]byte, error) { 51 if len(data) < 3 { 52 return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed") 53 } 54 p := 0 55 t.Type = TLVType(data[p]) 56 p++ 57 t.Length = binary.BigEndian.Uint16(data[p : p+2]) 58 p += 2 59 60 if len(data[p:]) < int(t.Length) { 61 return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed") 62 } 63 return data[p : p+int(t.Length)], nil 64 } 65 66 // PrefixSIDTLVInterface defines standard set of methods to handle Prefix SID attribute's TLVs 67 type PrefixSIDTLVInterface interface { 68 Len() int 69 DecodeFromBytes([]byte) error 70 Serialize() ([]byte, error) 71 String() string 72 MarshalJSON() ([]byte, error) 73 } 74 75 type PrefixSIDAttribute struct { 76 TLVs []PrefixSIDTLVInterface 77 } 78 79 type PathAttributePrefixSID struct { 80 PathAttribute 81 TLVs []PrefixSIDTLVInterface 82 } 83 84 func NewPathAttributePrefixSID(values ...PrefixSIDTLVInterface) *PathAttributePrefixSID { 85 var l int 86 for _, v := range values { 87 l += v.Len() 88 } 89 return &PathAttributePrefixSID{ 90 PathAttribute: PathAttribute{ 91 Flags: getPathAttrFlags(BGP_ATTR_TYPE_PREFIX_SID, l), 92 Type: BGP_ATTR_TYPE_PREFIX_SID, 93 Length: uint16(l), 94 }, 95 TLVs: values, 96 } 97 } 98 99 func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { 100 tlvs, err := p.PathAttribute.DecodeFromBytes(data) 101 if err != nil { 102 return err 103 } 104 105 for len(tlvs) >= prefixSIDtlvHdrLen { 106 t := &TLV{} 107 _, err := t.DecodeFromBytes(tlvs) 108 if err != nil { 109 return err 110 } 111 112 var tlv PrefixSIDTLVInterface 113 switch t.Type { 114 case TLVTypeSRv6L3Service, TLVTypeSRv6L2Service: 115 tlv = &SRv6ServiceTLV{ 116 SubTLVs: make([]PrefixSIDTLVInterface, 0), 117 } 118 default: 119 tlvs = tlvs[t.Len():] 120 continue 121 } 122 123 if err := tlv.DecodeFromBytes(tlvs); err != nil { 124 return err 125 } 126 tlvs = tlvs[t.Len():] 127 p.TLVs = append(p.TLVs, tlv) 128 } 129 130 return nil 131 } 132 133 func (p *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) { 134 buf := make([]byte, 0) 135 for _, tlv := range p.TLVs { 136 s, err := tlv.Serialize() 137 if err != nil { 138 return nil, err 139 } 140 buf = append(buf, s...) 141 } 142 143 return p.PathAttribute.Serialize(buf) 144 } 145 146 func (p *PathAttributePrefixSID) String() string { 147 var buf bytes.Buffer 148 149 for _, tlv := range p.TLVs { 150 buf.WriteString(fmt.Sprintf("%s ", tlv.String())) 151 } 152 153 return fmt.Sprintf("{Prefix SID attributes: %s}", buf.String()) 154 } 155 156 func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) { 157 return json.Marshal(struct { 158 Type BGPAttrType `json:"type"` 159 Flags BGPAttrFlag `json:"flags"` 160 PrefixSIDAttribute 161 }{ 162 p.GetType(), 163 p.GetFlags(), 164 *p.Extract(), 165 }) 166 } 167 168 func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute { 169 psid := &PrefixSIDAttribute{ 170 TLVs: make([]PrefixSIDTLVInterface, 0), 171 } 172 psid.TLVs = append(psid.TLVs, p.TLVs...) 173 174 return psid 175 } 176 177 // SRv6L3Service defines the structure of SRv6 L3 Service object 178 type SRv6L3Service struct { 179 SubTLVs []PrefixSIDTLVInterface 180 } 181 182 // SRv6L3ServiceAttribute defines the structure of SRv6 L3 Service attribute 183 // Deprecated: Use SRv6ServiceTLV instead. 184 type SRv6L3ServiceAttribute struct { 185 TLV 186 SubTLVs []PrefixSIDTLVInterface 187 } 188 189 func (s *SRv6L3ServiceAttribute) Len() int { 190 return int(s.Length) + prefixSIDtlvHdrLen 191 } 192 193 func (s *SRv6L3ServiceAttribute) Serialize() ([]byte, error) { 194 buf := make([]byte, s.Length+3) 195 p := 4 196 for _, tlv := range s.SubTLVs { 197 s, err := tlv.Serialize() 198 if err != nil { 199 return nil, err 200 } 201 copy(buf[p:p+len(s)], s) 202 p += len(s) 203 } 204 return s.TLV.Serialize(buf) 205 } 206 207 func (s *SRv6L3ServiceAttribute) DecodeFromBytes(data []byte) error { 208 stlvs, err := s.TLV.DecodeFromBytes(data) 209 if err != nil { 210 return err 211 } 212 stlvs = stlvs[1:] // RESERVED(1) 213 214 for len(stlvs) >= subTLVHdrLen { 215 t := &SubTLV{} 216 _, err := t.DecodeFromBytes(stlvs) 217 if err != nil { 218 return err 219 } 220 221 var stlv PrefixSIDTLVInterface 222 switch t.Type { 223 case 1: 224 stlv = &SRv6InformationSubTLV{ 225 SubSubTLVs: make([]PrefixSIDTLVInterface, 0), 226 } 227 default: 228 data = data[t.Len():] 229 continue 230 } 231 232 if err := stlv.DecodeFromBytes(stlvs); err != nil { 233 return err 234 } 235 stlvs = stlvs[t.Len():] 236 s.SubTLVs = append(s.SubTLVs, stlv) 237 } 238 239 return nil 240 } 241 242 func (s *SRv6L3ServiceAttribute) MarshalJSON() ([]byte, error) { 243 return json.Marshal(struct { 244 Type TLVType `json:"type"` 245 SRv6L3Service 246 }{ 247 s.Type, 248 *s.Extract(), 249 }) 250 } 251 252 func (s *SRv6L3ServiceAttribute) String() string { 253 var buf bytes.Buffer 254 255 for _, tlv := range s.SubTLVs { 256 buf.WriteString(fmt.Sprintf("%s ", tlv.String())) 257 } 258 259 return fmt.Sprintf("{SRv6 L3 Service Attribute: %s}", buf.String()) 260 } 261 262 func (s *SRv6L3ServiceAttribute) Extract() *SRv6L3Service { 263 l3 := &SRv6L3Service{ 264 SubTLVs: make([]PrefixSIDTLVInterface, 0), 265 } 266 267 l3.SubTLVs = append(l3.SubTLVs, s.SubTLVs...) 268 269 return l3 270 } 271 272 const ( 273 subTLVHdrLen = 3 274 ) 275 276 type SubTLVType uint8 277 278 type SubTLV struct { 279 Type SubTLVType 280 Length uint16 281 } 282 283 func (s *SubTLV) Len() int { 284 return int(s.Length) + subTLVHdrLen 285 } 286 287 func (s *SubTLV) Serialize(value []byte) ([]byte, error) { 288 if len(value) != int(s.Length) { 289 return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") 290 } 291 // Extra byte is reserved 292 buf := make([]byte, subTLVHdrLen+len(value)) 293 buf[0] = byte(s.Type) 294 binary.BigEndian.PutUint16(buf[1:4], uint16(s.Length)) 295 // 4th reserved byte 296 copy(buf[4:], value) 297 298 return buf, nil 299 } 300 301 func (s *SubTLV) DecodeFromBytes(data []byte) ([]byte, error) { 302 if len(data) < subTLVHdrLen { 303 return nil, malformedAttrListErr("decoding failed: Prefix SID Sub TLV malformed") 304 } 305 s.Type = SubTLVType(data[0]) 306 s.Length = binary.BigEndian.Uint16(data[1:3]) 307 308 if len(data) < s.Len() { 309 return nil, malformedAttrListErr("decoding failed: Prefix SID Sub TLV malformed") 310 } 311 312 return data[subTLVHdrLen:s.Len()], nil 313 } 314 315 type SRv6InformationSTLV struct { 316 SID []byte `json:"sid"` 317 Flags uint8 `json:"flags"` 318 EndpointBehavior uint16 `json:"endpoint_behavior"` 319 SubSubTLVs []PrefixSIDTLVInterface `json:"sub_sub_tlvs,omitempty"` 320 } 321 322 // SRv6InformationSubTLV defines a structure of SRv6 Information Sub TLV (type 1) object 323 // https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1 324 type SRv6InformationSubTLV struct { 325 SubTLV 326 SID []byte 327 Flags uint8 328 EndpointBehavior uint16 329 SubSubTLVs []PrefixSIDTLVInterface 330 } 331 332 func NewSRv6InformationSubTLV(sid netip.Addr, behavior SRBehavior, values ...PrefixSIDTLVInterface) *SRv6InformationSubTLV { 333 l := 21 // RESERVED1(1) + SID(16) + Flags(1) + Endpoint Behavior(2) + RESERVED2(1) 334 for _, v := range values { 335 l += v.Len() 336 } 337 return &SRv6InformationSubTLV{ 338 SubTLV: SubTLV{ 339 Type: 1, 340 Length: uint16(l), 341 }, 342 SID: sid.AsSlice(), 343 Flags: 0, 344 EndpointBehavior: uint16(behavior), 345 SubSubTLVs: values, 346 } 347 } 348 349 func (s *SRv6InformationSubTLV) Len() int { 350 return int(s.Length) + subTLVHdrLen 351 } 352 353 func (s *SRv6InformationSubTLV) Serialize() ([]byte, error) { 354 buf := make([]byte, s.Length) 355 p := 0 356 copy(buf[p:], s.SID) 357 p += len(s.SID) 358 buf[p] = byte(s.Flags) 359 p++ 360 binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.EndpointBehavior)) 361 p += 2 362 // Reserved byte 363 buf[p] = 0x0 364 p++ 365 for _, sstlv := range s.SubSubTLVs { 366 sbuf, err := sstlv.Serialize() 367 if err != nil { 368 return nil, err 369 } 370 copy(buf[p:], sbuf) 371 p += len(sbuf) 372 } 373 374 return s.SubTLV.Serialize(buf) 375 } 376 377 func (s *SRv6InformationSubTLV) DecodeFromBytes(data []byte) error { 378 if len(data) < subTLVHdrLen { 379 return malformedAttrListErr("decoding failed: Prefix SID TLV malformed") 380 } 381 s.Type = SubTLVType(data[0]) 382 s.Length = binary.BigEndian.Uint16(data[1:3]) 383 // 4th reserved byte 384 p := 4 385 s.SID = make([]byte, 16) 386 copy(s.SID, data[p:p+16]) 387 p += 16 388 s.Flags = uint8(data[p]) 389 p++ 390 s.EndpointBehavior = binary.BigEndian.Uint16(data[p : p+2]) 391 p += 2 392 // reserved byte 393 p++ 394 if p+3 > len(data) { 395 // There is no Sub Sub TLVs detected, returning 396 return nil 397 } 398 stlvs := data[p:] 399 for len(stlvs) >= prefixSIDtlvHdrLen { 400 t := &SubSubTLV{} 401 _, err := t.DecodeFromBytes(stlvs) 402 if err != nil { 403 return err 404 } 405 406 var sstlv PrefixSIDTLVInterface 407 switch t.Type { 408 case 1: 409 sstlv = &SRv6SIDStructureSubSubTLV{} 410 default: 411 stlvs = stlvs[t.Len():] 412 continue 413 } 414 415 if err := sstlv.DecodeFromBytes(stlvs); err != nil { 416 return err 417 } 418 stlvs = stlvs[t.Len():] 419 s.SubSubTLVs = append(s.SubSubTLVs, sstlv) 420 } 421 422 return nil 423 } 424 425 func (s *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) { 426 return json.Marshal(struct { 427 Type SubTLVType `json:"type"` 428 SRv6InformationSTLV 429 }{ 430 s.Type, 431 *s.Extract(), 432 }) 433 } 434 435 func (s *SRv6InformationSubTLV) String() string { 436 var buf bytes.Buffer 437 buf.WriteString(fmt.Sprintf("SID: %s ", net.IP(s.SID).To16().String())) 438 buf.WriteString(fmt.Sprintf("Flag: %d ", s.Flags)) 439 buf.WriteString(fmt.Sprintf("Endpoint Behavior: %d ", s.EndpointBehavior)) 440 for _, tlv := range s.SubSubTLVs { 441 buf.WriteString(fmt.Sprintf("%s ", tlv.String())) 442 } 443 444 return fmt.Sprintf("{SRv6 Information Sub TLV: %s}", buf.String()) 445 } 446 447 func (s *SRv6InformationSubTLV) Extract() *SRv6InformationSTLV { 448 info := &SRv6InformationSTLV{ 449 SID: s.SID, 450 Flags: s.Flags, 451 EndpointBehavior: s.EndpointBehavior, 452 SubSubTLVs: make([]PrefixSIDTLVInterface, 0), 453 } 454 455 info.SubSubTLVs = append(info.SubSubTLVs, s.SubSubTLVs...) 456 457 return info 458 } 459 460 const ( 461 subSubTLVHdrLen = 3 462 ) 463 464 type SubSubTLVType uint8 465 466 type SubSubTLV struct { 467 Type SubSubTLVType 468 Length uint16 469 } 470 471 func (s *SubSubTLV) Len() int { 472 return int(s.Length) + subSubTLVHdrLen 473 } 474 475 func (s *SubSubTLV) Serialize(value []byte) ([]byte, error) { 476 if len(value) != int(s.Length) { 477 return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") 478 } 479 // Extra byte is reserved 480 buf := make([]byte, subSubTLVHdrLen+len(value)) 481 p := 0 482 buf[p] = byte(s.Type) 483 p++ 484 binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length)) 485 p += 2 486 copy(buf[p:], value) 487 488 return buf, nil 489 } 490 491 func (s *SubSubTLV) DecodeFromBytes(data []byte) ([]byte, error) { 492 if len(data) < prefixSIDtlvHdrLen { 493 return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") 494 } 495 s.Type = SubSubTLVType(data[0]) 496 s.Length = binary.BigEndian.Uint16(data[1:3]) 497 498 if len(data) < s.Len() { 499 return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") 500 } 501 502 return data[prefixSIDtlvHdrLen:s.Len()], nil 503 } 504 505 // SRv6SIDStructureSubSubTLV defines a structure of SRv6 SID Structure Sub Sub TLV (type 1) object 506 // https://www.rfc-editor.org/rfc/rfc9252.html#section-3.2.1 507 type SRv6SIDStructureSubSubTLV struct { 508 SubSubTLV 509 LocatorBlockLength uint8 510 LocatorNodeLength uint8 511 FunctionLength uint8 512 ArgumentLength uint8 513 TranspositionLength uint8 514 TranspositionOffset uint8 515 } 516 517 func NewSRv6SIDStructureSubSubTLV(lbl, lnl, fl, al, tl, to uint8) *SRv6SIDStructureSubSubTLV { 518 return &SRv6SIDStructureSubSubTLV{ 519 SubSubTLV: SubSubTLV{ 520 Type: 1, 521 Length: 6, 522 }, 523 LocatorBlockLength: lbl, 524 LocatorNodeLength: lnl, 525 FunctionLength: fl, 526 ArgumentLength: al, 527 TranspositionLength: tl, 528 TranspositionOffset: to, 529 } 530 } 531 532 func (s *SRv6SIDStructureSubSubTLV) Len() int { 533 return int(s.Length) + subSubTLVHdrLen 534 } 535 536 func (s *SRv6SIDStructureSubSubTLV) Serialize() ([]byte, error) { 537 buf := make([]byte, s.Length) 538 p := 0 539 buf[p] = s.LocatorBlockLength 540 p++ 541 buf[p] = s.LocatorNodeLength 542 p++ 543 buf[p] = s.FunctionLength 544 p++ 545 buf[p] = s.ArgumentLength 546 p++ 547 buf[p] = s.TranspositionLength 548 p++ 549 buf[p] = s.TranspositionOffset 550 551 return s.SubSubTLV.Serialize(buf) 552 } 553 554 func (s *SRv6SIDStructureSubSubTLV) DecodeFromBytes(data []byte) error { 555 if len(data) < subSubTLVHdrLen { 556 return malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") 557 } 558 s.Type = SubSubTLVType(data[0]) 559 s.Length = binary.BigEndian.Uint16(data[1:3]) 560 561 s.LocatorBlockLength = data[3] 562 s.LocatorNodeLength = data[4] 563 s.FunctionLength = data[5] 564 s.ArgumentLength = data[6] 565 s.TranspositionLength = data[7] 566 s.TranspositionOffset = data[8] 567 568 return nil 569 } 570 571 func (s *SRv6SIDStructureSubSubTLV) MarshalJSON() ([]byte, error) { 572 return json.Marshal(struct { 573 Type SubSubTLVType `json:"type"` 574 LocatorBlockLength uint8 `json:"locator_block_length"` 575 LocatorNodeLength uint8 `json:"locator_node_length"` 576 FunctionLength uint8 `json:"function_length"` 577 ArgumentLength uint8 `json:"argument_length"` 578 TranspositionLength uint8 `json:"transposition_length"` 579 TranspositionOffset uint8 `json:"transposition_offset"` 580 }{ 581 Type: s.Type, 582 LocatorBlockLength: s.LocatorBlockLength, 583 LocatorNodeLength: s.LocatorNodeLength, 584 FunctionLength: s.FunctionLength, 585 ArgumentLength: s.ArgumentLength, 586 TranspositionLength: s.TranspositionLength, 587 TranspositionOffset: s.TranspositionOffset, 588 }) 589 } 590 591 func (s *SRv6SIDStructureSubSubTLV) String() string { 592 return fmt.Sprintf("{SRv6 Structure Sub Sub TLV: [ Locator Block Length: %d, Locator Node Length: %d, Function Length: %d, Argument Length: %d, Transposition Length: %d, Transposition Offset: %d] }", 593 s.LocatorBlockLength, 594 s.LocatorNodeLength, 595 s.FunctionLength, 596 s.ArgumentLength, 597 s.TranspositionLength, 598 s.TranspositionOffset, 599 ) 600 } 601 602 // SRv6ServiceTLV represents SRv6 Service TLV. 603 // https://www.rfc-editor.org/rfc/rfc9252.html#section-2 604 type SRv6ServiceTLV struct { 605 TLV 606 SubTLVs []PrefixSIDTLVInterface 607 } 608 609 func NewSRv6ServiceTLV(t TLVType, values ...PrefixSIDTLVInterface) *SRv6ServiceTLV { 610 l := 1 // RESERVED(1) 611 for _, v := range values { 612 l += v.Len() 613 } 614 return &SRv6ServiceTLV{ 615 TLV: TLV{ 616 Type: t, 617 Length: uint16(l), 618 }, 619 SubTLVs: values, 620 } 621 } 622 623 func (s *SRv6ServiceTLV) Len() int { 624 return int(s.Length) + 3 // Type(1) + Length(2) 625 } 626 627 func (t *SRv6ServiceTLV) Serialize() ([]byte, error) { 628 buf := make([]byte, t.Len()) 629 p := 4 630 for _, tlv := range t.SubTLVs { 631 b, err := tlv.Serialize() 632 if err != nil { 633 return nil, err 634 } 635 copy(buf[p:p+len(b)], b) 636 p += len(b) 637 } 638 return t.TLV.Serialize(buf) 639 } 640 641 func (s *SRv6ServiceTLV) DecodeFromBytes(data []byte) error { 642 stlvs, err := s.TLV.DecodeFromBytes(data) 643 if err != nil { 644 return err 645 } 646 stlvs = stlvs[1:] // RESERVED(1) 647 648 for len(stlvs) >= subTLVHdrLen { 649 t := &SubTLV{} 650 _, err := t.DecodeFromBytes(stlvs) 651 if err != nil { 652 return err 653 } 654 655 var stlv PrefixSIDTLVInterface 656 switch t.Type { 657 case 1: 658 stlv = &SRv6InformationSubTLV{ 659 SubSubTLVs: make([]PrefixSIDTLVInterface, 0), 660 } 661 default: 662 data = data[t.Len():] 663 continue 664 } 665 666 if err := stlv.DecodeFromBytes(stlvs); err != nil { 667 return err 668 } 669 stlvs = stlvs[t.Len():] 670 s.SubTLVs = append(s.SubTLVs, stlv) 671 } 672 673 return nil 674 } 675 676 func (t *SRv6ServiceTLV) MarshalJSON() ([]byte, error) { 677 return json.Marshal(struct { 678 Type TLVType `json:"type"` 679 SubTLVs []PrefixSIDTLVInterface 680 }{ 681 t.Type, 682 t.SubTLVs, 683 }) 684 } 685 686 func (t *SRv6ServiceTLV) String() string { 687 var buf bytes.Buffer 688 689 for _, tlv := range t.SubTLVs { 690 buf.WriteString(fmt.Sprintf("%s ", tlv.String())) 691 } 692 693 return fmt.Sprintf("{SRv6 Service TLV: %s}", buf.String()) 694 }