summaryrefslogtreecommitdiffhomepage
path: root/pkg/packet/bgp/prefix_sid.go
diff options
context:
space:
mode:
authorSerguei Bezverkhi <sbezverk@cisco.com>2020-05-06 15:44:17 -0400
committerSerguei Bezverkhi <sbezverk@cisco.com>2020-05-06 15:44:17 -0400
commit9251c7a7c0ce93c3365090a79146151c4294e393 (patch)
tree9128b2456f6dd2002d35de1bf6b7cff9df1fa04e /pkg/packet/bgp/prefix_sid.go
parentcd4b9c5b0abfbe73fc7ffc63725a758b7242d759 (diff)
code Decode and Serialize for Prefix SID types and add unit tests
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
Diffstat (limited to 'pkg/packet/bgp/prefix_sid.go')
-rw-r--r--pkg/packet/bgp/prefix_sid.go370
1 files changed, 173 insertions, 197 deletions
diff --git a/pkg/packet/bgp/prefix_sid.go b/pkg/packet/bgp/prefix_sid.go
index f096a8de..1642b87f 100644
--- a/pkg/packet/bgp/prefix_sid.go
+++ b/pkg/packet/bgp/prefix_sid.go
@@ -5,8 +5,10 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
+)
- "github.com/golang/glog"
+const (
+ prefixSIDtlvHdrLen = 4
)
// PrefixSIDTLVInterface defines standard set of methods to handle Prefix SID attribute's TLVs
@@ -23,46 +25,53 @@ type PathAttributePrefixSID struct {
TLVs []PrefixSIDTLVInterface
}
-type PrefixSIDTLVType uint8
+type TLVType uint8
-type PrefixSIDTLV struct {
- Type PrefixSIDTLVType
- Length uint16
+type TLV struct {
+ Type TLVType
+ Length uint16
+ Reserved uint8
}
-func (s *PrefixSIDTLV) Len() int {
- return int(s.Length) + tlvHdrLen
+func (s *TLV) Len() int {
+ return int(s.Length) + tlvHdrLen - 1
}
-func (s *PrefixSIDTLV) Serialize(value []byte) ([]byte, error) {
- if len(value) != int(s.Length) {
+func (s *TLV) Serialize(value []byte) ([]byte, error) {
+ if len(value) != int(s.Length)-1 {
return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
}
-
- buf := make([]byte, tlvHdrLen+len(value))
- binary.BigEndian.PutUint16(buf[:2], uint16(s.Type))
- binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length))
- copy(buf[4:], value)
+ buf := make([]byte, prefixSIDtlvHdrLen+len(value))
+ p := 0
+ buf[p] = byte(s.Type)
+ p++
+ binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length))
+ p += 2
+ // Reserved byte
+ p++
+ copy(buf[p:], value)
return buf, nil
}
-func (s *PrefixSIDTLV) DecodeFromBytes(data []byte) ([]byte, error) {
- if len(data) < tlvHdrLen {
+func (s *TLV) DecodeFromBytes(data []byte) ([]byte, error) {
+ if len(data) < prefixSIDtlvHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
- s.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2]))
- s.Length = binary.BigEndian.Uint16(data[2:4])
+ p := 0
+ s.Type = TLVType(data[p])
+ p++
+ s.Length = binary.BigEndian.Uint16(data[p : p+2])
if len(data) < s.Len() {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
- return data[tlvHdrLen:s.Len()], nil
+ return data[prefixSIDtlvHdrLen:s.Len()], nil
}
type PrefixSIDAttribute struct {
- PrefixSIDTLV
+ TLV
TLVs []PrefixSIDTLVInterface
}
@@ -72,9 +81,8 @@ func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*Marsha
return err
}
- glog.Infof("><SB> tlvs: %+v", tlvs)
- for len(tlvs) >= tlvHdrLen {
- t := &PrefixSIDTLV{}
+ for len(tlvs) >= prefixSIDtlvHdrLen {
+ t := &TLV{}
_, err := t.DecodeFromBytes(tlvs)
if err != nil {
return err
@@ -83,7 +91,9 @@ func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*Marsha
var tlv PrefixSIDTLVInterface
switch t.Type {
case 5:
- tlv = &PrefixSIDType5{}
+ tlv = &PrefixSIDType5{
+ ServiceTLVs: make([]PrefixSIDTLVInterface, 0),
+ }
default:
tlvs = tlvs[t.Len():]
continue
@@ -100,8 +110,7 @@ func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*Marsha
}
func (p *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) {
- buf := []byte{}
-
+ buf := make([]byte, 0)
for _, tlv := range p.TLVs {
s, err := tlv.Serialize()
if err != nil {
@@ -120,7 +129,7 @@ func (p *PathAttributePrefixSID) String() string {
buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
}
- return fmt.Sprintf("{LsAttributes: %s}", buf.String())
+ return fmt.Sprintf("{Prefix SID attributes: %s}", buf.String())
}
func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) {
@@ -131,45 +140,63 @@ func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) {
}{
p.GetType(),
p.GetFlags(),
+ // TODO sbezverk
PrefixSIDAttribute{},
})
}
// PrefixSIDType5 defines the structure of
type PrefixSIDType5 struct {
- PrefixSIDTLV
+ TLV
ServiceTLVs []PrefixSIDTLVInterface
}
func (s *PrefixSIDType5) Len() int {
- return int(s.Length) + tlvHdrLen
+ return int(s.Length) + prefixSIDtlvHdrLen
}
func (s *PrefixSIDType5) Serialize() ([]byte, error) {
- // if len(value) != int(s.Length) {
- // return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
- // }
-
- // buf := make([]byte, tlvHdrLen+len(value))
- // binary.BigEndian.PutUint16(buf[:2], uint16(s.Type))
- // binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length))
- // copy(buf[4:], value)
-
- // return buf, nil
- return nil, nil
+ buf := make([]byte, 0)
+ for _, tlv := range s.ServiceTLVs {
+ s, err := tlv.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, s...)
+ }
+ return s.TLV.Serialize(buf)
}
func (s *PrefixSIDType5) DecodeFromBytes(data []byte) error {
- if len(data) < tlvHdrLen {
- return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ stlvs, err := s.TLV.DecodeFromBytes(data)
+ if err != nil {
+ return err
}
- s.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2]))
- s.Length = binary.BigEndian.Uint16(data[2:4])
- if len(data) < s.Len() {
- return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ for len(stlvs) >= subTLVHdrLen {
+ t := &SubTLV{}
+ _, err := t.DecodeFromBytes(stlvs)
+ if err != nil {
+ return err
+ }
+
+ var stlv PrefixSIDTLVInterface
+ switch t.Type {
+ case 1:
+ stlv = &SRv6InformationSubTLV{
+ SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
+ }
+ default:
+ data = data[t.Len():]
+ continue
+ }
+
+ if err := stlv.DecodeFromBytes(stlvs); err != nil {
+ return err
+ }
+ stlvs = stlvs[t.Len():]
+ s.ServiceTLVs = append(s.ServiceTLVs, stlv)
}
- glog.Infof("><SB> PrefixSIDType5 %+v", data)
return nil
}
@@ -186,190 +213,139 @@ func (s *PrefixSIDType5) Extract() string {
return ""
}
-type SRv6ServiceSubTLV struct {
- PrefixSIDTLV
- TLV []PrefixSIDTLVInterface
-}
+const (
+ subTLVHdrLen = 3
+)
+
+type SubTLVType uint8
-func (s *SRv6ServiceSubTLV) Len() int {
- return int(s.Length) + tlvHdrLen
+type SubTLV struct {
+ Type SubTLVType
+ Length uint16
}
-func (s *SRv6ServiceSubTLV) Serialize() ([]byte, error) {
- // if len(value) != int(s.Length) {
- // return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
- // }
+func (s *SubTLV) Len() int {
+ return int(s.Length) + subTLVHdrLen
+}
- // buf := make([]byte, tlvHdrLen+len(value))
- // binary.BigEndian.PutUint16(buf[:2], uint16(s.Type))
- // binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length))
- // copy(buf[4:], value)
+func (s *SubTLV) 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, subTLVHdrLen+len(value))
+ buf[0] = byte(s.Type)
+ binary.BigEndian.PutUint16(buf[1:4], uint16(s.Length))
+ // 4th reserved byte
+ copy(buf[4:], value)
- // return buf, nil
- return nil, nil
+ return buf, nil
}
-func (s *SRv6ServiceSubTLV) DecodeFromBytes(data []byte) error {
- if len(data) < tlvHdrLen {
- return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+func (s *SubTLV) DecodeFromBytes(data []byte) ([]byte, error) {
+ if len(data) < subTLVHdrLen {
+ return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
- s.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2]))
- s.Length = binary.BigEndian.Uint16(data[2:4])
+ s.Type = SubTLVType(data[0])
+ s.Length = binary.BigEndian.Uint16(data[1:3])
if len(data) < s.Len() {
- return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
- return nil
-}
-
-func (s *SRv6ServiceSubTLV) MarshalJSON() ([]byte, error) {
- return nil, nil
-}
-
-func (s *SRv6ServiceSubTLV) String() string {
- return ""
+ return data[subTLVHdrLen:s.Len()], nil
}
// 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 {
- PrefixSIDTLV
+ SubTLV
SID []byte
Flags uint8
EndpointBehavior uint16
- SubSubTLV []PrefixSIDTLVInterface
-}
-
-type SRv6SubSubTLV struct {
- PrefixSIDTLV
- TLV []PrefixSIDTLVInterface
-}
-
-func (s *SRv6SubSubTLV) Len() int {
- return int(s.Length) + tlvHdrLen
-}
-
-func (s *SRv6SubSubTLV) Serialize() ([]byte, error) {
- s.
- if len(value) != int(s.Length) {
- return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
+ SubSubTLVs []PrefixSIDTLVInterface
+}
+
+func (s *SRv6InformationSubTLV) Len() int {
+ return int(s.Length) + subTLVHdrLen
+}
+
+func (s *SRv6InformationSubTLV) Serialize() ([]byte, error) {
+ buf := make([]byte, s.Length)
+ p := 0
+ copy(buf[p:], s.SID)
+ p += len(s.SID)
+ buf[p] = byte(s.Flags)
+ p++
+ binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.EndpointBehavior))
+ p += 2
+ // Reserved byte
+ buf[p] = 0x0
+ p++
+ for _, sstlv := range s.SubSubTLVs {
+ sbuf, err := sstlv.Serialize()
+ if err != nil {
+ return nil, err
}
+ copy(buf[p:], sbuf)
+ p += len(sbuf)
+ }
- buf := make([]byte, tlvHdrLen+len(value))
- binary.BigEndian.PutUint16(buf[:2], uint16(s.Type))
- binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length))
- copy(buf[4:], value)
-
- return buf, nil
- return nil, nil
+ return s.SubTLV.Serialize(buf)
}
-func (s *SRv6SubSubTLV) DecodeFromBytes(data []byte) error {
- if len(data) < tlvHdrLen {
+func (s *SRv6InformationSubTLV) DecodeFromBytes(data []byte) error {
+ if len(data) < subTLVHdrLen {
return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
- s.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2]))
- s.Length = binary.BigEndian.Uint16(data[2:4])
+ s.Type = SubTLVType(data[0])
+ s.Length = binary.BigEndian.Uint16(data[1:3])
+ // 4th reserved byte
+ p := 4
+ s.SID = make([]byte, 16)
+ copy(s.SID, data[p:p+16])
+ p += 16
+ s.Flags = uint8(data[p])
+ p++
+ s.EndpointBehavior = binary.BigEndian.Uint16(data[p : p+2])
+ p += 2
+ // reserved byte
+ p++
+ if p+3 > len(data) {
+ // There is no Sub Sub TLVs detected, returning
+ return nil
+ }
+ stlvs := data[p:]
+ for len(stlvs) >= prefixSIDtlvHdrLen {
+ t := &SubSubTLV{}
+ _, err := t.DecodeFromBytes(stlvs)
+ if err != nil {
+ return err
+ }
- if len(data) < s.Len() {
- return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ var sstlv PrefixSIDTLVInterface
+ switch t.Type {
+ case 1:
+ sstlv = &SRv6SIDStructureSubSubTLV{}
+ default:
+ stlvs = stlvs[t.Len():]
+ continue
+ }
+
+ if err := sstlv.DecodeFromBytes(stlvs); err != nil {
+ return err
+ }
+ stlvs = stlvs[t.Len():]
+ s.SubSubTLVs = append(s.SubSubTLVs, sstlv)
}
return nil
}
-func (s *SRv6SubSubTLV) MarshalJSON() ([]byte, error) {
+func (s *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) {
return nil, nil
}
-func (s *SRv6SubSubTLV) String() string {
+func (s *SRv6InformationSubTLV) String() string {
return ""
}
-
-// 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 {
- PrefixSIDTLV
- 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"`
-}
-
-
-
-/////////////////////////////
-// type LsTLVAdjacencySID struct {
-// LsTLV
-// Flags uint8
-// Weight uint8
-// SID uint32
-// }
-
-// func (l *LsTLVAdjacencySID) DecodeFromBytes(data []byte) error {
-// value, err := l.LsTLV.DecodeFromBytes(data)
-// if err != nil {
-// return err
-// }
-
-// if l.Type != LS_TLV_ADJACENCY_SID {
-// return malformedAttrListErr("Unexpected TLV type")
-// }
-
-// // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.2.1
-// if len(value) != 7 && len(value) != 8 {
-// return malformedAttrListErr("Incorrect Adjacency SID length")
-// }
-
-// l.Flags = value[0]
-// l.Weight = value[1]
-
-// v := value[4:]
-// if len(v) == 4 {
-// l.SID = binary.BigEndian.Uint32(v)
-// } else {
-// buf := []byte{0, 0, 0, 0}
-// for i := 1; i < len(buf); i++ {
-// buf[i] = v[i-1]
-// }
-// // Label is represented by 20 rightmost bits.
-// l.SID = binary.BigEndian.Uint32(buf) & 0xfffff
-// }
-
-// return nil
-// }
-
-// func (l *LsTLVAdjacencySID) Serialize() ([]byte, error) {
-// buf := make([]byte, 0)
-// buf = append(buf, l.Flags)
-// buf = append(buf, l.Weight)
-// // Reserved
-// buf = append(buf, []byte{0, 0}...)
-
-// var b [4]byte
-// binary.BigEndian.PutUint32(b[:4], l.SID)
-
-// if l.Length == 7 {
-// return l.LsTLV.Serialize(append(buf, b[1:]...))
-// }
-
-// return l.LsTLV.Serialize(append(buf, b[:]...))
-// }
-
-// func (l *LsTLVAdjacencySID) String() string {
-// return fmt.Sprintf("{Adjacency SID: %v}", l.SID)
-// }
-
-// func (l *LsTLVAdjacencySID) MarshalJSON() ([]byte, error) {
-// return json.Marshal(struct {
-// Type LsTLVType `json:"type"`
-// SID uint32 `json:"adjacency_sid"`
-// }{
-// Type: l.Type,
-// SID: l.SID,
-// })
-// }
-////////////////////////////////////// \ No newline at end of file