diff options
author | zvfvrv <franclombardo@gmail.com> | 2021-06-18 12:06:43 +0200 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@gmail.com> | 2021-06-30 07:38:00 +0900 |
commit | edda6899101cca31e21a2eec079dc418d5213fd4 (patch) | |
tree | 1b43fe0dc06f8ed57c82c382983f506925d16380 | |
parent | 8aaeb6d33902c725e2980256c0e83a9edd853124 (diff) |
add support of the optional "SRv6 Endpoint Behavior and SID Structure" in segment type b
-rw-r--r-- | internal/pkg/apiutil/attribute.go | 49 | ||||
-rw-r--r-- | pkg/packet/bgp/sr_policy.go | 101 | ||||
-rw-r--r-- | pkg/packet/bgp/sr_policy_test.go | 41 |
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(), }, }, }, |