summaryrefslogtreecommitdiffhomepage
path: root/internal
diff options
context:
space:
mode:
authorSerguei Bezverkhi <sbezverk@cisco.com>2020-05-12 22:05:44 -0400
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2020-05-13 12:58:51 +0900
commit833188f52610dcf47c57250788b36625b10a8925 (patch)
tree2c4f80208c1d40bc0e52a2f379421039fe577f56 /internal
parent95745b6cf9a5ed229c5494bb0b531215dec38dbe (diff)
extend attributes proto for Prefix SID support
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/pkg/apiutil/attribute.go113
-rw-r--r--internal/pkg/apiutil/attribute_test.go103
2 files changed, 215 insertions, 1 deletions
diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go
index 1610a181..8422f3f3 100644
--- a/internal/pkg/apiutil/attribute.go
+++ b/internal/pkg/apiutil/attribute.go
@@ -75,6 +75,8 @@ func UnmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
}
}
return bgp.NewPathAttributeClusterList(a.Ids), nil
+ case *api.PrefixSID:
+ return bgp.NewPathAttributePrefixSID(a)
}
return nil, errors.New("unexpected object")
}
@@ -149,6 +151,114 @@ func NewClusterListAttributeFromNative(a *bgp.PathAttributeClusterList) *api.Clu
}
}
+func NewPrefixSIDAttributeFromNative(a *bgp.PathAttributePrefixSID) *api.PrefixSID {
+ psid := &api.PrefixSID{}
+ psid.Tlvs = MarshalSRv6TLVs(a.TLVs)
+
+ return psid
+}
+
+func MarshalSRv6TLVs(tlvs []bgp.PrefixSIDTLVInterface) []*any.Any {
+ mtlvs := make([]*any.Any, len(tlvs))
+ for i, tlv := range tlvs {
+ var r proto.Message
+ switch t := tlv.(type) {
+ case *bgp.SRv6L3ServiceAttribute:
+ o := &api.SRv6L3ServiceTLV{}
+ o.SubTlvs = MarshalSRv6SubTLVs(t.SubTLVs)
+ r = o
+ default:
+ log.WithFields(log.Fields{
+ "Topic": "protobuf",
+ "SRv6": t,
+ }).Warn("invalid prefix sid tlv type to marshal")
+ return nil
+ }
+ a, _ := ptypes.MarshalAny(r)
+ mtlvs[i] = a
+ }
+
+ return mtlvs
+}
+
+func MarshalSRv6SubTLVs(tlvs []bgp.PrefixSIDTLVInterface) map[uint32]*api.SRv6TLV {
+ mtlvs := make(map[uint32]*api.SRv6TLV)
+ var key uint32
+ for _, tlv := range tlvs {
+ var r proto.Message
+ switch t := tlv.(type) {
+ case *bgp.SRv6InformationSubTLV:
+ o := &api.SRv6InformationSubTLV{
+ EndpointBehavior: uint32(t.EndpointBehavior),
+ // TODO Once flags are used in RFC, add processing.
+ Flags: &api.SRv6SIDFlags{},
+ }
+ o.Sid = make([]byte, len(t.SID))
+ copy(o.Sid, t.SID)
+ o.SubSubTlvs = MarshalSRv6SubSubTLVs(t.SubSubTLVs)
+ // SRv6 Information Sub TLV is type 1 Sub TLV
+ key = 1
+ r = o
+ default:
+ log.WithFields(log.Fields{
+ "Topic": "protobuf",
+ "SRv6": t,
+ }).Warn("invalid prefix sid sub tlv type to marshal")
+ return nil
+ }
+ a, _ := ptypes.MarshalAny(r)
+ tlvs, ok := mtlvs[key]
+ if !ok {
+ tlvs = &api.SRv6TLV{
+ Tlv: make([]*any.Any, 0),
+ }
+ mtlvs[key] = tlvs
+ }
+ tlvs.Tlv = append(tlvs.Tlv, a)
+ }
+
+ return mtlvs
+}
+
+func MarshalSRv6SubSubTLVs(tlvs []bgp.PrefixSIDTLVInterface) map[uint32]*api.SRv6TLV {
+ mtlvs := make(map[uint32]*api.SRv6TLV)
+ var key uint32
+ for _, tlv := range tlvs {
+ var r proto.Message
+ switch t := tlv.(type) {
+ case *bgp.SRv6SIDStructureSubSubTLV:
+ o := &api.SRv6StructureSubSubTLV{
+ LocalBlockLength: uint32(t.LocalBlockLength),
+ LocalNodeLength: uint32(t.LocatorNodeLength),
+ FunctionLength: uint32(t.FunctionLength),
+ ArgumentLength: uint32(t.ArgumentLength),
+ TranspositionLength: uint32(t.TranspositionLength),
+ TranspositionOffset: uint32(t.TranspositionOffset),
+ }
+ // SRv6 SID Structure Sub Sub TLV is type 1 Sub Sub TLV
+ key = 1
+ r = o
+ default:
+ log.WithFields(log.Fields{
+ "Topic": "protobuf",
+ "SRv6": t,
+ }).Warn("invalid prefix sid sub sub tlv type to marshal")
+ return nil
+ }
+ a, _ := ptypes.MarshalAny(r)
+ tlvs, ok := mtlvs[key]
+ if !ok {
+ tlvs = &api.SRv6TLV{
+ Tlv: make([]*any.Any, 0),
+ }
+ mtlvs[key] = tlvs
+ }
+ tlvs.Tlv = append(tlvs.Tlv, a)
+ }
+
+ return mtlvs
+}
+
func MarshalRD(rd bgp.RouteDistinguisherInterface) *any.Any {
var r proto.Message
switch v := rd.(type) {
@@ -1537,7 +1647,8 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
communities = append(communities, bgp.NewLargeCommunity(c.GlobalAdmin, c.LocalData1, c.LocalData2))
}
return bgp.NewPathAttributeLargeCommunities(communities), nil
-
+ case *api.PrefixSID:
+ return bgp.NewPathAttributePrefixSID(a)
case *api.UnknownAttribute:
return bgp.NewPathAttributeUnknown(bgp.BGPAttrFlag(a.Flags), bgp.BGPAttrType(a.Type), a.Value), nil
}
diff --git a/internal/pkg/apiutil/attribute_test.go b/internal/pkg/apiutil/attribute_test.go
index 8b3cd1c2..a3eff1a7 100644
--- a/internal/pkg/apiutil/attribute_test.go
+++ b/internal/pkg/apiutil/attribute_test.go
@@ -16,6 +16,7 @@
package apiutil
import (
+ "bytes"
"net"
"testing"
@@ -1579,3 +1580,105 @@ func Test_UnknownAttribute(t *testing.T) {
assert.Equal(input.Type, output.Type)
assert.Equal(input.Value, output.Value)
}
+
+func TestFullCyclePrefixSID(t *testing.T) {
+ tests := []struct {
+ name string
+ input []byte
+ }{
+ {
+ name: "srv6 prefix sid",
+ input: []byte{0xc0, 0x28, 0x25, 0x05, 0x00, 0x22, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ attribute := bgp.PathAttributePrefixSID{}
+ if err := attribute.DecodeFromBytes(tt.input); err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ // Converting from Native to API
+ apiPrefixSID := NewPrefixSIDAttributeFromNative(&attribute)
+ // Converting back from API to Native
+ recoveredPrefixSID, err := bgp.NewPathAttributePrefixSID(apiPrefixSID)
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ recovered, err := recoveredPrefixSID.Serialize()
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ if !bytes.Equal(tt.input, recovered) {
+ t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered)
+ }
+ })
+ }
+}
+
+func TestFullCycleSRv6SIDStructureSubSubTLV(t *testing.T) {
+ tests := []struct {
+ name string
+ input []byte
+ }{
+ {
+ name: "srv6 prefix sid",
+ input: []byte{0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ sstlv := bgp.SRv6SIDStructureSubSubTLV{}
+ if err := sstlv.DecodeFromBytes(tt.input); err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ // Converting from Native to API
+ apiPrefixSID := MarshalSRv6SubSubTLVs([]bgp.PrefixSIDTLVInterface{&sstlv})
+ // Converting back from API to Native
+ _, recoveredPrefixSID, err := bgp.UnmarshalSubSubTLVs(apiPrefixSID)
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ recovered, err := recoveredPrefixSID[0].Serialize()
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ if !bytes.Equal(tt.input, recovered) {
+ t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered)
+ }
+ })
+ }
+}
+
+func TestFullCycleSRv6InformationSubTLV(t *testing.T) {
+ tests := []struct {
+ name string
+ input []byte
+ }{
+ {
+ name: "srv6 prefix sid informationw sub tlv",
+ input: []byte{0x01, 0x00, 0x1e, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x06, 0x28, 0x18, 0x10, 0x00, 0x10, 0x40},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ stlv := bgp.SRv6InformationSubTLV{}
+ if err := stlv.DecodeFromBytes(tt.input); err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ // Converting from Native to API
+ apiPrefixSID := MarshalSRv6SubTLVs([]bgp.PrefixSIDTLVInterface{&stlv})
+ // Converting back from API to Native
+ _, recoveredPrefixSID, err := bgp.UnmarshalSubTLVs(apiPrefixSID)
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ recovered, err := recoveredPrefixSID[0].Serialize()
+ if err != nil {
+ t.Fatalf("test failed with error: %+v", err)
+ }
+ if !bytes.Equal(tt.input, recovered) {
+ t.Fatalf("round trip conversion test failed as expected prefix sid attribute %+v does not match actual: %+v", tt.input, recovered)
+ }
+ })
+ }
+}