Skip to content

Commit

Permalink
colibri: add application level types (scionproto#3776)
Browse files Browse the repository at this point in the history
Fix capnp e2e setup ctrl message: both success and failure must contain ID
Serialize application level request types from/to control ones.
All application level requests must have an ID
  • Loading branch information
juagargi authored Jun 16, 2020
1 parent 63872b0 commit e243193
Show file tree
Hide file tree
Showing 21 changed files with 844 additions and 326 deletions.
6 changes: 5 additions & 1 deletion go/cs/reservation/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["index.go"],
srcs = [
"index.go",
"request.go",
],
importpath = "github.com/scionproto/scion/go/cs/reservation",
visibility = ["//visibility:public"],
deps = [
"//go/lib/colibri/reservation:go_default_library",
"//go/lib/serrors:go_default_library",
"//go/lib/spath:go_default_library",
],
)
2 changes: 2 additions & 0 deletions go/cs/reservation/e2e/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_library(
"//go/lib/colibri/reservation:go_default_library",
"//go/lib/ctrl/colibri_mgmt:go_default_library",
"//go/lib/serrors:go_default_library",
"//go/lib/spath:go_default_library",
"//go/proto:go_default_library",
],
)
Expand All @@ -31,6 +32,7 @@ go_test(
"//go/cs/reservation/segmenttest:go_default_library",
"//go/lib/colibri/reservation:go_default_library",
"//go/lib/ctrl/colibri_mgmt:go_default_library",
"//go/lib/spath:go_default_library",
"//go/lib/xtest:go_default_library",
"//go/proto:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
Expand Down
189 changes: 135 additions & 54 deletions go/cs/reservation/e2e/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package e2e
import (
"time"

base "github.com/scionproto/scion/go/cs/reservation"
"github.com/scionproto/scion/go/lib/colibri/reservation"
"github.com/scionproto/scion/go/lib/ctrl/colibri_mgmt"
"github.com/scionproto/scion/go/lib/serrors"
"github.com/scionproto/scion/go/lib/spath"
"github.com/scionproto/scion/go/proto"
)

Expand All @@ -33,25 +35,78 @@ type SetupReq interface {

// BaseSetupReq is the common part of any e2e setup request.
type BaseSetupReq struct {
reservation *Reservation
timestamp time.Time
Metadata base.RequestMetadata // information about the request (forwarding path)
ID reservation.E2EID // the ID this request refers to
timestamp time.Time // the mandatory timestamp
reservation *Reservation // nil if no reservation yet
}

func NewBaseSetupReq(path *spath.Path, ts time.Time,
ID *colibri_mgmt.E2EReservationID) (*BaseSetupReq, error) {

metadata, err := base.NewRequestMetadata(path)
if err != nil {
return nil, serrors.WrapStr("cannot construct e2e setup", err)
}
if ID == nil {
return nil, serrors.New("new e2e request with nil ID")
}
e2eID, err := reservation.E2EIDFromRawBuffers(ID.ASID, ID.Suffix)
if err != nil {
return nil, serrors.WrapStr("cannot construct e2e request", err)
}
return &BaseSetupReq{
Metadata: *metadata,
ID: *e2eID,
timestamp: ts,
}, nil
}

func (r *BaseSetupReq) Timestamp() time.Time { return r.timestamp }
func (r *BaseSetupReq) Reservation() *Reservation { return r.reservation }

func (r *BaseSetupReq) ToCtrlMsg() (*colibri_mgmt.E2ESetup, error) {
id := make([]byte, reservation.E2EIDLen)
_, err := r.ID.Read(id)
if err != nil {
return nil, err
}
return &colibri_mgmt.E2ESetup{
ReservationID: &colibri_mgmt.E2EReservationID{
ASID: id[:6],
Suffix: id[6:],
},
}, nil
}

// SuccessSetupReq is a successful e2e resevation setup request.
type SuccessSetupReq struct {
BaseSetupReq
ID reservation.E2EID
Token reservation.Token
}

var _ SetupReq = (*SuccessSetupReq)(nil)

// NewSuccessSetupReq constructs the app type from its control message.
func NewSuccessSetupReq(path *spath.Path, ts time.Time, ID *colibri_mgmt.E2EReservationID,
ctrl *colibri_mgmt.E2ESetupSuccess) (*SuccessSetupReq, error) {

baseReq, err := NewBaseSetupReq(path, ts, ID)
if err != nil {
return nil, serrors.WrapStr("cannot construct success e2e setup", err)
}
tok, err := reservation.TokenFromRaw(ctrl.Token)
if err != nil {
return nil, serrors.WrapStr("cannot construct success e2e setup", err)
}
return &SuccessSetupReq{
BaseSetupReq: *baseReq,
Token: *tok,
}, nil
}

func (r *SuccessSetupReq) ToCtrlMsg() (*colibri_mgmt.E2ESetup, error) {
id := make([]byte, reservation.E2EIDLen)
_, err := r.ID.Read(id)
ctrl, err := r.BaseSetupReq.ToCtrlMsg()
if err != nil {
return nil, err
}
Expand All @@ -60,17 +115,11 @@ func (r *SuccessSetupReq) ToCtrlMsg() (*colibri_mgmt.E2ESetup, error) {
if err != nil {
return nil, err
}
msg := &colibri_mgmt.E2ESetup{
Which: proto.E2ESetupData_Which_success,
Success: &colibri_mgmt.E2ESetupSuccess{
ReservationID: &colibri_mgmt.E2EReservationID{
ASID: id[:6],
Suffix: id[6:],
},
Token: token,
},
ctrl.Which = proto.E2ESetupData_Which_success
ctrl.Success = &colibri_mgmt.E2ESetupSuccess{
Token: token,
}
return msg, nil
return ctrl, nil
}

// FailureSetupReq is a failing e2e resevation setup request.
Expand All @@ -83,65 +132,97 @@ type FailureSetupReq struct {

var _ SetupReq = (*FailureSetupReq)(nil)

func NewFailureSetupReq(path *spath.Path, ts time.Time, ID *colibri_mgmt.E2EReservationID,
ctrl *colibri_mgmt.E2ESetupFailure) (*FailureSetupReq, error) {

baseReq, err := NewBaseSetupReq(path, ts, ID)
if err != nil {
return nil, serrors.WrapStr("cannot construct failure e2e setup", err)
}
ifield, err := reservation.InfoFieldFromRaw(ctrl.InfoField)
if err != nil {
return nil, err
}
bwTrail := make([]reservation.BWCls, len(ctrl.MaxBWs))
for i, bw := range ctrl.MaxBWs {
bwTrail[i] = reservation.BWCls(bw)
}
return &FailureSetupReq{
BaseSetupReq: *baseReq,
ErrorCode: int(ctrl.ErrorCode),
InfoField: *ifield,
MaxBWTrail: bwTrail,
}, nil
}

func (r *FailureSetupReq) ToCtrlMsg() (*colibri_mgmt.E2ESetup, error) {
ctrl, err := r.BaseSetupReq.ToCtrlMsg()
if err != nil {
return nil, err
}
inf := make([]byte, reservation.InfoFieldLen)
_, err := r.InfoField.Read(inf)
_, err = r.InfoField.Read(inf)
if err != nil {
return nil, err
}
trail := make([]uint8, len(r.MaxBWTrail))
for i, bw := range r.MaxBWTrail {
trail[i] = uint8(bw)
}
msg := &colibri_mgmt.E2ESetup{
Which: proto.E2ESetupData_Which_failure,
Failure: &colibri_mgmt.E2ESetupFailure{
ErrorCode: uint8(r.ErrorCode),
InfoField: inf,
MaxBWs: trail,
},
ctrl.Which = proto.E2ESetupData_Which_failure
ctrl.Failure = &colibri_mgmt.E2ESetupFailure{
ErrorCode: uint8(r.ErrorCode),
InfoField: inf,
MaxBWs: trail,
}
return msg, nil
return ctrl, nil
}

// NewRequestFromCtrlMsg will return a SuccessSetupReq or FailSetupReq depending on the
// success flag of the ctrl message.
func NewRequestFromCtrlMsg(setup *colibri_mgmt.E2ESetup, ts time.Time) (SetupReq, error) {
func NewRequestFromCtrlMsg(setup *colibri_mgmt.E2ESetup, ts time.Time,
path *spath.Path) (SetupReq, error) {

var s SetupReq
var err error
switch {
case setup.Success != nil:
id, err := reservation.E2EIDFromRawBuffers(setup.Success.ReservationID.ASID,
setup.Success.ReservationID.Suffix)
if err != nil {
return nil, err
}
tok, err := reservation.TokenFromRaw(setup.Success.Token)
if err != nil {
return nil, err
}
s = &SuccessSetupReq{
BaseSetupReq: BaseSetupReq{timestamp: ts},
ID: *id,
Token: *tok,
}
s, err = NewSuccessSetupReq(path, ts, setup.ReservationID, setup.Success)
case setup.Failure != nil:
ifield, err := reservation.InfoFieldFromRaw(setup.Failure.InfoField)
if err != nil {
return nil, err
}
bwTrail := make([]reservation.BWCls, len(setup.Failure.MaxBWs))
for i, bw := range setup.Failure.MaxBWs {
bwTrail[i] = reservation.BWCls(bw)
}
s = &FailureSetupReq{
BaseSetupReq: BaseSetupReq{timestamp: ts},
ErrorCode: int(setup.Failure.ErrorCode),
InfoField: *ifield,
MaxBWTrail: bwTrail,
}
s, err = NewFailureSetupReq(path, ts, setup.ReservationID, setup.Failure)
default:
return nil, serrors.New("invalid E2E setup request received, neither successful or failed",
"success_ptr", setup.Success, "failure_ptr", setup.Failure)
}
return s, nil
return s, err
}

// CleanupReq is a cleaup request for an e2e index.
type CleanupReq struct {
BaseSetupReq
}

// NewCleanupReqFromCtrlMsg contructs a cleanup request from its control message counterpart.
func NewCleanupReqFromCtrlMsg(ctrl *colibri_mgmt.E2ECleanup, ts time.Time,
path *spath.Path) (*CleanupReq, error) {

baseReq, err := NewBaseSetupReq(path, ts, ctrl.ReservationID)
if err != nil {
return nil, serrors.WrapStr("cannot construct cleanup request", err)
}
return &CleanupReq{
BaseSetupReq: *baseReq,
}, nil
}

// ToCtrlMsg converts this application type to its control message counterpart.
func (r *CleanupReq) ToCtrlMsg() *colibri_mgmt.E2ECleanup {
rawid := make([]byte, reservation.E2EIDLen)
r.ID.Read(rawid)
return &colibri_mgmt.E2ECleanup{
ReservationID: &colibri_mgmt.E2EReservationID{
ASID: rawid[:6],
Suffix: rawid[6:],
},
}
}
Loading

0 comments on commit e243193

Please sign in to comment.