Add unit tests

This commit is contained in:
Mayuresh Gaitonde
2020-12-17 17:25:53 -08:00
parent 3702339f44
commit 6be4d69d02
705 changed files with 120529 additions and 150051 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,50 @@
// generated by stringer -type BGPAttrType bgp.go; DO NOT EDIT
// Code generated by "stringer -type=BGPAttrType"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[BGP_ATTR_TYPE_ORIGIN-1]
_ = x[BGP_ATTR_TYPE_AS_PATH-2]
_ = x[BGP_ATTR_TYPE_NEXT_HOP-3]
_ = x[BGP_ATTR_TYPE_MULTI_EXIT_DISC-4]
_ = x[BGP_ATTR_TYPE_LOCAL_PREF-5]
_ = x[BGP_ATTR_TYPE_ATOMIC_AGGREGATE-6]
_ = x[BGP_ATTR_TYPE_AGGREGATOR-7]
_ = x[BGP_ATTR_TYPE_COMMUNITIES-8]
_ = x[BGP_ATTR_TYPE_ORIGINATOR_ID-9]
_ = x[BGP_ATTR_TYPE_CLUSTER_LIST-10]
_ = x[BGP_ATTR_TYPE_MP_REACH_NLRI-14]
_ = x[BGP_ATTR_TYPE_MP_UNREACH_NLRI-15]
_ = x[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES-16]
_ = x[BGP_ATTR_TYPE_AS4_PATH-17]
_ = x[BGP_ATTR_TYPE_AS4_AGGREGATOR-18]
_ = x[BGP_ATTR_TYPE_PMSI_TUNNEL-22]
_ = x[BGP_ATTR_TYPE_TUNNEL_ENCAP-23]
_ = x[BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES-25]
_ = x[BGP_ATTR_TYPE_AIGP-26]
_ = x[BGP_ATTR_TYPE_LS-29]
_ = x[BGP_ATTR_TYPE_LARGE_COMMUNITY-32]
}
const (
_BGPAttrType_name_0 = "BGP_ATTR_TYPE_ORIGINBGP_ATTR_TYPE_AS_PATHBGP_ATTR_TYPE_NEXT_HOPBGP_ATTR_TYPE_MULTI_EXIT_DISCBGP_ATTR_TYPE_LOCAL_PREFBGP_ATTR_TYPE_ATOMIC_AGGREGATEBGP_ATTR_TYPE_AGGREGATORBGP_ATTR_TYPE_COMMUNITIESBGP_ATTR_TYPE_ORIGINATOR_IDBGP_ATTR_TYPE_CLUSTER_LIST"
_BGPAttrType_name_1 = "BGP_ATTR_TYPE_MP_REACH_NLRIBGP_ATTR_TYPE_MP_UNREACH_NLRIBGP_ATTR_TYPE_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AS4_PATHBGP_ATTR_TYPE_AS4_AGGREGATOR"
_BGPAttrType_name_2 = "BGP_ATTR_TYPE_PMSI_TUNNELBGP_ATTR_TYPE_TUNNEL_ENCAP"
_BGPAttrType_name_3 = "BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AIGP"
_BGPAttrType_name_4 = "BGP_ATTR_TYPE_LS"
_BGPAttrType_name_5 = "BGP_ATTR_TYPE_LARGE_COMMUNITY"
)
var (
_BGPAttrType_index_0 = [...]uint8{0, 20, 41, 63, 92, 116, 146, 170, 195, 222, 248}
_BGPAttrType_index_1 = [...]uint8{0, 27, 56, 90, 112, 140}
_BGPAttrType_index_2 = [...]uint8{0, 25, 51}
_BGPAttrType_index_3 = [...]uint8{0, 38, 56}
)
func (i BGPAttrType) String() string {
@@ -22,7 +55,17 @@ func (i BGPAttrType) String() string {
case 14 <= i && i <= 18:
i -= 14
return _BGPAttrType_name_1[_BGPAttrType_index_1[i]:_BGPAttrType_index_1[i+1]]
case 22 <= i && i <= 23:
i -= 22
return _BGPAttrType_name_2[_BGPAttrType_index_2[i]:_BGPAttrType_index_2[i+1]]
case 25 <= i && i <= 26:
i -= 25
return _BGPAttrType_name_3[_BGPAttrType_index_3[i]:_BGPAttrType_index_3[i+1]]
case i == 29:
return _BGPAttrType_name_4
case i == 32:
return _BGPAttrType_name_5
default:
return fmt.Sprintf("BGPAttrType(%d)", i)
return "BGPAttrType(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -16,7 +16,7 @@
package bgp
import (
"fmt"
"strconv"
"strings"
)
@@ -24,6 +24,7 @@ const AS_TRANS = 23456
const BGP_PORT = 179
//go:generate stringer -type=FSMState
type FSMState int
const (
@@ -73,7 +74,7 @@ var ProtocolNameMap = map[Protocol]string{
func (p Protocol) String() string {
name, ok := ProtocolNameMap[p]
if !ok {
return fmt.Sprintf("%d", p)
return strconv.Itoa(int(p))
}
return name
}
@@ -161,7 +162,7 @@ var BitmaskFlagOpValueMap = map[string]BitmaskFlagOp{
}
func (f BitmaskFlagOp) String() string {
ops := make([]string, 0)
ops := make([]string, 0, 3)
if f&BITMASK_FLAG_OP_AND > 0 {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND])
} else {
@@ -323,5 +324,5 @@ func (t EthernetType) String() string {
if name, ok := EthernetTypeNameMap[t]; ok {
return name
}
return fmt.Sprintf("%d", t)
return strconv.Itoa(int(t))
}

View File

@@ -1,16 +1,28 @@
// generated by stringer -type=ESIType bgp.go validate.go; DO NOT EDIT
// Code generated by "stringer -type=ESIType"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ESI_ARBITRARY-0]
_ = x[ESI_LACP-1]
_ = x[ESI_MSTP-2]
_ = x[ESI_MAC-3]
_ = x[ESI_ROUTERID-4]
_ = x[ESI_AS-5]
}
const _ESIType_name = "ESI_ARBITRARYESI_LACPESI_MSTPESI_MACESI_ROUTERIDESI_AS"
var _ESIType_index = [...]uint8{0, 13, 21, 29, 36, 48, 54}
func (i ESIType) String() string {
if i+1 >= ESIType(len(_ESIType_index)) {
return fmt.Sprintf("ESIType(%d)", i)
if i >= ESIType(len(_ESIType_index)-1) {
return "ESIType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ESIType_name[_ESIType_index[i]:_ESIType_index[i+1]]
}

View File

@@ -1,8 +1,20 @@
// generated by stringer -type=FSMState -output=fsmstate_string.go bgp.go validate.go mrt.go rtr.go constant.go bmp.go esitype_string.go bgpattrtype_string.go; DO NOT EDIT
// Code generated by "stringer -type=FSMState"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[BGP_FSM_IDLE-0]
_ = x[BGP_FSM_CONNECT-1]
_ = x[BGP_FSM_ACTIVE-2]
_ = x[BGP_FSM_OPENSENT-3]
_ = x[BGP_FSM_OPENCONFIRM-4]
_ = x[BGP_FSM_ESTABLISHED-5]
}
const _FSMState_name = "BGP_FSM_IDLEBGP_FSM_CONNECTBGP_FSM_ACTIVEBGP_FSM_OPENSENTBGP_FSM_OPENCONFIRMBGP_FSM_ESTABLISHED"
@@ -10,7 +22,7 @@ var _FSMState_index = [...]uint8{0, 12, 27, 41, 57, 76, 95}
func (i FSMState) String() string {
if i < 0 || i >= FSMState(len(_FSMState_index)-1) {
return fmt.Sprintf("FSMState(%d)", i)
return "FSMState(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _FSMState_name[_FSMState_index[i]:_FSMState_index[i+1]]
}

View File

@@ -0,0 +1,677 @@
package bgp
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"net"
"github.com/golang/protobuf/ptypes"
api "github.com/osrg/gobgp/api"
)
const (
prefixSIDtlvHdrLen = 4
)
type TLVType uint8
type TLV struct {
Type TLVType
Length uint16
}
func (s *TLV) Len() int {
return int(s.Length) + tlvHdrLen - 1 // Extra reserved byte in the header
}
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, 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 *TLV) DecodeFromBytes(data []byte) ([]byte, error) {
if len(data) < prefixSIDtlvHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
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[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 {
TLVs []PrefixSIDTLVInterface
}
type PathAttributePrefixSID struct {
PathAttribute
TLVs []PrefixSIDTLVInterface
}
func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
tlvs, err := p.PathAttribute.DecodeFromBytes(data)
if err != nil {
return err
}
for len(tlvs) >= prefixSIDtlvHdrLen {
t := &TLV{}
_, err := t.DecodeFromBytes(tlvs)
if err != nil {
return err
}
var tlv PrefixSIDTLVInterface
switch t.Type {
case 5:
tlv = &SRv6L3ServiceAttribute{
SubTLVs: make([]PrefixSIDTLVInterface, 0),
}
default:
tlvs = tlvs[t.Len():]
continue
}
if err := tlv.DecodeFromBytes(tlvs); err != nil {
return err
}
tlvs = tlvs[t.Len():]
p.TLVs = append(p.TLVs, tlv)
}
return nil
}
func (p *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 0)
for _, tlv := range p.TLVs {
s, err := tlv.Serialize()
if err != nil {
return nil, err
}
buf = append(buf, s...)
}
return p.PathAttribute.Serialize(buf)
}
func (p *PathAttributePrefixSID) String() string {
var buf bytes.Buffer
for _, tlv := range p.TLVs {
buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
}
return fmt.Sprintf("{Prefix SID attributes: %s}", buf.String())
}
func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type BGPAttrType `json:"type"`
Flags BGPAttrFlag `json:"flags"`
PrefixSIDAttribute
}{
p.GetType(),
p.GetFlags(),
*p.Extract(),
})
}
func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute {
psid := &PrefixSIDAttribute{
TLVs: make([]PrefixSIDTLVInterface, 0),
}
psid.TLVs = append(psid.TLVs, p.TLVs...)
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
SubTLVs []PrefixSIDTLVInterface
}
func (s *SRv6L3ServiceAttribute) Len() int {
return int(s.Length) + prefixSIDtlvHdrLen
}
func (s *SRv6L3ServiceAttribute) Serialize() ([]byte, error) {
buf := make([]byte, 0)
for _, tlv := range s.SubTLVs {
s, err := tlv.Serialize()
if err != nil {
return nil, err
}
buf = append(buf, s...)
}
return s.TLV.Serialize(buf)
}
func (s *SRv6L3ServiceAttribute) DecodeFromBytes(data []byte) error {
stlvs, err := s.TLV.DecodeFromBytes(data)
if err != nil {
return err
}
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.SubTLVs = append(s.SubTLVs, stlv)
}
return nil
}
func (s *SRv6L3ServiceAttribute) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type TLVType `json:"type"`
SRv6L3Service
}{
s.Type,
*s.Extract(),
})
}
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 *SRv6L3ServiceAttribute) Extract() *SRv6L3Service {
l3 := &SRv6L3Service{
SubTLVs: make([]PrefixSIDTLVInterface, 0),
}
l3.SubTLVs = append(l3.SubTLVs, s.SubTLVs...)
return l3
}
const (
subTLVHdrLen = 3
)
type SubTLVType uint8
type SubTLV struct {
Type SubTLVType
Length uint16
}
func (s *SubTLV) Len() int {
return int(s.Length) + subTLVHdrLen
}
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
}
func (s *SubTLV) DecodeFromBytes(data []byte) ([]byte, error) {
if len(data) < subTLVHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
s.Type = SubTLVType(data[0])
s.Length = binary.BigEndian.Uint16(data[1:3])
if len(data) < s.Len() {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
return data[subTLVHdrLen:s.Len()], nil
}
type SRv6InformationSTLV struct {
SID []byte `json:"sid"`
Flags uint8 `json:"flags"`
EndpointBehavior uint16 `json:"endpoint_behavior"`
SubSubTLVs []PrefixSIDTLVInterface `json:"sub_sub_tlvs,omitempty"`
}
// 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 {
SubTLV
SID []byte
Flags uint8
EndpointBehavior uint16
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)
}
return s.SubTLV.Serialize(buf)
}
func (s *SRv6InformationSubTLV) DecodeFromBytes(data []byte) error {
if len(data) < subTLVHdrLen {
return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
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
}
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 *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type SubTLVType `json:"type"`
SRv6InformationSTLV
}{
s.Type,
*s.Extract(),
})
}
func (s *SRv6InformationSubTLV) String() string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("SID: %s ", net.IP(s.SID).To16().String()))
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),
}
info.SubSubTLVs = append(info.SubSubTLVs, s.SubSubTLVs...)
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,
)
}
func NewPathAttributePrefixSID(psid *api.PrefixSID) (*PathAttributePrefixSID, error) {
t := BGP_ATTR_TYPE_PREFIX_SID
s := &PathAttributePrefixSID{
PathAttribute: PathAttribute{
Flags: PathAttrFlags[t],
Type: t,
},
TLVs: make([]PrefixSIDTLVInterface, 0),
}
for _, raw := range psid.Tlvs {
var tlv ptypes.DynamicAny
if err := ptypes.UnmarshalAny(raw, &tlv); err != nil {
return nil, err
}
switch v := tlv.Message.(type) {
case *api.SRv6L3ServiceTLV:
tlvLength, tlvs, err := UnmarshalSubTLVs(v.SubTlvs)
if err != nil {
return nil, err
}
o := &SRv6L3ServiceAttribute{
TLV: TLV{
Type: TLVType(5),
Length: tlvLength,
},
}
s.PathAttribute.Length += tlvLength
// Storing Sub TLVs in a Service TLV
o.SubTLVs = append(o.SubTLVs, tlvs...)
// Adding Service TLV to Path Attribute TLV slice.
s.TLVs = append(s.TLVs, o)
default:
return nil, fmt.Errorf("unknown or not implemented Prefix SID type: %+v", v)
}
}
// Final Path Attribute Length is 3 bytes of the header and 1 byte Reserved1
s.PathAttribute.Length += (3 + 1)
return s, nil
}
func UnmarshalSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
p := make([]PrefixSIDTLVInterface, 0, len(stlvs))
l := uint16(0)
// v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
for t, tlv := range stlvs {
switch t {
case 1:
// Sub TLV Type 1 is SRv6 Informational Sub TLV
for _, stlvRaw := range tlv.Tlv {
// Instantiating Information Sub TLV
info := &SRv6InformationSubTLV{
SubTLV: SubTLV{
Type: SubTLVType(1),
},
SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
}
var raw ptypes.DynamicAny
if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
return 0, nil, err
}
infoProto := raw.Message.(*api.SRv6InformationSubTLV)
info.SID = make([]byte, len(infoProto.Sid))
copy(info.SID, infoProto.Sid)
// TODO Once RFC is published add processing of flags
info.Flags = 0
info.EndpointBehavior = uint16(infoProto.EndpointBehavior)
var sstlvslength uint16
var sstlvs []PrefixSIDTLVInterface
if len(infoProto.SubSubTlvs) != 0 {
// Processing Sub Sub TLVs
var err error
sstlvslength, sstlvs, err = UnmarshalSubSubTLVs(infoProto.SubSubTlvs)
if err != nil {
return 0, nil, err
}
info.SubSubTLVs = append(info.SubSubTLVs, sstlvs...)
}
// SRv6 Information Sub TLV length consists 1 byte Resrved2, 16 bytes SID, 1 byte flags, 2 bytes Endpoint Behavior
// 1 byte Reserved3 and length of Sub Sub TLVs
info.SubTLV.Length = 1 + 16 + 1 + 2 + 1 + sstlvslength
// For total Srv6 Information Sub TLV length, adding 3 bytes of the Sub TLV header
l += info.SubTLV.Length + 4
p = append(p, info)
}
default:
return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
}
}
return l, p, nil
}
func UnmarshalSubSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
p := make([]PrefixSIDTLVInterface, 0)
l := uint16(0)
// v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
for t, tlv := range stlvs {
switch t {
case 1:
// Sub Sub TLV Type 1 is SRv6 Structure Sub Sub TLV
for _, stlvRaw := range tlv.Tlv {
// Instantiating Information Sub TLV
structure := &SRv6SIDStructureSubSubTLV{
SubSubTLV: SubSubTLV{
Type: SubSubTLVType(1),
Length: 6,
},
}
var raw ptypes.DynamicAny
if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
return 0, nil, err
}
structureProto := raw.Message.(*api.SRv6StructureSubSubTLV)
structure.LocalBlockLength = uint8(structureProto.LocalBlockLength)
structure.LocatorNodeLength = uint8(structureProto.LocalNodeLength)
structure.FunctionLength = uint8(structureProto.FunctionLength)
structure.ArgumentLength = uint8(structureProto.ArgumentLength)
structure.TranspositionLength = uint8(structureProto.TranspositionLength)
structure.TranspositionOffset = uint8(structureProto.TranspositionOffset)
// SRv6 Structure Sub Sub TLV length consists of header 3 bytes, 6 bytes of value
l += (3 + 6)
p = append(p, structure)
}
default:
return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
}
}
return l, p, nil
}

View File

@@ -33,17 +33,18 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, isEBGP
//check specific path attribute
ok, err := ValidateAttribute(a, rfs, isEBGP, isConfed)
if !ok {
if err.(*MessageError).ErrorHandling == ERROR_HANDLING_SESSION_RESET {
msgErr := err.(*MessageError)
if msgErr.ErrorHandling == ERROR_HANDLING_SESSION_RESET {
return false, err
} else if err.(*MessageError).Stronger(strongestError) {
} else if msgErr.Stronger(strongestError) {
strongestError = err
}
}
} else if a.GetType() == BGP_ATTR_TYPE_MP_REACH_NLRI || a.GetType() == BGP_ATTR_TYPE_MP_UNREACH_NLRI {
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
eMsg := "the path attribute appears twice. Type : " + strconv.Itoa(int(a.GetType()))
return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg)
} else {
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
eMsg := "the path attribute appears twice. Type : " + strconv.Itoa(int(a.GetType()))
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeAttrList, nil, ERROR_HANDLING_ATTRIBUTE_DISCARD, nil, eMsg)
if e.(*MessageError).Stronger(strongestError) {
strongestError = e
@@ -159,6 +160,10 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
}
isClassDorE := func(ip net.IP) bool {
if ip.To4() == nil {
// needs to verify ipv6 too?
return false
}
res := ip[0] & 0xe0
return res == 0xe0
}
@@ -197,7 +202,7 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
for _, x := range p.Values {
found := false
for _, y := range uniq {
if x.String() == y.String() {
if x.Eq(y) {
found = true
break
}

View File

@@ -344,8 +344,21 @@ func (body *BMPStatisticsReport) ParseBody(msg *BMPMessage, data []byte) error {
s = &BMPStatsTLV64{BMPStatsTLV: tl}
case BMP_STAT_TYPE_PER_AFI_SAFI_ADJ_RIB_IN, BMP_STAT_TYPE_PER_AFI_SAFI_LOC_RIB:
s = &BMPStatsTLVPerAfiSafi64{BMPStatsTLV: tl}
default:
case BMP_STAT_TYPE_REJECTED, BMP_STAT_TYPE_DUPLICATE_PREFIX,
BMP_STAT_TYPE_DUPLICATE_WITHDRAW, BMP_STAT_TYPE_INV_UPDATE_DUE_TO_CLUSTER_LIST_LOOP,
BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_PATH_LOOP, BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID,
BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP, BMP_STAT_TYPE_WITHDRAW_UPDATE,
BMP_STAT_TYPE_WITHDRAW_PREFIX, BMP_STAT_TYPE_DUPLICATE_UPDATE:
s = &BMPStatsTLV32{BMPStatsTLV: tl}
default:
switch tl.Length {
case 4:
s = &BMPStatsTLV32{BMPStatsTLV: tl}
case 8:
s = &BMPStatsTLV64{BMPStatsTLV: tl}
default:
return fmt.Errorf("value length %d is not known for unknown stat type %d", tl.Length, tl.Type)
}
}
if err := s.ParseValue(data); err != nil {
return err
@@ -371,7 +384,7 @@ func (body *BMPStatisticsReport) Serialize() ([]byte, error) {
}
const (
BMP_PEER_DOWN_REASON_UNKNOWN = iota
BMP_peerDownByUnknownReason = iota
BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION
BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION

View File

@@ -18,6 +18,7 @@ package mrt
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"math"
"net"
@@ -198,10 +199,11 @@ type Peer struct {
AS uint32
}
var errNotAllPeerBytesAvailable = errors.New("not all Peer bytes are available")
func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
notAllBytesAvail := fmt.Errorf("not all Peer bytes are available")
if len(data) < 5 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.Type = uint8(data[0])
p.BgpId = net.IP(data[1:5])
@@ -209,13 +211,13 @@ func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
if p.Type&1 > 0 {
if len(data) < 16 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.IpAddress = net.IP(data[:16])
data = data[16:]
} else {
if len(data) < 4 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.IpAddress = net.IP(data[:4])
data = data[4:]
@@ -223,13 +225,13 @@ func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
if p.Type&(1<<1) > 0 {
if len(data) < 4 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.AS = binary.BigEndian.Uint32(data[:4])
data = data[4:]
} else {
if len(data) < 2 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.AS = uint32(binary.BigEndian.Uint16(data[:2]))
data = data[2:]
@@ -291,22 +293,23 @@ type PeerIndexTable struct {
Peers []*Peer
}
var errNnotAllPeerIndexBytesAvailable = errors.New("not all PeerIndexTable bytes are available")
func (t *PeerIndexTable) DecodeFromBytes(data []byte) error {
notAllBytesAvail := fmt.Errorf("not all PeerIndexTable bytes are available")
if len(data) < 6 {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
t.CollectorBgpId = net.IP(data[:4])
viewLen := binary.BigEndian.Uint16(data[4:6])
if len(data) < 6+int(viewLen) {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
t.ViewName = string(data[6 : 6+viewLen])
data = data[6+viewLen:]
if len(data) < 2 {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
peerNum := binary.BigEndian.Uint16(data[:2])
data = data[2:]
@@ -360,10 +363,11 @@ type RibEntry struct {
isAddPath bool
}
var errNotAllRibEntryBytesAvailable = errors.New("not all RibEntry bytes are available")
func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
notAllBytesAvail := fmt.Errorf("not all RibEntry bytes are available")
if len(data) < 8 {
return nil, notAllBytesAvail
return nil, errNotAllRibEntryBytesAvailable
}
e.PeerIndex = binary.BigEndian.Uint16(data[:2])
e.OriginatedTime = binary.BigEndian.Uint32(data[2:6])
@@ -386,7 +390,7 @@ func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
}
attrLen -= uint16(p.Len())
if len(data) < p.Len() {
return nil, notAllBytesAvail
return nil, errNotAllRibEntryBytesAvailable
}
data = data[p.Len():]
e.PathAttributes = append(e.PathAttributes, p)
@@ -417,13 +421,13 @@ func (e *RibEntry) Serialize() ([]byte, error) {
}
var buf []byte
if e.isAddPath {
buf = make([]byte, 12)
buf = make([]byte, 12, 12+len(pbuf))
binary.BigEndian.PutUint16(buf, e.PeerIndex)
binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
binary.BigEndian.PutUint32(buf[6:], e.PathIdentifier)
binary.BigEndian.PutUint16(buf[10:], uint16(totalLen))
} else {
buf = make([]byte, 8)
buf = make([]byte, 8, 8+len(pbuf))
binary.BigEndian.PutUint16(buf, e.PeerIndex)
binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
@@ -461,7 +465,7 @@ type Rib struct {
func (u *Rib) DecodeFromBytes(data []byte) error {
if len(data) < 4 {
return fmt.Errorf("Not all RibIpv4Unicast message bytes available")
return fmt.Errorf("not all RibIpv4Unicast message bytes available")
}
u.SequenceNumber = binary.BigEndian.Uint32(data[:4])
data = data[4:]
@@ -504,9 +508,9 @@ func (u *Rib) Serialize() ([]byte, error) {
switch rf {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_MC, bgp.RF_IPv6_UC, bgp.RF_IPv6_MC:
default:
bbuf := make([]byte, 2)
binary.BigEndian.PutUint16(bbuf, u.Prefix.AFI())
buf = append(buf, bbuf...)
var bbuf [2]byte
binary.BigEndian.PutUint16(bbuf[:], u.Prefix.AFI())
buf = append(buf, bbuf[:]...)
buf = append(buf, u.Prefix.SAFI())
}
bbuf, err := u.Prefix.Serialize()
@@ -665,9 +669,9 @@ type BGP4MPHeader struct {
func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
if m.isAS4 && len(data) < 8 {
return nil, fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
return nil, errors.New("not all BGP4MPMessageAS4 bytes available")
} else if !m.isAS4 && len(data) < 4 {
return nil, fmt.Errorf("Not all BGP4MPMessageAS bytes available")
return nil, errors.New("not all BGP4MPMessageAS bytes available")
}
if m.isAS4 {
@@ -735,7 +739,7 @@ func newBGP4MPHeader(peeras, localas uint32, intfindex uint16, peerip, localip s
if paddr != nil && laddr != nil {
af = bgp.AFI_IP6
} else {
return nil, fmt.Errorf("Peer IP Address and Local IP Address must have the same address family")
return nil, fmt.Errorf("peer IP Address and Local IP Address must have the same address family")
}
}
return &BGP4MPHeader{
@@ -761,7 +765,7 @@ func (m *BGP4MPStateChange) DecodeFromBytes(data []byte) error {
return err
}
if len(rest) < 4 {
return fmt.Errorf("Not all BGP4MPStateChange bytes available")
return fmt.Errorf("not all BGP4MPStateChange bytes available")
}
m.OldState = BGPState(binary.BigEndian.Uint16(rest[:2]))
m.NewState = BGPState(binary.BigEndian.Uint16(rest[2:4]))
@@ -804,7 +808,7 @@ func (m *BGP4MPMessage) DecodeFromBytes(data []byte) error {
}
if len(rest) < bgp.BGP_HEADER_LENGTH {
return fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
return fmt.Errorf("not all BGP4MPMessageAS4 bytes available")
}
msg, err := bgp.ParseBGPMessage(rest)
@@ -903,7 +907,7 @@ func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
if len(data) < int(h.Len) {
return nil, fmt.Errorf("Not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
return nil, fmt.Errorf("not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
}
msg := &MRTMessage{Header: *h}
switch h.Type {
@@ -940,7 +944,7 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
case RIB_GENERIC_ADDPATH:
isAddPath = true
default:
return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v\n", subType)
return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v", subType)
}
if msg.Body == nil {
@@ -993,10 +997,10 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
isAddPath: true,
}
default:
return nil, fmt.Errorf("unsupported bgp4mp subtype: %v\n", subType)
return nil, fmt.Errorf("unsupported bgp4mp subtype: %v", subType)
}
default:
return nil, fmt.Errorf("unsupported type: %v\n", h.Type)
return nil, fmt.Errorf("unsupported type: %v", h.Type)
}
err := msg.Body.DecodeFromBytes(data)
if err != nil {

View File

@@ -355,7 +355,7 @@ func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) {
totalLen := binary.BigEndian.Uint32(data[4:8])
if totalLen < RTR_MIN_LEN {
return 0, nil, fmt.Errorf("Invalid length: %d", totalLen)
return 0, nil, fmt.Errorf("invalid length: %d", totalLen)
}
if uint32(len(data)) < totalLen {
return 0, nil, nil
@@ -385,7 +385,7 @@ func ParseRTR(data []byte) (RTRMessage, error) {
case RTR_ERROR_REPORT:
msg = &RTRErrorReport{}
default:
return nil, fmt.Errorf("unknown RTR message type %d:", data[1])
return nil, fmt.Errorf("unknown RTR message type %d", data[1])
}
err := msg.DecodeFromBytes(data)
return msg, err