summaryrefslogtreecommitdiffhomepage
path: root/pkg/packet/bgp/sr_policy.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/packet/bgp/sr_policy.go')
-rw-r--r--pkg/packet/bgp/sr_policy.go301
1 files changed, 213 insertions, 88 deletions
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,
- },
- }
-}