summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--internal/pkg/apiutil/attribute.go128
-rw-r--r--pkg/packet/bgp/bgp.go23
-rw-r--r--pkg/packet/bgp/sr_policy.go301
-rw-r--r--pkg/server/grpc_server.go5
4 files changed, 353 insertions, 104 deletions
diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go
index 112df6ff..a85ec06b 100644
--- a/internal/pkg/apiutil/attribute.go
+++ b/internal/pkg/apiutil/attribute.go
@@ -1167,6 +1167,9 @@ func NewTunnelEncapAttributeFromNative(a *bgp.PathAttributeTunnelEncap) *api.Tun
Type: uint32(sv.Type),
Value: sv.Value,
}
+
+ // TODO (sbezverk) Add processing new tunneling sub tlvs
+
}
an, _ := ptypes.MarshalAny(subTlv)
subTlvs = append(subTlvs, an)
@@ -1611,15 +1614,58 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
subTlv = bgp.NewTunnelEncapSubTLVProtocol(uint16(sv.Protocol))
case *api.TunnelEncapSubTLVColor:
subTlv = bgp.NewTunnelEncapSubTLVColor(sv.Color)
-
- // TODO (sbezverk) Add processing SR Policy Tunnel sub tlv
case *api.TunnelEncapSubTLVSRPreference:
subTlv = bgp.NewTunnelEncapSubTLVSRPreference(sv.Flags, sv.Preference)
-
+ case *api.TunnelEncapSubTLVSRPriority:
+ subTlv = bgp.NewTunnelEncapSubTLVSRPriority(uint8(sv.Priority))
+ case *api.TunnelEncapSubTLVSRCandidatePathName:
+ subTlv = bgp.NewTunnelEncapSubTLVSRCandidatePathName(sv.CandidatePathName)
+ case *api.TunnelEncapSubTLVSRENLP:
+ subTlv = bgp.NewTunnelEncapSubTLVSRENLP(sv.Flags, bgp.SRENLPValue(sv.Enlp))
+ case *api.TunnelEncapSubTLVSRBindingSID:
+ var err error
+ subTlv, err = UnmarshalSRBSID(sv.Bsid)
+ if err != nil {
+ return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err)
+ }
+ case *api.TunnelEncapSubTLVSRSegmentList:
+ var err error
+ weight := uint32(0)
+ flags := uint8(0)
+ if sv.Weight != nil {
+ weight = sv.Weight.Weight
+ flags = uint8(sv.Weight.Flags)
+ }
+ s := &bgp.TunnelEncapSubTLVSRSegmentList{
+ TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{
+ Type: bgp.ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST,
+ Length: uint16(6), // Weight (6 bytes) + length of segment (added later, after all segments are discovered)
+ },
+ Weight: &bgp.SegmentListWeight{
+ TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{
+ Type: bgp.SegmentListSubTLVWeight,
+ Length: uint16(6),
+ },
+ Flags: flags,
+ Weight: weight,
+ },
+ Segments: make([]bgp.TunnelEncapSubTLVInterface, 0),
+ }
+ if len(sv.Segments) != 0 {
+ s.Segments, err = UnmarshalSRSegments(sv.Segments)
+ if err != nil {
+ return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err)
+ }
+ }
+ // Get total length of Segment List Sub TLV
+ for _, seg := range s.Segments {
+ s.TunnelEncapSubTLV.Length += uint16(seg.Len() + 2) // Adding 1 byte of type and 1 byte of length for each Segment object
+ }
+ subTlv = s
case *api.TunnelEncapSubTLVUnknown:
subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value)
default:
- return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v", subValue.Message)
+ return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v type: %T", subValue.Message, sv)
}
subTlvs = append(subTlvs, subTlv)
}
@@ -1681,3 +1727,77 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
}
return nil, errors.New("unknown path attribute")
}
+
+// UnmarshalSRBSID unmarshals SR Policy Binding SID Sub TLV and returns native TunnelEncapSubTLVInterface interface
+func UnmarshalSRBSID(bsid *any.Any) (bgp.TunnelEncapSubTLVInterface, error) {
+ var value ptypes.DynamicAny
+ if err := ptypes.UnmarshalAny(bsid, &value); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal tunnel encap sub tlv: %s", err)
+ }
+ switch v := value.Message.(type) {
+ case *api.SRBindingSID:
+ b, err := bgp.NewBSID(v.Sid)
+ if err != nil {
+ return nil, err
+ }
+ flags := uint8(0x0)
+ if v.SFlag {
+ flags += 0x80
+ }
+ if v.IFlag {
+ flags += 0x40
+ }
+ return &bgp.TunnelEncapSubTLVSRBSID{
+ TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{
+ Type: bgp.ENCAP_SUBTLV_TYPE_SRBINDING_SID,
+ Length: uint16(2 + b.Len()),
+ },
+ BSID: b,
+ Flags: flags,
+ }, nil
+ case *api.SRv6BindingSID:
+ return nil, fmt.Errorf("srv6 binding sid is not yet supported")
+ default:
+ return nil, fmt.Errorf("unknown binding sid type %+v", v)
+ }
+}
+
+// UnmarshalSRSegments unmarshals SR Policy Segments slice of structs
+func UnmarshalSRSegments(s []*any.Any) ([]bgp.TunnelEncapSubTLVInterface, error) {
+ if len(s) == 0 {
+ return nil, nil
+ }
+ segments := make([]bgp.TunnelEncapSubTLVInterface, len(s))
+ for i := 0; i < len(s); i++ {
+ var value ptypes.DynamicAny
+ if err := ptypes.UnmarshalAny(s[i], &value); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal SR Policy Segment: %s", err)
+ }
+ switch v := value.Message.(type) {
+ case *api.SegmentTypeA:
+ seg := &bgp.SegmentTypeA{
+ TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{
+ Type: bgp.EncapSubTLVType(bgp.TypeA),
+ Length: 6,
+ },
+ Label: v.Label << 12,
+ }
+ if v.Flags.VFlag {
+ seg.Flags += 0x80
+ }
+ if v.Flags.AFlag {
+ seg.Flags += 0x40
+ }
+ if v.Flags.SFlag {
+ seg.Flags += 0x20
+ }
+ if v.Flags.BFlag {
+ seg.Flags += 0x10
+ }
+ segments[i] = seg
+ case *api.SegmentTypeB:
+ return nil, fmt.Errorf("segment of type B is not yet supported")
+ }
+ }
+ return segments, nil
+}
diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go
index 0976935e..63082af1 100644
--- a/pkg/packet/bgp/bgp.go
+++ b/pkg/packet/bgp/bgp.go
@@ -254,16 +254,15 @@ func (p PmsiTunnelType) String() string {
type EncapSubTLVType uint8
const (
- ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1
- ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2
- ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4
- ENCAP_SUBTLV_TYPE_SRPREFIX_SID EncapSubTLVType = 11
- ENCAP_SUBTLV_TYPE_SRPREFERENCE EncapSubTLVType = 12
- ENCAP_SUBTLV_TYPE_SRBINDING_SID EncapSubTLVType = 13
- ENCAP_SUBTLV_TYPE_SRENLP EncapSubTLVType = 14
- ENCAP_SUBTLV_TYPE_SRPRIORITY EncapSubTLVType = 15
- ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST EncapSubTLVType = 128
- ENCAP_SUBTLV_TYPE_SRPOLICY_NAME EncapSubTLVType = 129
+ ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1
+ ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2
+ ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4
+ ENCAP_SUBTLV_TYPE_SRPREFERENCE EncapSubTLVType = 12
+ ENCAP_SUBTLV_TYPE_SRBINDING_SID EncapSubTLVType = 13
+ ENCAP_SUBTLV_TYPE_SRENLP EncapSubTLVType = 14
+ ENCAP_SUBTLV_TYPE_SRPRIORITY EncapSubTLVType = 15
+ ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST EncapSubTLVType = 128
+ ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME EncapSubTLVType = 129
)
const (
@@ -11645,8 +11644,8 @@ func (t *TunnelEncapTLV) DecodeFromBytes(data []byte) error {
subTlv = &TunnelEncapSubTLVSRENLP{}
case ENCAP_SUBTLV_TYPE_SRPRIORITY:
subTlv = &TunnelEncapSubTLVSRPriority{}
- case ENCAP_SUBTLV_TYPE_SRPOLICY_NAME:
- subTlv = &TunnelEncapSubTLVSRPolicyName{}
+ case ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME:
+ subTlv = &TunnelEncapSubTLVSRCandidatePathName{}
default:
subTlv = &TunnelEncapSubTLVUnknown{
TunnelEncapSubTLV: TunnelEncapSubTLV{
diff --git a/pkg/packet/bgp/sr_policy.go b/pkg/packet/bgp/sr_policy.go
index 007612c4..e7baa069 100644
--- a/pkg/packet/bgp/sr_policy.go
+++ b/pkg/packet/bgp/sr_policy.go
@@ -6,6 +6,8 @@ import (
"fmt"
"net"
"strconv"
+
+ api "github.com/osrg/gobgp/api"
)
type SRPolicyNLRI struct {
@@ -60,11 +62,11 @@ func (s *SRPolicyNLRI) decodeFromBytes(rf RouteFamily, data []byte, options ...*
func (s *SRPolicyNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 1+s.Length)
p := 0
- buf[0] = s.Length
+ buf[0] = s.Length * 8
p++
- binary.BigEndian.PutUint32(buf[:4], s.Distinguisher)
+ binary.BigEndian.PutUint32(buf[p:p+4], s.Distinguisher)
p += 4
- binary.BigEndian.PutUint32(buf[:4], s.Color)
+ binary.BigEndian.PutUint32(buf[p:p+4], s.Color)
p += 4
copy(buf[p:], s.Endpoint)
if IsAddPathEnabled(false, s.rf, options) {
@@ -129,11 +131,10 @@ func (s *SRPolicyIPv4) DecodeFromBytes(data []byte, options ...*MarshallingOptio
}
func NewSRPolicyIPv4(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv4 {
- fmt.Printf("><SB> NewSRPolicyIPv4: length: %d distinguisher: %d color: %d endpoint: %+v\n", l, d, c, ep)
return &SRPolicyIPv4{
SRPolicyNLRI: SRPolicyNLRI{
rf: RF_SR_POLICY_IPv4,
- Length: uint8(l),
+ Length: uint8(l / 8),
Distinguisher: d,
Color: c,
Endpoint: ep,
@@ -150,11 +151,10 @@ func (s *SRPolicyIPv6) DecodeFromBytes(data []byte, options ...*MarshallingOptio
}
func NewSRPolicyIPv6(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv6 {
- fmt.Printf("><SB> NewSRPolicyIPv6: length: %d distinguisher: %d color: %d endpoint: %+v\n", l, d, c, ep)
return &SRPolicyIPv6{
SRPolicyNLRI: SRPolicyNLRI{
rf: RF_SR_POLICY_IPv6,
- Length: uint8(l),
+ Length: uint8(l / 8),
Distinguisher: d,
Color: c,
Endpoint: ep,
@@ -184,7 +184,7 @@ func (t *TunnelEncapSubTLVSRPreference) DecodeFromBytes(data []byte) error {
}
func (t *TunnelEncapSubTLVSRPreference) Serialize() ([]byte, error) {
- buf := make([]byte, t.Length)
+ buf := make([]byte, 6)
buf[0] = t.Flags
binary.BigEndian.PutUint32(buf[2:6], t.Preference)
return t.TunnelEncapSubTLV.Serialize(buf[:])
@@ -209,7 +209,8 @@ func (t *TunnelEncapSubTLVSRPreference) MarshalJSON() ([]byte, error) {
func NewTunnelEncapSubTLVSRPreference(flags uint32, preference uint32) *TunnelEncapSubTLVSRPreference {
return &TunnelEncapSubTLVSRPreference{
TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRPREFERENCE,
+ Type: ENCAP_SUBTLV_TYPE_SRPREFERENCE,
+ Length: 6,
},
Flags: uint8(flags),
Preference: preference,
@@ -236,7 +237,7 @@ func (t *TunnelEncapSubTLVSRPriority) DecodeFromBytes(data []byte) error {
}
func (t *TunnelEncapSubTLVSRPriority) Serialize() ([]byte, error) {
- buf := make([]byte, t.Length)
+ buf := make([]byte, 1+1)
buf[0] = t.Priority
return t.TunnelEncapSubTLV.Serialize(buf[:])
}
@@ -258,53 +259,55 @@ func (t *TunnelEncapSubTLVSRPriority) MarshalJSON() ([]byte, error) {
func NewTunnelEncapSubTLVSRPriority(priority uint8) *TunnelEncapSubTLVSRPriority {
return &TunnelEncapSubTLVSRPriority{
TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRPRIORITY,
+ Type: ENCAP_SUBTLV_TYPE_SRPRIORITY,
+ Length: 2,
},
Priority: priority,
}
}
-type TunnelEncapSubTLVSRPolicyName struct {
+type TunnelEncapSubTLVSRCandidatePathName struct {
TunnelEncapSubTLV
- PolicyName string
+ CandidatePathName string
}
-func (t *TunnelEncapSubTLVSRPolicyName) DecodeFromBytes(data []byte) error {
+func (t *TunnelEncapSubTLVSRCandidatePathName) DecodeFromBytes(data []byte) error {
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
if err != nil {
return err
}
// Skip Reserved byte
- t.PolicyName = string(value[1:t.TunnelEncapSubTLV.Len()])
+ t.CandidatePathName = string(value[1:t.TunnelEncapSubTLV.Len()])
return nil
}
-func (t *TunnelEncapSubTLVSRPolicyName) Serialize() ([]byte, error) {
- buf := make([]byte, t.Length)
- copy(buf[1:], t.PolicyName)
+func (t *TunnelEncapSubTLVSRCandidatePathName) Serialize() ([]byte, error) {
+ buf := make([]byte, 1+len(t.CandidatePathName))
+ copy(buf[1:], t.CandidatePathName)
return t.TunnelEncapSubTLV.Serialize(buf[:])
}
-func (t *TunnelEncapSubTLVSRPolicyName) String() string {
- return fmt.Sprintf("{Policy Name: %s}", t.PolicyName)
+func (t *TunnelEncapSubTLVSRCandidatePathName) String() string {
+ return fmt.Sprintf("{Candidate Path Name: %s}", t.CandidatePathName)
}
-func (t *TunnelEncapSubTLVSRPolicyName) MarshalJSON() ([]byte, error) {
+func (t *TunnelEncapSubTLVSRCandidatePathName) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
- Type EncapSubTLVType `json:"type"`
- PolicyName string `json:"policy_name"`
+ Type EncapSubTLVType `json:"type"`
+ CandidatePathName string `json:"candidate_path_name"`
}{
- Type: t.Type,
- PolicyName: t.PolicyName,
+ Type: t.Type,
+ CandidatePathName: t.CandidatePathName,
})
}
-func NewTunnelEncapSubTLVSRPolicyName(pn string) *TunnelEncapSubTLVSRPolicyName {
- return &TunnelEncapSubTLVSRPolicyName{
+func NewTunnelEncapSubTLVSRCandidatePathName(cpn string) *TunnelEncapSubTLVSRCandidatePathName {
+ return &TunnelEncapSubTLVSRCandidatePathName{
TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRPOLICY_NAME,
+ Type: ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME,
+ Length: uint16(len(cpn) + 1), // length of Candidate Path name string + 1 Reserved byte
},
- PolicyName: pn,
+ CandidatePathName: cpn,
}
}
@@ -380,10 +383,11 @@ func (t *TunnelEncapSubTLVSRENLP) MarshalJSON() ([]byte, error) {
})
}
-func NewTTunnelEncapSubTLVSRENLP(flags uint32, enlp SRENLPValue) *TunnelEncapSubTLVSRENLP {
+func NewTunnelEncapSubTLVSRENLP(flags uint32, enlp SRENLPValue) *TunnelEncapSubTLVSRENLP {
return &TunnelEncapSubTLVSRENLP{
TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRENLP,
+ Type: ENCAP_SUBTLV_TYPE_SRENLP,
+ Length: 3,
},
Flags: uint8(flags),
ENLP: enlp,
@@ -391,12 +395,11 @@ func NewTTunnelEncapSubTLVSRENLP(flags uint32, enlp SRENLPValue) *TunnelEncapSub
}
type BSID struct {
- Length int
- Value []byte
+ Value []byte
}
func (b *BSID) String() string {
- switch b.Length {
+ switch len(b.Value) {
case 0:
return "n/a"
case 4:
@@ -411,24 +414,31 @@ func (b *BSID) String() string {
}
func (b *BSID) Serialize() []byte {
- return []byte{}
+ return b.Value
+}
+func (b *BSID) Len() int {
+ return len(b.Value)
}
-func NewBSID(v []byte, l int) (*BSID, error) {
- switch l {
+
+func NewBSID(v []byte) (*BSID, error) {
+ var bsid *BSID
+ switch len(v) {
case 0:
case 4:
+ t := binary.BigEndian.Uint32(v)
+ t <<= 12
+ bsid = &BSID{
+ Value: make([]byte, len(v)),
+ }
+ binary.BigEndian.PutUint32(bsid.Value, t)
case 16:
+ bsid = &BSID{
+ Value: make([]byte, len(v)),
+ }
+ copy(bsid.Value, v)
default:
- return nil, fmt.Errorf("invalid length %d", l)
- }
- if l < len(v) {
- return nil, fmt.Errorf("parameter length does not match the length of data bytes")
+ return nil, fmt.Errorf("invalid length %d", len(v))
}
- bsid := &BSID{
- Length: l,
- Value: make([]byte, l),
- }
- copy(bsid.Value, v)
return bsid, nil
}
@@ -446,25 +456,33 @@ func (t *TunnelEncapSubTLVSRBSID) DecodeFromBytes(data []byte) error {
}
// Check Sub TLV length, only 3 possible length are allowed
switch t.Length {
- case 2:
+ case 2: // No BSID, do not initializing BSID struct
case 6:
+ fallthrough
case 18:
+ t.BSID = &BSID{
+ Value: make([]byte, t.Length-2),
+ }
+ copy(t.BSID.Value, value[2:t.Length])
default:
msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRBSID length: %d", t.Length)
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
}
t.Flags = value[0]
- t.BSID, err = NewBSID(value[2:t.Length], int(t.Length-2))
- if err != nil {
- return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
- }
return nil
}
func (t *TunnelEncapSubTLVSRBSID) Serialize() ([]byte, error) {
- buf := make([]byte, t.Length)
+ l := 2
+ if t.BSID != nil {
+ l += t.BSID.Len()
+ }
+ buf := make([]byte, l) // 1st byte Flags, 2nd byte Reserved, 3rd+ BSID
buf[0] = t.Flags
- copy(buf[2:t.BSID.Length], t.BSID.Serialize())
+ if t.BSID != nil {
+ bsid := t.BSID.Serialize()
+ copy(buf[2:], bsid)
+ }
return t.TunnelEncapSubTLV.Serialize(buf[:])
}
@@ -484,14 +502,47 @@ func (t *TunnelEncapSubTLVSRBSID) MarshalJSON() ([]byte, error) {
})
}
-// TODO sbezverk Figure out parameters to pass to NewTunnelEncapSubTLVSRBSID
-func NewTunnelEncapSubTLVSRBSID(flags uint32) *TunnelEncapSubTLVSRBSID {
- return &TunnelEncapSubTLVSRBSID{
- TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRBINDING_SID,
- },
- Flags: uint8(flags),
+type TunnelEncapSubTLVSRv6BSID struct {
+ TunnelEncapSubTLV
+ Flags uint8
+ BSID *BSID
+ EPBAS *SRv6EndpointBehaviorStructure
+}
+
+func (t *TunnelEncapSubTLVSRv6BSID) DecodeFromBytes(data []byte) error {
+ value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
+ if err != nil {
+ return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
}
+ t.Flags = value[0]
+ t.BSID, err = NewBSID(value[2:t.Length])
+ if err != nil {
+ return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
+ }
+ return nil
+}
+
+func (t *TunnelEncapSubTLVSRv6BSID) Serialize() ([]byte, error) {
+ buf := make([]byte, t.Length)
+ buf[0] = t.Flags
+ copy(buf[2:t.BSID.Len()], t.BSID.Serialize())
+ return t.TunnelEncapSubTLV.Serialize(buf[:])
+}
+
+func (t *TunnelEncapSubTLVSRv6BSID) String() string {
+ return fmt.Sprintf("{S-Flag: %t, I-Flag: %t, B-Flag: %t, BSID: %s}", t.Flags&0x80 == 0x80, t.Flags&0x40 == 0x40, t.Flags&0x20 == 0x20, t.BSID.String())
+}
+
+func (t *TunnelEncapSubTLVSRv6BSID) MarshalJSON() ([]byte, error) {
+ return json.Marshal(struct {
+ Type EncapSubTLVType `json:"type"`
+ Flags uint8 `json:"flags"`
+ BSID string `json:"binding_sid,omitempty"`
+ }{
+ Type: t.Type,
+ Flags: t.Flags,
+ BSID: t.BSID.String(),
+ })
}
// SegmentType defines a type of Segment in Segment List
@@ -500,6 +551,8 @@ type SegmentType int
const (
// TypeA Segment Sub-TLV encodes a single SR-MPLS SID
TypeA SegmentType = 1
+ // TypeB Segment Sub-TLV encodes a single SRv6 SID.
+ TypeB SegmentType = 13
// TypeC Segment Sub-TLV encodes an IPv4 node address, SR Algorithm
// and an optional SR-MPLS SID
TypeC SegmentType = 3
@@ -521,10 +574,19 @@ const (
// TypeH Segment Sub-TLV encodes an adjacency local address, an
// adjacency remote address and an optional SR-MPLS SID.
TypeH SegmentType = 8
+ // TypeI Segment Sub-TLV encodes an IPv6 node address, SR Algorithm
+ // and an optional SRv6 SID.
+ TypeI SegmentType = 14
+ // TypeJ Segment Sub-TLV encodes an IPv6 Link Local adjacency with
+ // local node address, a local interface identifier (Local Interface
+ // ID), remote IPv6 node address, a remote interface identifier (Remote
+ // Interface ID) and an optional SRv6 SID.
+ TypeJ SegmentType = 15
+ // TypeK Segment Sub-TLV encodes an adjacency local address, an
+ // adjacency remote address and an optional SRv6 SID.
+ TypeK SegmentType = 16
)
-const SegmentListWeightType = 9
-
// Weight sub-TLV specifies the weight associated to a given segment list.
type SegmentListWeight struct {
TunnelEncapSubTLV
@@ -585,7 +647,6 @@ func (s *SegmentTypeA) Serialize() ([]byte, error) {
return s.TunnelEncapSubTLV.Serialize(buf)
}
func (s *SegmentTypeA) String() string {
-
return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Label: %d TC: %d S: %t TTL: %d}",
s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10,
s.Label>>12, s.Label&0x00000e00>>9, s.Label&0x00000100 == 0x00000100, s.Label&0x000000ff)
@@ -615,6 +676,61 @@ func (s *SegmentTypeA) MarshalJSON() ([]byte, error) {
})
}
+type SRv6EndpointBehaviorStructure struct {
+ Behavior api.SRv6Behavior
+ BlockLen uint8
+ NodeLen uint8
+ FuncLen uint8
+ ArgLen uint8
+}
+
+type SegmentTypeB struct {
+ TunnelEncapSubTLV
+ Flags uint8
+ SID []byte
+ EP *SRv6EndpointBehaviorStructure
+}
+
+func (s *SegmentTypeB) DecodeFromBytes(data []byte) error {
+ value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data)
+ if err != nil {
+ return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
+ }
+ s.Flags = value[0]
+ return nil
+}
+func (s *SegmentTypeB) Serialize() ([]byte, error) {
+ buf := make([]byte, 6)
+ buf[0] = s.Flags
+ return s.TunnelEncapSubTLV.Serialize(buf)
+}
+func (s *SegmentTypeB) String() string {
+
+ return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t}",
+ s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10)
+}
+
+func (s *SegmentTypeB) MarshalJSON() ([]byte, error) {
+ return json.Marshal(struct {
+ Type EncapSubTLVType `json:"type"`
+ VFlag bool `json:"v_flag"`
+ AFlag bool `json:"a_flag"`
+ SFlag bool `json:"s_flag"`
+ BFlag bool `json:"b_flag"`
+ }{
+ Type: s.Type,
+ VFlag: s.Flags&0x80 == 0x80,
+ AFlag: s.Flags&0x40 == 0x40,
+ SFlag: s.Flags&0x20 == 0x20,
+ BFlag: s.Flags&0x10 == 0x10,
+ })
+}
+
+const (
+ // SegmentListSubTLVWeight defines code for Segment List's Weight sub-TLV
+ SegmentListSubTLVWeight = 9
+)
+
type TunnelEncapSubTLVSRSegmentList struct {
TunnelEncapSubTLV
Weight *SegmentListWeight
@@ -628,12 +744,12 @@ func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error {
}
// Skip reserved byte to access inner SubTLV type
value = value[1:]
- t.Segments = make([]TunnelEncapSubTLVInterface, 0)
+ segments := make([]TunnelEncapSubTLVInterface, 0)
p := 0
for p < t.TunnelEncapSubTLV.Len()-4 {
var segment TunnelEncapSubTLVInterface
switch SegmentType(value[0]) {
- case SegmentListWeightType:
+ case SegmentListSubTLVWeight:
t.Weight = &SegmentListWeight{}
if err := t.Weight.DecodeFromBytes(value); err != nil {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
@@ -646,6 +762,8 @@ func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error {
if err := segment.DecodeFromBytes(value); err != nil {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
}
+ case TypeB:
+ fallthrough
case TypeC:
fallthrough
case TypeD:
@@ -657,47 +775,62 @@ func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error {
case TypeG:
fallthrough
case TypeH:
+ fallthrough
+ case TypeI:
+ fallthrough
+ case TypeJ:
+ fallthrough
+ case TypeK:
msg := fmt.Sprintf("Invalid SR Policy Segment SubTLV %d is not yet supported", value[0])
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
default:
msg := fmt.Sprintf("Invalid SR Policy Segment List SubTLV %d", value[0])
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
}
- t.Segments = append(t.Segments, segment)
+ segments = append(segments, segment)
p += segment.Len()
value = value[segment.Len():]
}
+ if len(segments) == 0 {
+ t.Segments = nil
+ } else {
+ t.Segments = segments
+ }
return nil
}
func (t *TunnelEncapSubTLVSRSegmentList) Serialize() ([]byte, error) {
- buf := make([]byte, t.Length)
- wbuf, err := t.Weight.Serialize()
- if err != nil {
- return nil, err
- }
- p := 0
+ buf := make([]byte, 0)
// Add reserved byte
- p++
- copy(buf[p:], wbuf)
- p += len(wbuf)
+ buf = append(buf, 0x0)
+ if t.Weight != nil {
+ wbuf, err := t.Weight.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, wbuf...)
+ }
for _, s := range t.Segments {
sbuf, err := s.Serialize()
if err != nil {
return nil, err
}
- copy(buf[p:], sbuf)
- p += len(sbuf)
+ buf = append(buf, sbuf...)
}
return t.TunnelEncapSubTLV.Serialize(buf[:])
}
func (t *TunnelEncapSubTLVSRSegmentList) String() string {
- var segments string
+ msg := "{"
+ if t.Weight != nil {
+ msg += "Weight: " + t.Weight.String() + ","
+ }
+ msg += "Segment List: [ "
for _, s := range t.Segments {
- segments += s.String()
+ msg += s.String() + ","
}
- return fmt.Sprintf("{Weight: %s Segment List: %s}", t.Weight.String(), segments)
+ msg += " ] }"
+ return msg
}
func (t *TunnelEncapSubTLVSRSegmentList) MarshalJSON() ([]byte, error) {
@@ -711,11 +844,3 @@ func (t *TunnelEncapSubTLVSRSegmentList) MarshalJSON() ([]byte, error) {
Segments: t.Segments,
})
}
-
-func NewTunnelEncapSubTLVSRSegmentList() *TunnelEncapSubTLVSRSegmentList {
- return &TunnelEncapSubTLVSRSegmentList{
- TunnelEncapSubTLV: TunnelEncapSubTLV{
- Type: ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST,
- },
- }
-}
diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go
index 06425dfa..a057d6ae 100644
--- a/pkg/server/grpc_server.go
+++ b/pkg/server/grpc_server.go
@@ -296,6 +296,11 @@ func api2Path(resource api.TableType, path *api.Path, isWithdraw bool) (*table.P
return nil, err
}
+ // TODO (sbezverk) At this poinnt nlri and path attributes are converted to native mode
+ // need to check if update with SR Policy nlri comes with mandatory route distinguisher
+ // extended community or NO_ADVERTISE community, with Tunnel Encapsulation Attribute 23
+ // and tunnel type 15. If it is not the case ignore update and log an error.
+
pattrs := make([]bgp.PathAttributeInterface, 0)
seen := make(map[bgp.BGPAttrType]struct{})
for _, attr := range attrList {