Skip to content

Commit

Permalink
hidden_paths: Slight change of approach to address configuration.
Browse files Browse the repository at this point in the history
The CS public address and the CS scion address can now be the same, while the service resolver explicitly gets a different port.

I am experimenting with the possibility of configuring the service resolver address as the regular address field of a new service named "service_resolution". (oncilla@ thinks it's a bad idea. I do not understand why yet but I guess I'll find out).

Also updated tests to match the intended changes, and to call assert.Equal() with arguments in the correct order.
  • Loading branch information
jiceatscion committed Aug 17, 2023
1 parent 2de1d5a commit 27e52fa
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 42 deletions.
7 changes: 7 additions & 0 deletions control/cmd/control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,16 @@ func realMain(ctx context.Context) error {

nc := infraenv.NetworkConfig{
IA: topo.IA(),
// Public: (Historical name) The TCP/IP:port address for this (control) service.
Public: topo.ControlServiceAddress(globalCfg.General.ID),
// ServiceResolution: The UDP/SCION address of the service "redirector". It is hosted by this
// (control service) process but as a separate service.
ServiceResolution: topo.ServiceResolutionAddress(globalCfg.General.ID),
ReconnectToDispatcher: globalCfg.General.ReconnectToDispatcher,
QUIC: infraenv.QUIC{
// Address: the QUIC/SCION address of this service. See QUICStack() for how address
// assigned. This can be configured statically and can be identical to the Public address.
// If not configured: a dynamic port is assigned.
Address: globalCfg.QUIC.Address,
TLSVerifier: trust.NewTLSCryptoVerifier(trustDB),
GetCertificate: cs.NewTLSCertificateLoader(
Expand Down
33 changes: 17 additions & 16 deletions control/hiddenpaths.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,26 +80,27 @@ func (c HiddenPathConfigurator) Setup(location string) (*HiddenPathRegistrationC
})
if roles.Registry {
log.Info("Starting hidden path authoritative and registration server")
hspb.RegisterAuthoritativeHiddenSegmentLookupServiceServer(c.InterASQUICServer,
&hpgrpc.AuthoritativeSegmentServer{
hsSegmentService := &hpgrpc.AuthoritativeSegmentServer{
Lookup: c.localAuthServer(groups),
Verifier: c.Verifier,
})
hspb.RegisterHiddenSegmentRegistrationServiceServer(c.InterASQUICServer,
&hpgrpc.RegistrationServer{
Registry: hiddenpath.RegistryServer{
Groups: groups,
DB: &hiddenpath.Storer{
DB: c.PathDB,
},
Verifier: hiddenpath.VerifierAdapter{
Verifier: c.Verifier,
},
LocalIA: c.LocalIA,
}
hspb.RegisterAuthoritativeHiddenSegmentLookupServiceServer(c.InterASQUICServer, hsSegmentService)
hspb.RegisterAuthoritativeHiddenSegmentLookupServiceServer(c.IntraASTCPServer, hsSegmentService)
hsRegistrationService := &hpgrpc.RegistrationServer{
Registry: hiddenpath.RegistryServer{
Groups: groups,
DB: &hiddenpath.Storer{
DB: c.PathDB,
},
Verifier: c.Verifier,
Verifier: hiddenpath.VerifierAdapter{
Verifier: c.Verifier,
},
LocalIA: c.LocalIA,
},
)
Verifier: c.Verifier,
}
hspb.RegisterHiddenSegmentRegistrationServiceServer(c.InterASQUICServer, hsRegistrationService)
hspb.RegisterHiddenSegmentRegistrationServiceServer(c.IntraASTCPServer, hsRegistrationService)
}
if !roles.Writer {
return nil, nil
Expand Down
40 changes: 17 additions & 23 deletions private/app/appnet/addr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ func TestRedirectQUIC(t *testing.T) {

a, r, err := aw.RedirectToQUIC(context.Background(), tc.input)
tc.assertErr(t, err)
assert.Equal(t, a, tc.wantAddr)
assert.Equal(t, r, tc.wantRedirect)
assert.Equal(t, tc.wantAddr, a)
assert.Equal(t, tc.wantRedirect, r)
})
}

Expand All @@ -97,9 +97,7 @@ func TestRedirectQUIC(t *testing.T) {
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)
path.EXPECT().Dataplane().Return(snetpath.SCION{})
path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{IP: net.ParseIP("10.1.1.1")})
path.EXPECT().Metadata().Return(&snet.PathMetadata{
Interfaces: make([]snet.PathInterface, 1), // just non-empty
})
path.EXPECT().Interfaces().Return(make([]snet.PathInterface, 1)) // just non-empty

aw := infraenv.AddressRewriter{
Router: router,
Expand Down Expand Up @@ -134,9 +132,7 @@ func TestRedirectQUIC(t *testing.T) {
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)
path.EXPECT().Dataplane().Return(snetpath.SCION{})
path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{IP: net.ParseIP("10.1.1.1")})
path.EXPECT().Metadata().Return(&snet.PathMetadata{
Interfaces: make([]snet.PathInterface, 1), // just non-empty
})
path.EXPECT().Interfaces().Return(make([]snet.PathInterface, 1)) // just non-empty

aw := infraenv.AddressRewriter{
Router: router,
Expand Down Expand Up @@ -166,7 +162,7 @@ func TestRedirectQUIC(t *testing.T) {
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)
path.EXPECT().Dataplane().Return(snetpath.SCION{})
path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{IP: net.ParseIP("10.1.1.1")})
path.EXPECT().Metadata().Return(&snet.PathMetadata{})
path.EXPECT().Interfaces().Return([]snet.PathInterface{})
svcRouter := mock_infraenv.NewMockSVCResolver(ctrl)
svcRouter.EXPECT().GetUnderlay(addr.SvcCS).Return(
&net.UDPAddr{IP: net.ParseIP("10.1.1.1")}, nil,
Expand All @@ -182,7 +178,7 @@ func TestRedirectQUIC(t *testing.T) {
want := &snet.SVCAddr{
SVC: addr.SvcCS,
NextHop: &net.UDPAddr{IP: net.ParseIP("10.1.1.1")},
Path: snetpath.SCION{},
Path: snetpath.Empty{},
}
a, r, err := aw.RedirectToQUIC(context.Background(), input)
assert.NoError(t, err)
Expand Down Expand Up @@ -225,7 +221,7 @@ func TestBuildFullAddress(t *testing.T) {
SVC: addr.SvcCS,
}
a, err := aw.BuildFullAddress(context.Background(), input)
assert.Equal(t, a, input)
assert.Equal(t, input, a)
assert.NoError(t, err)
})

Expand All @@ -243,9 +239,7 @@ func TestBuildFullAddress(t *testing.T) {
path := mock_snet.NewMockPath(ctrl)
path.EXPECT().Dataplane().Return(snetpath.SCION{})
path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{})
path.EXPECT().Metadata().Return(&snet.PathMetadata{
Interfaces: make([]snet.PathInterface, 1), // just non-empty
})
path.EXPECT().Interfaces().Return(make([]snet.PathInterface, 1)) // just non-empty
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)
input := &snet.SVCAddr{IA: remoteIA, SVC: addr.SvcCS, Path: snetpath.Empty{}}
a, err := aw.BuildFullAddress(context.Background(), input)
Expand All @@ -255,7 +249,7 @@ func TestBuildFullAddress(t *testing.T) {
NextHop: &net.UDPAddr{},
SVC: addr.SvcCS,
}
assert.Equal(t, a, want)
assert.Equal(t, want, a)
assert.NoError(t, err)
})

Expand All @@ -277,16 +271,16 @@ func TestBuildFullAddress(t *testing.T) {
svcRouter.EXPECT().GetUnderlay(addr.SvcCS).Return(underlayAddr, nil)

path := mock_snet.NewMockPath(ctrl)
path.EXPECT().Metadata().Return(&snet.PathMetadata{})
path.EXPECT().Interfaces().Return([]snet.PathInterface{})
path.EXPECT().Dataplane()
path.EXPECT().UnderlayNextHop()
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)

input := &snet.SVCAddr{IA: localIA, SVC: addr.SvcCS, Path: snetpath.Empty{}}
a, err := aw.BuildFullAddress(context.Background(), input)

want := &snet.SVCAddr{IA: localIA, NextHop: underlayAddr, SVC: addr.SvcCS}
assert.Equal(t, a, want)
want := &snet.SVCAddr{IA: localIA, NextHop: underlayAddr, SVC: addr.SvcCS, Path: snetpath.Empty{}}
assert.Equal(t, want, a)
assert.NoError(t, err)
})

Expand All @@ -304,7 +298,7 @@ func TestBuildFullAddress(t *testing.T) {
svcRouter.EXPECT().GetUnderlay(addr.SvcCS).Return(nil, errors.New("err"))

path := mock_snet.NewMockPath(ctrl)
path.EXPECT().Metadata().Return(&snet.PathMetadata{})
path.EXPECT().Interfaces().Return([]snet.PathInterface{})
path.EXPECT().Dataplane()
path.EXPECT().UnderlayNextHop()
router.EXPECT().Route(gomock.Any(), gomock.Any()).Return(path, nil)
Expand Down Expand Up @@ -388,9 +382,9 @@ func TestResolve(t *testing.T) {
}
initResolver(resolver, tc.ResolverSetup)
p, a, redirect, err := aw.ResolveSVC(context.Background(), path, tc.input)
assert.Equal(t, p, tc.wantPath)
assert.Equal(t, a.String(), tc.want.String())
assert.Equal(t, redirect, tc.wantQUICRedirect)
assert.Equal(t, tc.wantPath, p)
assert.Equal(t, tc.want.String(), a.String())
assert.Equal(t, tc.wantQUICRedirect, redirect)
tc.assertErr(t, err)
})
}
Expand Down Expand Up @@ -448,7 +442,7 @@ func TestParseReply(t *testing.T) {
if err != nil {
return
}
assert.Equal(t, a.String(), tc.want.String())
assert.Equal(t, tc.want.String(), a.String())
})
}
}
Expand Down
4 changes: 3 additions & 1 deletion private/app/appnet/infraenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ type NetworkConfig struct {
// Public is the Internet-reachable address in the case where the service
// is behind NAT.
Public *net.UDPAddr
// ServiceResolution is the address of the service resolver.
ServiceResolution *net.UDPAddr
// ReconnectToDispatcher sets up sockets that automatically reconnect if
// the dispatcher closes the connection (e.g., if the dispatcher goes
// down).
Expand Down Expand Up @@ -266,7 +268,7 @@ func (nc *NetworkConfig) initSvcRedirect(quicAddress string) (func(), error) {
Dispatcher: packetDispatcher,
Metrics: nc.SCIONNetworkMetrics,
}
conn, err := network.Listen(context.Background(), "udp", nc.Public, addr.SvcWildcard)
conn, err := network.Listen(context.Background(), "udp", nc.ServiceResolution, addr.SvcWildcard)
if err != nil {
return nil, serrors.WrapStr("listening on SCION", err, "addr", nc.Public)
}
Expand Down
16 changes: 15 additions & 1 deletion private/topology/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,15 @@ type Topology interface {
InterfaceIDs() []common.IFIDType

// PublicAddress gets the public address of a server with the requested type and name, and nil
// if no such server exists.
// if no such server exists. The service type is specified as a addr.SVC and retricted to
// addr.SvcDS and addr.SvcCS.
PublicAddress(svc addr.SVC, name string) *net.UDPAddr

// PublicAddressByType gets the public address of a server with the requested type and name, and nil
// if no such server exists. This support more types than PublicAddress. That is, all the types
// specified by topology.ServiceType.
PublicAddressByType(svc ServiceType, name string) *net.UDPAddr

// Anycast returns the address for an arbitrary server of the requested type.
Anycast(svc addr.SVC) (*net.UDPAddr, error)
// Multicast returns all addresses for the requested type.
Expand Down Expand Up @@ -203,6 +209,14 @@ func (t *topologyS) BR(name string) (BRInfo, bool) {
return br, ok
}

func (t *topologyS) PublicAddressByType(svc ServiceType, name string) *net.UDPAddr {
topoAddr, err := t.Topology.GetTopoAddr(name, svc)
if err != nil {
return nil
}
return topoAddr.SCIONAddress
}

func (t *topologyS) PublicAddress(svc addr.SVC, name string) *net.UDPAddr {
topoAddr := t.topoAddress(svc, name)
if topoAddr == nil {
Expand Down
1 change: 1 addition & 0 deletions private/topology/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type Topology struct {
HiddenSegmentLookup map[string]*ServerInfo `json:"hidden_segment_lookup_service,omitempty"`
HiddenSegmentReg map[string]*ServerInfo `json:"hidden_segment_registration_service,omitempty"`
SIG map[string]*GatewayInfo `json:"sigs,omitempty"`
ServiceResolution map[string]*ServerInfo `json:"service_resolution,omitempty"`
}

// ServerInfo contains the information for a SCION application running in the local AS.
Expand Down
7 changes: 7 additions & 0 deletions private/topology/reload.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ func (l *Loader) ControlServiceAddress(id string) *net.UDPAddr {
return l.topo.PublicAddress(addr.SvcCS, id)
}

func (l *Loader) ServiceResolutionAddress(id string) *net.UDPAddr {
l.mtx.Lock()
defer l.mtx.Unlock()

return l.topo.PublicAddressByType(ServiceResolution, id)
}

// TODO(lukedirtwalker): remove error and simplify struct in the return type.
func (l *Loader) Gateways() ([]GatewayInfo, error) {
l.mtx.Lock()
Expand Down
3 changes: 3 additions & 0 deletions private/topology/servicetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
Gateway
HiddenSegmentLookup
HiddenSegmentRegistration
ServiceResolution
)

func (t ServiceType) String() string {
Expand Down Expand Up @@ -64,6 +65,8 @@ func ServiceTypeFromString(s string) ServiceType {
return HiddenSegmentLookup
case "hiddensegmentregistration":
return HiddenSegmentRegistration
case "serviceresolution":
return ServiceResolution
default:
return Unknown
}
Expand Down
11 changes: 10 additions & 1 deletion private/topology/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type (
HiddenSegmentLookup IDAddrMap
HiddenSegmentRegistration IDAddrMap
SIG map[string]GatewayInfo
ServiceResolution IDAddrMap
}

// GatewayInfo describes a scion gateway.
Expand Down Expand Up @@ -146,6 +147,7 @@ func NewRWTopology() *RWTopology {
HiddenSegmentRegistration: make(IDAddrMap),
SIG: make(map[string]GatewayInfo),
IFInfoMap: make(IfInfoMap),
ServiceResolution: make(IDAddrMap),
}
}

Expand Down Expand Up @@ -309,6 +311,10 @@ func (t *RWTopology) populateServices(raw *jsontopo.Topology) error {
if err != nil {
return serrors.WrapStr("unable to extract hidden segment registration address", err)
}
t.ServiceResolution, err = svcMapFromRaw(raw.ServiceResolution)
if err != nil {
return serrors.WrapStr("unable to extract service resolution address", err)
}
return nil
}

Expand Down Expand Up @@ -363,6 +369,8 @@ func (t *RWTopology) getSvcInfo(svc ServiceType) (*svcInfo, error) {
m[k] = *v.CtrlAddr
}
return &svcInfo{idTopoAddrMap: m}, nil
case ServiceResolution:
return &svcInfo{idTopoAddrMap: t.ServiceResolution}, nil
default:
return nil, serrors.New("unsupported service type", "type", svc)
}
Expand All @@ -385,9 +393,10 @@ func (t *RWTopology) Copy() *RWTopology {

CS: t.CS.copy(),
DS: t.DS.copy(),
SIG: copySIGMap(t.SIG),
HiddenSegmentLookup: t.HiddenSegmentLookup.copy(),
HiddenSegmentRegistration: t.HiddenSegmentRegistration.copy(),
SIG: copySIGMap(t.SIG),
ServiceResolution: t.ServiceResolution.copy(),
}
}

Expand Down

0 comments on commit 27e52fa

Please sign in to comment.