summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorzvfvrv <franclombardo@gmail.com>2021-06-18 12:06:43 +0200
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2021-06-30 07:38:00 +0900
commitedda6899101cca31e21a2eec079dc418d5213fd4 (patch)
tree1b43fe0dc06f8ed57c82c382983f506925d16380
parent8aaeb6d33902c725e2980256c0e83a9edd853124 (diff)
add support of the optional "SRv6 Endpoint Behavior and SID Structure" in segment type b
-rw-r--r--internal/pkg/apiutil/attribute.go49
-rw-r--r--pkg/packet/bgp/sr_policy.go101
-rw-r--r--pkg/packet/bgp/sr_policy_test.go41
3 files changed, 167 insertions, 24 deletions
diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go
index 30737cc4..1b4a73e7 100644
--- a/internal/pkg/apiutil/attribute.go
+++ b/internal/pkg/apiutil/attribute.go
@@ -1830,15 +1830,26 @@ func UnmarshalSRBSID(bsid *any.Any) (bgp.TunnelEncapSubTLVInterface, error) {
if err != nil {
return nil, err
}
- return &bgp.TunnelEncapSubTLVSRv6BSID{
+ result := &bgp.TunnelEncapSubTLVSRv6BSID{
TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{
Type: bgp.ENCAP_SUBTLV_TYPE_SRBINDING_SID,
Length: uint16(2 + b.Len()),
},
Flags: 0,
BSID: b,
- EPBAS: &bgp.SRv6EndpointBehaviorStructure{},
- }, nil
+ }
+
+ if v.EndpointBehaviorStructure != nil {
+ result.EPBAS = &bgp.SRv6EndpointBehaviorStructure{
+ Behavior: bgp.SRBehavior(v.EndpointBehaviorStructure.Behavior),
+ BlockLen: uint8(v.EndpointBehaviorStructure.BlockLen),
+ NodeLen: uint8(v.EndpointBehaviorStructure.NodeLen),
+ FuncLen: uint8(v.EndpointBehaviorStructure.FuncLen),
+ ArgLen: uint8(v.EndpointBehaviorStructure.ArgLen),
+ }
+ }
+
+ return result, nil
default:
return nil, fmt.Errorf("unknown binding sid type %+v", v)
}
@@ -1862,15 +1873,29 @@ func MarshalSRSegments(segs []bgp.TunnelEncapSubTLVInterface) []*any.Any {
}
// TODO (sbezverk) Add Type B Segment when SRv6 Binding SID gets finalized.
case *bgp.SegmentTypeB:
- r = &api.SegmentTypeB{
- Flags: &api.SegmentFlags{
- VFlag: s.Flags&0x80 == 0x80,
- AFlag: s.Flags&0x40 == 0x40,
- SFlag: s.Flags&0x20 == 0x20,
- BFlag: s.Flags&0x10 == 0x10,
- },
- Sid: s.SID,
- //EndpointBehaviorStructure: &api.SRv6EndPointBehavior{},
+ flags := &api.SegmentFlags{
+ VFlag: s.Flags&0x80 == 0x80,
+ AFlag: s.Flags&0x40 == 0x40,
+ SFlag: s.Flags&0x20 == 0x20,
+ BFlag: s.Flags&0x10 == 0x10,
+ }
+ if s.SRv6EBS != nil {
+ r = &api.SegmentTypeB{
+ Flags: flags,
+ Sid: s.SID,
+ EndpointBehaviorStructure: &api.SRv6EndPointBehavior{
+ Behavior: api.SRv6Behavior(s.SRv6EBS.Behavior),
+ BlockLen: uint32(s.SRv6EBS.BlockLen),
+ NodeLen: uint32(s.SRv6EBS.NodeLen),
+ FuncLen: uint32(s.SRv6EBS.FuncLen),
+ ArgLen: uint32(s.SRv6EBS.ArgLen),
+ },
+ }
+ } else {
+ r = &api.SegmentTypeB{
+ Flags: flags,
+ Sid: s.SID,
+ }
}
default:
// Unrecognize Segment type, skip it
diff --git a/pkg/packet/bgp/sr_policy.go b/pkg/packet/bgp/sr_policy.go
index 39015c37..8a191f60 100644
--- a/pkg/packet/bgp/sr_policy.go
+++ b/pkg/packet/bgp/sr_policy.go
@@ -676,25 +676,86 @@ func (s *SegmentTypeA) MarshalJSON() ([]byte, error) {
})
}
+type SRBehavior int32
+
+const (
+ RESERVED SRBehavior = SRBehavior(api.SRv6Behavior_RESERVED)
+ END SRBehavior = SRBehavior(api.SRv6Behavior_END)
+ END_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP)
+ END_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USP)
+ END_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USP)
+ ENDX SRBehavior = SRBehavior(api.SRv6Behavior_ENDX)
+ ENDX_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP)
+ ENDX_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USP)
+ ENDX_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USP)
+ ENDT SRBehavior = SRBehavior(api.SRv6Behavior_ENDT)
+ ENDT_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP)
+ ENDT_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USP)
+ ENDT_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USP)
+ END_B6_ENCAPS SRBehavior = SRBehavior(api.SRv6Behavior_END_B6_ENCAPS)
+ END_BM SRBehavior = SRBehavior(api.SRv6Behavior_END_BM)
+ END_DX6 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX6)
+ END_DX4 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX4)
+ END_DT6 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT6)
+ END_DT4 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT4)
+ END_DT46 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT46)
+ END_DX2 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX2)
+ END_DX2V SRBehavior = SRBehavior(api.SRv6Behavior_END_DX2V)
+ END_DT2U SRBehavior = SRBehavior(api.SRv6Behavior_RESERVED)
+ END_DT2M SRBehavior = SRBehavior(api.SRv6Behavior_END_DT2M)
+ END_B6_ENCAPS_Red SRBehavior = SRBehavior(api.SRv6Behavior_END_B6_ENCAPS_Red)
+ END_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USD)
+ END_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USD)
+ END_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USP_USD)
+ END_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USP_USD)
+ ENDX_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USD)
+ ENDX_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USD)
+ ENDX_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USP_USD)
+ ENDX_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USP_USD)
+ ENDT_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USD)
+ ENDT_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USD)
+ ENDT_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USP_USD)
+ ENDT_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USP_USD)
+)
+
type SRv6EndpointBehaviorStructure struct {
- Behavior api.SRv6Behavior
+ Behavior SRBehavior
BlockLen uint8
NodeLen uint8
FuncLen uint8
ArgLen uint8
}
-func (s *SRv6EndpointBehaviorStructure) String() string {
+func (s *SRv6EndpointBehaviorStructure) DecodeFromBytes(data []byte) error {
+ behavior := binary.BigEndian.Uint16(data[0:2])
+ s.Behavior = SRBehavior(behavior)
+ s.BlockLen = data[4]
+ s.NodeLen = data[5]
+ s.FuncLen = data[6]
+ s.ArgLen = data[7]
+ return nil
+}
+func (s *SRv6EndpointBehaviorStructure) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ binary.BigEndian.PutUint16(buf[0:2], uint16(s.Behavior))
+ buf[4] = s.BlockLen
+ buf[5] = s.NodeLen
+ buf[6] = s.FuncLen
+ buf[7] = s.ArgLen
+ return buf, nil
+}
+
+func (s *SRv6EndpointBehaviorStructure) String() string {
return fmt.Sprintf("{Behavior: %s, BlockLen: %d, NodeLen: %d, FuncLen: %d, ArgLen: %d}",
- s.Behavior.String(), s.BlockLen, s.NodeLen, s.FuncLen, s.ArgLen)
+ api.SRv6Behavior(s.Behavior).String(), s.BlockLen, s.NodeLen, s.FuncLen, s.ArgLen)
}
type SegmentTypeB struct {
TunnelEncapSubTLV
- Flags uint8
- SID []byte
- //SRv6EBS SRv6EndpointBehaviorStructure
+ Flags uint8
+ SID []byte
+ SRv6EBS *SRv6EndpointBehaviorStructure
}
func (s *SegmentTypeB) DecodeFromBytes(data []byte) error {
@@ -704,17 +765,39 @@ func (s *SegmentTypeB) DecodeFromBytes(data []byte) error {
}
s.Flags = value[0]
s.SID = value[2:18]
+
+ if len(data) == 48 {
+ s.SRv6EBS = &SRv6EndpointBehaviorStructure{}
+ err = s.SRv6EBS.DecodeFromBytes(value[18:])
+ if err != nil {
+ return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
+ }
+ }
return nil
}
func (s *SegmentTypeB) Serialize() ([]byte, error) {
buf := make([]byte, 18)
buf[0] = s.Flags
copy(buf[2:], s.SID)
+ if s.SRv6EBS != nil {
+ if ebs, _ := s.SRv6EBS.Serialize(); ebs != nil {
+ buf = append(buf, ebs...)
+ return s.TunnelEncapSubTLV.Serialize(buf)
+ }
+ }
+
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, Sid: %s}",
- s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, net.IP(s.SID).To16().String())
+ if s.SRv6EBS == nil {
+ return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Sid: %s}",
+ s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, net.IP(s.SID).To16().String())
+ } else {
+ return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Sid: %s, Ebs: %s}",
+ s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, net.IP(s.SID).To16().String(),
+ s.SRv6EBS.String())
+ }
+
}
func (s *SegmentTypeB) MarshalJSON() ([]byte, error) {
@@ -775,12 +858,10 @@ func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
}
case TypeB:
- //fmt.Printf("TypeB\n")
segment = &SegmentTypeB{}
if err := segment.DecodeFromBytes(value); err != nil {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
}
- //fmt.Printf(segment.String())
case TypeC:
fallthrough
case TypeD:
diff --git a/pkg/packet/bgp/sr_policy_test.go b/pkg/packet/bgp/sr_policy_test.go
index 13d605f2..493e2be2 100644
--- a/pkg/packet/bgp/sr_policy_test.go
+++ b/pkg/packet/bgp/sr_policy_test.go
@@ -205,12 +205,49 @@ func TestSegmentListRoundTrip(t *testing.T) {
&SegmentTypeB{
TunnelEncapSubTLV: TunnelEncapSubTLV{Type: EncapSubTLVType(TypeB), Length: 6},
Flags: 0,
- SID: net.ParseIP("2001:1::1").To16(), //[]byte{},
+ SID: net.ParseIP("2001:1::1").To16(),
},
&SegmentTypeB{
TunnelEncapSubTLV: TunnelEncapSubTLV{Type: EncapSubTLVType(TypeB), Length: 6},
Flags: 0,
- SID: net.ParseIP("2001:1::2").To16(), //[]byte{}
+ SID: net.ParseIP("2001:1::2").To16(),
+ },
+ },
+ },
+ fail: false,
+ },
+ {
+ name: "weight and 2 type B segment with SR Endpoint Behavior and Structure",
+ input: &TunnelEncapSubTLVSRSegmentList{
+ TunnelEncapSubTLV: TunnelEncapSubTLV{
+ Type: ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST,
+ Length: 6, // Weight (6 bytes) + Length of each segment + 2
+ },
+ Weight: &SegmentListWeight{
+ TunnelEncapSubTLV: TunnelEncapSubTLV{
+ Type: SegmentListSubTLVWeight,
+ Length: 6,
+ },
+ Flags: 0,
+ Weight: 100,
+ },
+ Segments: []TunnelEncapSubTLVInterface{
+ &SegmentTypeB{
+ TunnelEncapSubTLV: TunnelEncapSubTLV{Type: EncapSubTLVType(TypeB), Length: 6},
+ Flags: 0,
+ SID: net.ParseIP("2001:1::1").To16(),
+ SRv6EBS: &SRv6EndpointBehaviorStructure{
+ Behavior: 39,
+ BlockLen: 5,
+ NodeLen: 6,
+ FuncLen: 7,
+ ArgLen: 8,
+ },
+ },
+ &SegmentTypeB{
+ TunnelEncapSubTLV: TunnelEncapSubTLV{Type: EncapSubTLVType(TypeB), Length: 6},
+ Flags: 0,
+ SID: net.ParseIP("2001:1::2").To16(),
},
},
},