summaryrefslogtreecommitdiffhomepage
path: root/pkg/packet/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/packet/bgp')
-rw-r--r--pkg/packet/bgp/prefix_sid.go270
-rw-r--r--pkg/packet/bgp/prefix_sid_sstlv.go107
-rw-r--r--pkg/packet/bgp/prefix_sid_sstlv_test.go33
-rw-r--r--pkg/packet/bgp/prefix_sid_stlv_test.go33
-rw-r--r--pkg/packet/bgp/prefix_sid_test.go54
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