Skip to content

Commit

Permalink
hp: add gRPC beacon register
Browse files Browse the repository at this point in the history
  • Loading branch information
karampok authored and lukedirtwalker committed Dec 4, 2020
1 parent 2b6e6d5 commit cc7ec7b
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 38 deletions.
1 change: 0 additions & 1 deletion go/pkg/hiddenpath/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ go_test(
deps = [
"//go/cs/beacon:go_default_library",
"//go/cs/beaconing:go_default_library",
"//go/cs/beaconing/mock_beaconing:go_default_library",
"//go/cs/ifstate:go_default_library",
"//go/lib/addr:go_default_library",
"//go/lib/common:go_default_library",
Expand Down
28 changes: 20 additions & 8 deletions go/pkg/hiddenpath/beaconwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ import (
"github.com/scionproto/scion/go/lib/serrors"
)

// SegmentRegistration is a registration for hidden segments.
type SegmentRegistration struct {
GroupID GroupID
Seg seg.Meta
}

// Register is used to register segments to a remote.
type Register interface {
RegisterSegment(context.Context, SegmentRegistration, net.Addr) error
}

// BeaconWriter terminates segments and registers them at remotes. The remotes
// can either be a public core segment registry or a hidden segment registry.
type BeaconWriter struct {
Expand All @@ -46,9 +57,9 @@ type BeaconWriter struct {
Intfs *ifstate.Interfaces
// Extender is used to terminate the beacon.
Extender beaconing.Extender
// RPCs are used to send the segment to the remote. For public registrations
// RPC is used to send the segment to the remote. For public registrations
// the entry with an empty group ID as key is used.
RPCs map[GroupID]beaconing.RPC
RPC Register
// Pather is used to construct paths to the originator of a beacon.
Pather beaconing.Pather
// RegistrationPolicy is the hidden path registration policy.
Expand Down Expand Up @@ -100,12 +111,11 @@ func (w *BeaconWriter) Write(ctx context.Context, segments <-chan beacon.BeaconO
internalErrors: w.InternalErrors,
registered: w.Registered,
summary: summary,
segType: seg.TypeDown,
hiddenPathGroup: id,
resolveRemote: func(ctx context.Context) (net.Addr, error) {
return w.AddressResolver.Resolve(ctx, a)
},
rpc: w.RPCs[id],
rpc: w.RPC,
}
if id.ToUint64() == 0 {
// public
Expand Down Expand Up @@ -136,15 +146,17 @@ type remoteWriter struct {
internalErrors metrics.Counter
registered metrics.Counter
summary *summary
segType seg.Type
hiddenPathGroup GroupID
resolveRemote func(context.Context) (net.Addr, error)
rpc beaconing.RPC
rpc Register
}

// run resolves, and writes the segment to the remote registry.
func (w *remoteWriter) run(ctx context.Context, bseg beacon.Beacon) {
reg := seg.Meta{Type: w.segType, Segment: bseg.Segment}
reg := SegmentRegistration{
Seg: seg.Meta{Type: seg.TypeDown, Segment: bseg.Segment},
GroupID: w.hiddenPathGroup,
}

logger := log.FromCtx(ctx)

Expand Down Expand Up @@ -185,7 +197,7 @@ func (w *remoteWriter) hpGroup() string {
}

func (w *remoteWriter) segTypeString() string {
s := w.segType.String()
s := seg.TypeDown.String()
if w.hiddenPathGroup.ToUint64() != 0 {
s = "hidden_" + s
}
Expand Down
48 changes: 22 additions & 26 deletions go/pkg/hiddenpath/beaconwriter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (

"github.com/scionproto/scion/go/cs/beacon"
"github.com/scionproto/scion/go/cs/beaconing"
"github.com/scionproto/scion/go/cs/beaconing/mock_beaconing"
"github.com/scionproto/scion/go/cs/ifstate"
"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
Expand Down Expand Up @@ -92,38 +91,38 @@ func TestRemoteBeaconWriterWrite(t *testing.T) {
topoProvider := itopotest.TopoProviderFromFile(t, topoNonCore)

testCases := map[string]struct {
beacons [][]common.IFIDType
createRPCs func(*testing.T, *gomock.Controller) map[hiddenpath.GroupID]beaconing.RPC
policy hiddenpath.RegistrationPolicy
resolver func(*gomock.Controller) hiddenpath.AddressResolver
beacons [][]common.IFIDType
createRPC func(*testing.T, *gomock.Controller) hiddenpath.Register
policy hiddenpath.RegistrationPolicy
resolver func(*gomock.Controller) hiddenpath.AddressResolver
}{
"Only public registration": {
beacons: [][]common.IFIDType{
{graph.If_120_X_111_B},
{graph.If_130_B_120_A, graph.If_120_X_111_B},
},
createRPCs: func(t *testing.T,
ctrl *gomock.Controller) map[hiddenpath.GroupID]beaconing.RPC {
createRPC: func(t *testing.T,
ctrl *gomock.Controller) hiddenpath.Register {

rpc := mock_beaconing.NewMockRPC(ctrl)
rpc := mock_hiddenpath.NewMockRegister(ctrl)
rpc.EXPECT().RegisterSegment(gomock.Any(), gomock.Any(),
matchSVCCS("1-ff00:0:120")).DoAndReturn(
func(_ context.Context, meta seg.Meta, remote net.Addr) error {
validatePublicSeg(t, meta.Segment, remote.(*snet.SVCAddr), topoProvider)
func(_ context.Context, reg hiddenpath.SegmentRegistration,
remote net.Addr) error {
validatePublicSeg(t, reg.Seg.Segment, remote.(*snet.SVCAddr), topoProvider)
return nil
},
)
rpc.EXPECT().RegisterSegment(gomock.Any(), gomock.Any(),
matchSVCCS("1-ff00:0:130")).DoAndReturn(
func(_ context.Context, meta seg.Meta, remote net.Addr) error {
validatePublicSeg(t, meta.Segment, remote.(*snet.SVCAddr), topoProvider)
func(_ context.Context, reg hiddenpath.SegmentRegistration,
remote net.Addr) error {
validatePublicSeg(t, reg.Seg.Segment, remote.(*snet.SVCAddr), topoProvider)
return nil
},
)

return map[hiddenpath.GroupID]beaconing.RPC{
{}: rpc,
}
return rpc
},
policy: hiddenpath.RegistrationPolicy{
uint64(graph.If_111_B_120_X): hiddenpath.InterfacePolicy{
Expand All @@ -139,24 +138,21 @@ func TestRemoteBeaconWriterWrite(t *testing.T) {
{graph.If_120_X_111_B},
{graph.If_130_B_120_A, graph.If_120_X_111_B},
},
createRPCs: func(t *testing.T,
ctrl *gomock.Controller) map[hiddenpath.GroupID]beaconing.RPC {

rpc := mock_beaconing.NewMockRPC(ctrl)
createRPC: func(t *testing.T,
ctrl *gomock.Controller) hiddenpath.Register {
rpc := mock_hiddenpath.NewMockRegister(ctrl)
rpc.EXPECT().RegisterSegment(gomock.Any(), gomock.Any(),
addrMatcher{udp: &snet.UDPAddr{
IA: xtest.MustParseIA("1-ff00:0:114"),
Host: xtest.MustParseUDPAddr(t, "10.1.0.1:404"),
}}).Times(2).DoAndReturn(
func(_ context.Context, meta seg.Meta, remote net.Addr) error {
validateHS(t, meta.Segment)
func(_ context.Context, reg hiddenpath.SegmentRegistration,
remote net.Addr) error {
validateHS(t, reg.Seg.Segment)
return nil
},
)

return map[hiddenpath.GroupID]beaconing.RPC{
mustParseGroupID(t, "ff00:0:140-2"): rpc,
}
return rpc
},
policy: hiddenpath.RegistrationPolicy{
uint64(graph.If_111_B_120_X): hiddenpath.InterfacePolicy{
Expand Down Expand Up @@ -203,7 +199,7 @@ func TestRemoteBeaconWriterWrite(t *testing.T) {
MaxExpTime: func() uint8 { return uint8(beacon.DefaultMaxExpTime) },
StaticInfo: func() *beaconing.StaticInfoCfg { return nil },
},
RPCs: tc.createRPCs(t, ctrl),
RPC: tc.createRPC(t, ctrl),
Pather: addrutil.Pather{
UnderlayNextHop: func(ifID uint16) (*net.UDPAddr, bool) {
return topoProvider.Get().UnderlayNextHop2(common.IFIDType(ifID))
Expand Down
4 changes: 2 additions & 2 deletions go/pkg/hiddenpath/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ type Lookuper interface {
Segments(context.Context, SegmentRequest) ([]*seg.Meta, error)
}

// RPC is used to fetch hidden segments from a remote.
// RPC is used to fetch hidden segments from a remote and to register segments to a remote.
type RPC interface {
HiddenSegments(ctx context.Context, req SegmentRequest, dst net.Addr) ([]*seg.Meta, error)
HiddenSegments(context.Context, SegmentRequest, net.Addr) ([]*seg.Meta, error)
}

// Verifier is used to verify a segments reply.
Expand Down
3 changes: 3 additions & 0 deletions go/pkg/hiddenpath/grpc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ go_library(
srcs = [
"discovery.go",
"lookup.go",
"register.go",
"registry.go",
"requester.go",
],
importpath = "github.com/scionproto/scion/go/pkg/hiddenpath/grpc",
visibility = ["//visibility:public"],
deps = [
"//go/cs/beaconing:go_default_library",
"//go/lib/addr:go_default_library",
"//go/lib/ctrl/seg:go_default_library",
"//go/lib/infra/modules/segfetcher:go_default_library",
"//go/lib/serrors:go_default_library",
"//go/lib/snet:go_default_library",
"//go/pkg/grpc:go_default_library",
"//go/pkg/hiddenpath:go_default_library",
"//go/pkg/proto/control_plane:go_default_library",
"//go/pkg/proto/discovery:go_default_library",
"//go/pkg/proto/hidden_segment:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
Expand Down
64 changes: 64 additions & 0 deletions go/pkg/hiddenpath/grpc/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2020 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 grpc

import (
"context"
"net"

"github.com/scionproto/scion/go/cs/beaconing"
"github.com/scionproto/scion/go/lib/ctrl/seg"
libgrpc "github.com/scionproto/scion/go/pkg/grpc"
"github.com/scionproto/scion/go/pkg/hiddenpath"
"github.com/scionproto/scion/go/pkg/proto/control_plane"
hppb "github.com/scionproto/scion/go/pkg/proto/hidden_segment"
hspb "github.com/scionproto/scion/go/pkg/proto/hidden_segment"
)

// Register can be used to register segments to remotes.
type Register struct {
// Dialer dials a new gRPC connection.
Dialer libgrpc.Dialer
// RegularRegistration is the regular segment registration.
RegularRegistration beaconing.RPC
}

// RegisterSegment registers the segment at the remote. If the hidden path group
// ID is not defined it is registered via a normal segment registration message
func (s Register) RegisterSegment(ctx context.Context,
reg hiddenpath.SegmentRegistration, remote net.Addr) error {

if reg.GroupID.ToUint64() == 0 { // do regular public registration
return s.RegularRegistration.RegisterSegment(ctx, reg.Seg, remote)
}

conn, err := s.Dialer.Dial(ctx, remote)
if err != nil {
return err
}
defer conn.Close()

client := hspb.NewHiddenSegmentRegistrationServiceClient(conn)
in := &hspb.HiddenSegmentRegistrationRequest{
GroupId: reg.GroupID.ToUint64(),
Segments: map[int32]*hppb.Segments{
int32(reg.Seg.Type): {Segments: []*control_plane.PathSegment{
seg.PathSegmentToPB(reg.Seg.Segment),
}},
},
}
_, err = client.HiddenSegmentRegistration(ctx, in, libgrpc.RetryProfile...)
return err
}
1 change: 1 addition & 0 deletions go/pkg/hiddenpath/mock_hiddenpath/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ gomock(
"AddressResolver",
"Discoverer",
"Registry",
"Register",
],
library = "//go/pkg/hiddenpath:go_default_library",
package = "mock_hiddenpath",
Expand Down
39 changes: 38 additions & 1 deletion go/pkg/hiddenpath/mock_hiddenpath/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit cc7ec7b

Please sign in to comment.