Repository: scionproto/scion
Pull request #3710 (2020-04-14 14:28:52)

colibri: ctrl response types 
This PR adds the response types for colibri control messages.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/scionproto/scion/3710)
<!-- Reviewable:end -->



Patch:
diff --git a/go/lib/ctrl/colibri_mgmt/BUILD.bazel b/go/lib/ctrl/colibri_mgmt/BUILD.bazel
index b6007534e..1ef49cb93 100644
--- a/go/lib/ctrl/colibri_mgmt/BUILD.bazel
+++ b/go/lib/ctrl/colibri_mgmt/BUILD.bazel
@@ -8,6 +8,7 @@ go_library(
         "e2e_setup.go",
         "request.go",
         "reservation_ids.go",
+        "response.go",
         "segment_cleanup.go",
         "segment_index_confirmation.go",
         "segment_setup.go",
diff --git a/go/lib/ctrl/colibri_mgmt/colibri_mgmt.go b/go/lib/ctrl/colibri_mgmt/colibri_mgmt.go
index 2253f6212..5c379af01 100644
--- a/go/lib/ctrl/colibri_mgmt/colibri_mgmt.go
+++ b/go/lib/ctrl/colibri_mgmt/colibri_mgmt.go
@@ -20,10 +20,6 @@ import (
 	"github.com/scionproto/scion/go/proto"
 )
 
-type Response struct {
-	// TODO(juagargi)
-}
-
 type ColibriRequestPayload struct {
 	Which    proto.ColibriRequestPayload_Which
 	Request  *Request
diff --git a/go/lib/ctrl/colibri_mgmt/response.go b/go/lib/ctrl/colibri_mgmt/response.go
new file mode 100644
index 000000000..5d1015841
--- /dev/null
+++ b/go/lib/ctrl/colibri_mgmt/response.go
@@ -0,0 +1,39 @@
+// Copyright 2020 ETH Zurich, Anapaya Systems
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package colibri_mgmt
+
+import (
+	"github.com/scionproto/scion/go/proto"
+)
+
+type Response struct {
+	Which                    proto.Response_Which
+	SegmentSetup             *SegmentSetupRes
+	SegmentRenewal           *SegmentSetupRes
+	SegmentTelesSetup        *SegmentSetupRes
+	SegmentTelesRenewal      *SegmentSetupRes
+	SegmentTeardown          *SegmentTeardownRes
+	SegmentIndexConfirmation *SegmentIndexConfirmation
+	SegmentCleanup           *SegmentCleanup
+	E2ESetup                 *E2ESetup   `capnp:"e2eSetup"`
+	E2ERenewal               *E2ESetup   `capnp:"e2eRenewal"`
+	E2ECleanup               *E2ECleanup `capnp:"e2eCleanup"`
+	Accepted                 bool
+	FailedHop                uint8 // only relevant if Accepted == false
+}
+
+func (r *Response) ProtoId() proto.ProtoIdType {
+	return proto.Response_TypeID
+}
diff --git a/go/lib/ctrl/colibri_mgmt/segment_setup.go b/go/lib/ctrl/colibri_mgmt/segment_setup.go
index 4fb18fe5e..7121d30a7 100644
--- a/go/lib/ctrl/colibri_mgmt/segment_setup.go
+++ b/go/lib/ctrl/colibri_mgmt/segment_setup.go
@@ -31,6 +31,16 @@ func (s *SegmentSetup) ProtoId() proto.ProtoIdType {
 	return proto.SegmentSetupReqData_TypeID
 }
 
+type SegmentSetupRes struct {
+	Which   proto.SegmentSetupResData_Which
+	Failure *SegmentSetup
+	Token   []byte
+}
+
+func (s *SegmentSetupRes) ProtoId() proto.ProtoIdType {
+	return proto.SegmentSetupResData_TypeID
+}
+
 type PathEndProps struct {
 	Local    bool
 	Transfer bool
diff --git a/go/lib/ctrl/colibri_mgmt/segment_teardown.go b/go/lib/ctrl/colibri_mgmt/segment_teardown.go
index 3ed714bf8..e2877e8b0 100644
--- a/go/lib/ctrl/colibri_mgmt/segment_teardown.go
+++ b/go/lib/ctrl/colibri_mgmt/segment_teardown.go
@@ -23,3 +23,11 @@ type SegmentTeardownReq struct{}
 func (s *SegmentTeardownReq) ProtoId() proto.ProtoIdType {
 	return proto.SegmentTeardownReqData_TypeID
 }
+
+type SegmentTeardownRes struct {
+	ErrorCode uint8 // relevant only if Response.Accepted == false
+}
+
+func (r *SegmentTeardownRes) ProtoId() proto.ProtoIdType {
+	return proto.SegmentTeardownResData_TypeID
+}


Test patch:
diff --git a/go/lib/ctrl/colibri_mgmt/colibri_mgmt_test.go b/go/lib/ctrl/colibri_mgmt/colibri_mgmt_test.go
index 9759a8edc..6986e38bc 100644
--- a/go/lib/ctrl/colibri_mgmt/colibri_mgmt_test.go
+++ b/go/lib/ctrl/colibri_mgmt/colibri_mgmt_test.go
@@ -197,6 +197,160 @@ func TestSerializeRequest(t *testing.T) {
 			require.NoError(t, err)
 			otherBuffer, err := otherRoot.PackRoot()
 			require.NoError(t, err)
+			require.Equal(t, buffer, otherBuffer)
+		})
+	}
+}
+
+func TestSerializeResponse(t *testing.T) {
+	newSegmentSetupResp := func() *colibri_mgmt.SegmentSetupRes {
+		return &colibri_mgmt.SegmentSetupRes{
+			Which: proto.SegmentSetupResData_Which_token,
+			Token: xtest.MustParseHexString("0000"),
+		}
+	}
+	newE2ESetupResp := func() *colibri_mgmt.E2ESetup {
+		return &colibri_mgmt.E2ESetup{
+			Which: proto.E2ESetupData_Which_success,
+			Success: &colibri_mgmt.E2ESetupSuccess{
+				ReservationID: &colibri_mgmt.E2EReservationID{
+					ASID:   xtest.MustParseHexString("ff00cafe0001"),
+					Suffix: xtest.MustParseHexString("0123456789abcdef0123456789abcdef"),
+				},
+				Token: xtest.MustParseHexString("0000"),
+			},
+		}
+	}
+	testCases := map[string]struct {
+		Response *colibri_mgmt.Response
+	}{
+		"setup failed": {
+			Response: &colibri_mgmt.Response{
+				Which: proto.Response_Which_segmentSetup,
+				SegmentSetup: &colibri_mgmt.SegmentSetupRes{
+					Which: proto.SegmentSetupResData_Which_failure,
+					Failure: &colibri_mgmt.SegmentSetup{
+						MinBW:    1,
+						MaxBW:    2,
+						SplitCls: 3,
+						StartProps: colibri_mgmt.PathEndProps{
+							Local:    true,
+							Transfer: false,
+						},
+						EndProps: colibri_mgmt.PathEndProps{
+							Local:    false,
+							Transfer: true,
+						},
+						AllocationTrail: []*colibri_mgmt.AllocationBeads{
+							{
+								AllocBW: 5,
+								MaxBW:   6,
+							},
+						},
+					},
+				},
+				Accepted:  false,
+				FailedHop: 3,
+			},
+		},
+		"setup success": {
+			Response: &colibri_mgmt.Response{
+				Which:        proto.Response_Which_segmentSetup,
+				SegmentSetup: newSegmentSetupResp(),
+				Accepted:     true,
+			},
+		},
+		"renewal": {
+			Response: &colibri_mgmt.Response{
+				Which:          proto.Response_Which_segmentRenewal,
+				SegmentRenewal: newSegmentSetupResp(),
+				Accepted:       true,
+			},
+		},
+		"teles setup": {
+			Response: &colibri_mgmt.Response{
+				Which:             proto.Response_Which_segmentTelesSetup,
+				SegmentTelesSetup: newSegmentSetupResp(),
+				Accepted:          true,
+			},
+		},
+		"teles renewal": {
+			Response: &colibri_mgmt.Response{
+				Which:               proto.Response_Which_segmentTelesRenewal,
+				SegmentTelesRenewal: newSegmentSetupResp(),
+				Accepted:            true,
+			},
+		},
+		"teardown": {
+			Response: &colibri_mgmt.Response{
+				Which:           proto.Response_Which_segmentTeardown,
+				SegmentTeardown: &colibri_mgmt.SegmentTeardownRes{ErrorCode: 123},
+				Accepted:        false,
+				FailedHop:       2,
+			},
+		},
+		"index confirmation": {
+			Response: &colibri_mgmt.Response{
+				Which: proto.Response_Which_segmentIndexConfirmation,
+				SegmentIndexConfirmation: &colibri_mgmt.SegmentIndexConfirmation{
+					Index: 111,
+					State: proto.ReservationIndexState_active,
+				},
+				Accepted: true,
+			},
+		},
+		"segment cleanup": {
+			Response: &colibri_mgmt.Response{
+				Which: proto.Response_Which_segmentCleanup,
+				SegmentCleanup: &colibri_mgmt.SegmentCleanup{
+					ID: &colibri_mgmt.SegmentReservationID{
+						ASID:   xtest.MustParseHexString("ff00cafe0001"),
+						Suffix: xtest.MustParseHexString("deadbeef"),
+					},
+					Index: 17,
+				},
+				Accepted: true,
+			},
+		},
+		"e2e setup": {
+			Response: &colibri_mgmt.Response{
+				Which:    proto.Response_Which_e2eSetup,
+				E2ESetup: newE2ESetupResp(),
+				Accepted: true,
+			},
+		},
+		"e2e renewal": {
+			Response: &colibri_mgmt.Response{
+				Which:      proto.Response_Which_e2eRenewal,
+				E2ERenewal: newE2ESetupResp(),
+				Accepted:   true,
+			},
+		},
+		"e2e cleanup": {
+			Response: &colibri_mgmt.Response{
+				Which: proto.Response_Which_e2eCleanup,
+				E2ECleanup: &colibri_mgmt.E2ECleanup{
+					ReservationID: &colibri_mgmt.E2EReservationID{
+						ASID:   xtest.MustParseHexString("ff00cafe0001"),
+						Suffix: xtest.MustParseHexString("0123456789abcdef0123456789abcdef"),
+					},
+				},
+				Accepted: true,
+			},
+		},
+	}
+	for name, tc := range testCases {
+		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+			root := &colibri_mgmt.ColibriRequestPayload{
+				Which:    proto.ColibriRequestPayload_Which_response,
+				Response: tc.Response,
+			}
+			buffer, err := root.PackRoot()
+			require.NoError(t, err)
+			otherRoot, err := colibri_mgmt.NewFromRaw(buffer)
+			require.NoError(t, err)
+			otherBuffer, err := otherRoot.PackRoot()
 			require.NoError(t, err)
 			require.Equal(t, buffer, otherBuffer)
 		})