diff options
Diffstat (limited to 'pkg/packet/bgp')
-rw-r--r-- | pkg/packet/bgp/prefix_sid.go | 270 | ||||
-rw-r--r-- | pkg/packet/bgp/prefix_sid_sstlv.go | 107 | ||||
-rw-r--r-- | pkg/packet/bgp/prefix_sid_sstlv_test.go | 33 | ||||
-rw-r--r-- | pkg/packet/bgp/prefix_sid_stlv_test.go | 33 | ||||
-rw-r--r-- | pkg/packet/bgp/prefix_sid_test.go | 54 |
5 files changed, 288 insertions, 209 deletions
diff --git a/pkg/packet/bgp/prefix_sid.go b/pkg/packet/bgp/prefix_sid.go index 1642b87f..6a3f37b9 100644 --- a/pkg/packet/bgp/prefix_sid.go +++ b/pkg/packet/bgp/prefix_sid.go @@ -11,20 +11,6 @@ const ( prefixSIDtlvHdrLen = 4 ) -// PrefixSIDTLVInterface defines standard set of methods to handle Prefix SID attribute's TLVs -type PrefixSIDTLVInterface interface { - Len() int - DecodeFromBytes([]byte) error - Serialize() ([]byte, error) - String() string - MarshalJSON() ([]byte, error) -} - -type PathAttributePrefixSID struct { - PathAttribute - TLVs []PrefixSIDTLVInterface -} - type TLVType uint8 type TLV struct { @@ -34,7 +20,7 @@ type TLV struct { } func (s *TLV) Len() int { - return int(s.Length) + tlvHdrLen - 1 + return int(s.Length) + tlvHdrLen - 1 // Extra reserved byte in the header } func (s *TLV) Serialize(value []byte) ([]byte, error) { @@ -70,8 +56,21 @@ func (s *TLV) DecodeFromBytes(data []byte) ([]byte, error) { return data[prefixSIDtlvHdrLen:s.Len()], nil } +// PrefixSIDTLVInterface defines standard set of methods to handle Prefix SID attribute's TLVs +type PrefixSIDTLVInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + MarshalJSON() ([]byte, error) +} + type PrefixSIDAttribute struct { - TLV + TLVs []PrefixSIDTLVInterface +} + +type PathAttributePrefixSID struct { + PathAttribute TLVs []PrefixSIDTLVInterface } @@ -91,8 +90,8 @@ func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*Marsha var tlv PrefixSIDTLVInterface switch t.Type { case 5: - tlv = &PrefixSIDType5{ - ServiceTLVs: make([]PrefixSIDTLVInterface, 0), + tlv = &SRv6L3ServiceAttribute{ + SubTLVs: make([]PrefixSIDTLVInterface, 0), } default: tlvs = tlvs[t.Len():] @@ -140,24 +139,40 @@ func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) { }{ p.GetType(), p.GetFlags(), - // TODO sbezverk - PrefixSIDAttribute{}, + *p.Extract(), }) } -// PrefixSIDType5 defines the structure of -type PrefixSIDType5 struct { +func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute { + psid := &PrefixSIDAttribute{ + TLVs: make([]PrefixSIDTLVInterface, 0), + } + + for _, tlv := range p.TLVs { + psid.TLVs = append(psid.TLVs, tlv) + } + + return psid +} + +// SRv6L3Service defines the structure of SRv6 L3 Service object +type SRv6L3Service struct { + SubTLVs []PrefixSIDTLVInterface +} + +// SRv6L3ServiceAttribute defines the structure of SRv6 L3 Service attribute +type SRv6L3ServiceAttribute struct { TLV - ServiceTLVs []PrefixSIDTLVInterface + SubTLVs []PrefixSIDTLVInterface } -func (s *PrefixSIDType5) Len() int { +func (s *SRv6L3ServiceAttribute) Len() int { return int(s.Length) + prefixSIDtlvHdrLen } -func (s *PrefixSIDType5) Serialize() ([]byte, error) { +func (s *SRv6L3ServiceAttribute) Serialize() ([]byte, error) { buf := make([]byte, 0) - for _, tlv := range s.ServiceTLVs { + for _, tlv := range s.SubTLVs { s, err := tlv.Serialize() if err != nil { return nil, err @@ -167,7 +182,7 @@ func (s *PrefixSIDType5) Serialize() ([]byte, error) { return s.TLV.Serialize(buf) } -func (s *PrefixSIDType5) DecodeFromBytes(data []byte) error { +func (s *SRv6L3ServiceAttribute) DecodeFromBytes(data []byte) error { stlvs, err := s.TLV.DecodeFromBytes(data) if err != nil { return err @@ -195,22 +210,42 @@ func (s *PrefixSIDType5) DecodeFromBytes(data []byte) error { return err } stlvs = stlvs[t.Len():] - s.ServiceTLVs = append(s.ServiceTLVs, stlv) + s.SubTLVs = append(s.SubTLVs, stlv) } return nil } -func (s *PrefixSIDType5) MarshalJSON() ([]byte, error) { - return nil, nil +func (s *SRv6L3ServiceAttribute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type TLVType `json:"type"` + SRv6L3Service + }{ + s.Type, + *s.Extract(), + }) } -func (s *PrefixSIDType5) String() string { - return "" +func (s *SRv6L3ServiceAttribute) String() string { + var buf bytes.Buffer + + for _, tlv := range s.SubTLVs { + buf.WriteString(fmt.Sprintf("%s ", tlv.String())) + } + + return fmt.Sprintf("{SRv6 L3 Service Attribute: %s}", buf.String()) } -func (s *PrefixSIDType5) Extract() string { - return "" +func (s *SRv6L3ServiceAttribute) Extract() *SRv6L3Service { + l3 := &SRv6L3Service{ + SubTLVs: make([]PrefixSIDTLVInterface, 0), + } + + for _, tlv := range s.SubTLVs { + l3.SubTLVs = append(l3.SubTLVs, tlv) + } + + return l3 } const ( @@ -256,6 +291,13 @@ func (s *SubTLV) DecodeFromBytes(data []byte) ([]byte, error) { return data[subTLVHdrLen:s.Len()], nil } +type SRv6InformationSTLV struct { + SID []byte + Flags uint8 + EndpointBehavior uint16 + SubSubTLVs []PrefixSIDTLVInterface +} + // SRv6InformationSubTLV defines a structure of SRv6 Information Sub TLV (type 1) object // https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1 type SRv6InformationSubTLV struct { @@ -343,9 +385,165 @@ func (s *SRv6InformationSubTLV) DecodeFromBytes(data []byte) error { } func (s *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) { - return nil, nil + return json.Marshal(struct { + Type SubTLVType `json:"type"` + SRv6InformationSTLV + }{ + s.Type, + *s.Extract(), + }) } func (s *SRv6InformationSubTLV) String() string { - return "" + var buf bytes.Buffer + buf.WriteString(fmt.Sprintf("SID: %s ", string(s.SID))) + buf.WriteString(fmt.Sprintf("Flag: %d ", s.Flags)) + buf.WriteString(fmt.Sprintf("Endpoint Behavior: %d ", s.EndpointBehavior)) + for _, tlv := range s.SubSubTLVs { + buf.WriteString(fmt.Sprintf("%s ", tlv.String())) + } + + return fmt.Sprintf("{SRv6 Information Sub TLV: %s}", buf.String()) +} + +func (s *SRv6InformationSubTLV) Extract() *SRv6InformationSTLV { + info := &SRv6InformationSTLV{ + SID: s.SID, + Flags: s.Flags, + EndpointBehavior: s.EndpointBehavior, + SubSubTLVs: make([]PrefixSIDTLVInterface, 0), + } + + for _, tlv := range s.SubSubTLVs { + info.SubSubTLVs = append(info.SubSubTLVs, tlv) + } + + return info +} + +const ( + subSubTLVHdrLen = 3 +) + +type SubSubTLVType uint8 + +type SubSubTLV struct { + Type SubSubTLVType + Length uint16 +} + +func (s *SubSubTLV) Len() int { + return int(s.Length) + subSubTLVHdrLen +} + +func (s *SubSubTLV) Serialize(value []byte) ([]byte, error) { + if len(value) != int(s.Length) { + return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") + } + // Extra byte is reserved + buf := make([]byte, subSubTLVHdrLen+len(value)) + p := 0 + buf[p] = byte(s.Type) + p++ + binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length)) + p += 2 + copy(buf[p:], value) + + return buf, nil +} + +func (s *SubSubTLV) DecodeFromBytes(data []byte) ([]byte, error) { + if len(data) < prefixSIDtlvHdrLen { + return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") + } + s.Type = SubSubTLVType(data[0]) + s.Length = binary.BigEndian.Uint16(data[1:3]) + + if len(data) < s.Len() { + return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") + } + + return data[prefixSIDtlvHdrLen:s.Len()], nil +} + +// SRv6SIDStructureSubSubTLV defines a structure of SRv6 SID Structure Sub Sub TLV (type 1) object +// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.2.1 +type SRv6SIDStructureSubSubTLV struct { + SubSubTLV + LocalBlockLength uint8 + LocatorNodeLength uint8 + FunctionLength uint8 + ArgumentLength uint8 + TranspositionLength uint8 + TranspositionOffset uint8 +} + +func (s *SRv6SIDStructureSubSubTLV) Len() int { + return int(s.Length) + subSubTLVHdrLen +} + +func (s *SRv6SIDStructureSubSubTLV) Serialize() ([]byte, error) { + buf := make([]byte, s.Length) + p := 0 + buf[p] = s.LocalBlockLength + p++ + buf[p] = s.LocatorNodeLength + p++ + buf[p] = s.FunctionLength + p++ + buf[p] = s.ArgumentLength + p++ + buf[p] = s.TranspositionLength + p++ + buf[p] = s.TranspositionOffset + + return s.SubSubTLV.Serialize(buf) +} + +func (s *SRv6SIDStructureSubSubTLV) DecodeFromBytes(data []byte) error { + if len(data) < subSubTLVHdrLen { + return malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") + } + s.Type = SubSubTLVType(data[0]) + s.Length = binary.BigEndian.Uint16(data[1:3]) + + s.LocalBlockLength = data[3] + s.LocatorNodeLength = data[4] + s.FunctionLength = data[5] + s.ArgumentLength = data[6] + s.TranspositionLength = data[7] + s.TranspositionOffset = data[8] + + return nil +} + +func (s *SRv6SIDStructureSubSubTLV) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type SubSubTLVType `json:"type"` + LocalBlockLength uint8 `json:"local_block_length"` + LocatorNodeLength uint8 `json:"locator_node_length"` + FunctionLength uint8 `json:"function_length"` + ArgumentLength uint8 `json:"argument_length"` + TranspositionLength uint8 `json:"transposition_length"` + TranspositionOffset uint8 `json:"transposition_offset"` + }{ + Type: s.Type, + LocalBlockLength: s.LocalBlockLength, + LocatorNodeLength: s.LocatorNodeLength, + FunctionLength: s.FunctionLength, + ArgumentLength: s.ArgumentLength, + TranspositionLength: s.TranspositionLength, + TranspositionOffset: s.TranspositionOffset, + }) +} + +func (s *SRv6SIDStructureSubSubTLV) String() string { + return fmt.Sprintf("{SRv6 Structure Sub Sub TLV: [ Local Block Length: %d, Locator Node Length: %d, Function Length: %d, Argument Length: %d, Transposition Length: %d, Transposition Offset: %d] }", + s.LocalBlockLength, + s.LocatorNodeLength, + s.FunctionLength, + s.ArgumentLength, + s.TranspositionLength, + s.TranspositionOffset, + ) } diff --git a/pkg/packet/bgp/prefix_sid_sstlv.go b/pkg/packet/bgp/prefix_sid_sstlv.go deleted file mode 100644 index 14ff621a..00000000 --- a/pkg/packet/bgp/prefix_sid_sstlv.go +++ /dev/null @@ -1,107 +0,0 @@ -package bgp - -import "encoding/binary" - -const ( - subSubTLVHdrLen = 3 -) - -type SubSubTLVType uint8 - -type SubSubTLV struct { - Type SubSubTLVType - Length uint16 -} - -func (s *SubSubTLV) Len() int { - return int(s.Length) + subSubTLVHdrLen -} - -func (s *SubSubTLV) Serialize(value []byte) ([]byte, error) { - if len(value) != int(s.Length) { - return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed") - } - // Extra byte is reserved - buf := make([]byte, subSubTLVHdrLen+len(value)) - p := 0 - buf[p] = byte(s.Type) - p++ - binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length)) - p += 2 - copy(buf[p:], value) - - return buf, nil -} - -func (s *SubSubTLV) DecodeFromBytes(data []byte) ([]byte, error) { - if len(data) < prefixSIDtlvHdrLen { - return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") - } - s.Type = SubSubTLVType(data[0]) - s.Length = binary.BigEndian.Uint16(data[1:3]) - - if len(data) < s.Len() { - return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") - } - - return data[prefixSIDtlvHdrLen:s.Len()], nil -} - -// SRv6SIDStructureSubSubTLV defines a structure of SRv6 SID Structure Sub Sub TLV (type 1) object -// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.2.1 -type SRv6SIDStructureSubSubTLV struct { - SubSubTLV - LocalBlockLength uint8 `json:"local_block_length,omitempty"` - LocatorNodeLength uint8 `json:"locator_node_length,omitempty"` - FunctionLength uint8 `json:"function_length,omitempty"` - ArgumentLength uint8 `json:"argument_length,omitempty"` - TranspositionLength uint8 `json:"transposition_length,omitempty"` - TranspositionOffset uint8 `json:"transposition_offset,omitempty"` -} - -func (s *SRv6SIDStructureSubSubTLV) Len() int { - return int(s.Length) + subSubTLVHdrLen -} - -func (s *SRv6SIDStructureSubSubTLV) Serialize() ([]byte, error) { - buf := make([]byte, s.Length) - p := 0 - buf[p] = s.LocalBlockLength - p++ - buf[p] = s.LocatorNodeLength - p++ - buf[p] = s.FunctionLength - p++ - buf[p] = s.ArgumentLength - p++ - buf[p] = s.TranspositionLength - p++ - buf[p] = s.TranspositionOffset - - return s.SubSubTLV.Serialize(buf) -} - -func (s *SRv6SIDStructureSubSubTLV) DecodeFromBytes(data []byte) error { - if len(data) < subSubTLVHdrLen { - return malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed") - } - s.Type = SubSubTLVType(data[0]) - s.Length = binary.BigEndian.Uint16(data[1:3]) - - s.LocalBlockLength = data[3] - s.LocatorNodeLength = data[4] - s.FunctionLength = data[5] - s.ArgumentLength = data[6] - s.TranspositionLength = data[7] - s.TranspositionOffset = data[8] - - return nil -} - -func (s *SRv6SIDStructureSubSubTLV) MarshalJSON() ([]byte, error) { - return nil, nil -} - -func (s *SRv6SIDStructureSubSubTLV) String() string { - return "" -} diff --git a/pkg/packet/bgp/prefix_sid_sstlv_test.go b/pkg/packet/bgp/prefix_sid_sstlv_test.go deleted file mode 100644 index 478ee431..00000000 --- a/pkg/packet/bgp/prefix_sid_sstlv_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package bgp - -import ( - "bytes" - "testing" -) - -func TestRoundTripSubSubTLV(t *testing.T) { - tests := []struct { - name string - input []byte - }{ - { - name: "SRv6SIDStructureSubSubTLV", - input: []byte{0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - sstlv := &SRv6SIDStructureSubSubTLV{} - if err := sstlv.DecodeFromBytes(tt.input); err != nil { - t.Fatalf("test failed with error: %+v", err) - } - recovered, err := sstlv.Serialize() - if err != nil { - t.Fatalf("test failed with error: %+v", err) - } - if bytes.Compare(tt.input, recovered) != 0 { - t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered) - } - }) - } -} diff --git a/pkg/packet/bgp/prefix_sid_stlv_test.go b/pkg/packet/bgp/prefix_sid_stlv_test.go deleted file mode 100644 index b4f19d5b..00000000 --- a/pkg/packet/bgp/prefix_sid_stlv_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package bgp - -import ( - "bytes" - "testing" -) - -func TestRoundTripSubTLV(t *testing.T) { - tests := []struct { - name string - input []byte - }{ - { - name: "SRv6InformationSubTLV", - input: []byte{0x01, 0x00, 0x1e, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - stlv := &SRv6InformationSubTLV{} - if err := stlv.DecodeFromBytes(tt.input); err != nil { - t.Fatalf("test failed with error: %+v", err) - } - recovered, err := stlv.Serialize() - if err != nil { - t.Fatalf("test failed with error: %+v", err) - } - if bytes.Compare(tt.input, recovered) != 0 { - t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered) - } - }) - } -} diff --git a/pkg/packet/bgp/prefix_sid_test.go b/pkg/packet/bgp/prefix_sid_test.go index 6457c8df..82a8732e 100644 --- a/pkg/packet/bgp/prefix_sid_test.go +++ b/pkg/packet/bgp/prefix_sid_test.go @@ -5,6 +5,60 @@ import ( "testing" ) +func TestRoundTripSubSubTLV(t *testing.T) { + tests := []struct { + name string + input []byte + }{ + { + name: "SRv6SIDStructureSubSubTLV", + input: []byte{0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sstlv := &SRv6SIDStructureSubSubTLV{} + if err := sstlv.DecodeFromBytes(tt.input); err != nil { + t.Fatalf("test failed with error: %+v", err) + } + recovered, err := sstlv.Serialize() + if err != nil { + t.Fatalf("test failed with error: %+v", err) + } + if bytes.Compare(tt.input, recovered) != 0 { + t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered) + } + }) + } +} + +func TestRoundTripSubTLV(t *testing.T) { + tests := []struct { + name string + input []byte + }{ + { + name: "SRv6InformationSubTLV", + input: []byte{0x01, 0x00, 0x1e, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + stlv := &SRv6InformationSubTLV{} + if err := stlv.DecodeFromBytes(tt.input); err != nil { + t.Fatalf("test failed with error: %+v", err) + } + recovered, err := stlv.Serialize() + if err != nil { + t.Fatalf("test failed with error: %+v", err) + } + if bytes.Compare(tt.input, recovered) != 0 { + t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered) + } + }) + } +} + func TestRoundTripPrefixSID(t *testing.T) { tests := []struct { name string |