Add unit tests
This commit is contained in:
3704
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
3704
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
File diff suppressed because it is too large
Load Diff
49
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgpattrtype_string.go
generated
vendored
49
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgpattrtype_string.go
generated
vendored
@@ -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) + ")"
|
||||
}
|
||||
}
|
||||
|
||||
9
vendor/github.com/osrg/gobgp/pkg/packet/bgp/constant.go
generated
vendored
9
vendor/github.com/osrg/gobgp/pkg/packet/bgp/constant.go
generated
vendored
@@ -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))
|
||||
}
|
||||
|
||||
20
vendor/github.com/osrg/gobgp/pkg/packet/bgp/esitype_string.go
generated
vendored
20
vendor/github.com/osrg/gobgp/pkg/packet/bgp/esitype_string.go
generated
vendored
@@ -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]]
|
||||
}
|
||||
|
||||
18
vendor/github.com/osrg/gobgp/pkg/packet/bgp/fsmstate_string.go
generated
vendored
18
vendor/github.com/osrg/gobgp/pkg/packet/bgp/fsmstate_string.go
generated
vendored
@@ -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]]
|
||||
}
|
||||
|
||||
677
vendor/github.com/osrg/gobgp/pkg/packet/bgp/prefix_sid.go
generated
vendored
Normal file
677
vendor/github.com/osrg/gobgp/pkg/packet/bgp/prefix_sid.go
generated
vendored
Normal 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
|
||||
}
|
||||
15
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
15
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user