Documentation
¶
Overview ¶
Package controlplane implements CION's control plane: discovery of directly connected neighbors, and the control endpoint that serves trust material RPCs over HTTP/3 (QUIC) riding the SCION network.
Index ¶
- Constants
- func EndpointTLS(cfg EndpointTLSConfig) *tls.Config
- func ManageTLSCert(ctx context.Context, cfg TLSCertConfig) (*tls.Config, error)
- func RunCoreEnrollment(ctx context.Context, cfg EnrollmentConfig)
- func RunEnrollment(ctx context.Context, cfg EnrollmentConfig)
- func ServeHTTP3(conn *SCIONConn, handler http.Handler, tlsConf *tls.Config) error
- type Addr
- type BeaconStore
- type Beaconer
- type BeaconerConfig
- type Candidate
- type Client
- type ControlPlane
- type CoreClient
- func (c *CoreClient) Chains(ctx context.Context, q trust.ChainQuery) ([][]*x509.Certificate, error)
- func (c *CoreClient) Close() error
- func (c *CoreClient) RenewChain(ctx context.Context, csr *x509.CertificateRequest, key crypto.Signer) ([]*x509.Certificate, error)
- func (c *CoreClient) SetCore(ia addr.IA, addr netip.AddrPort)
- func (c *CoreClient) SetLocator(locator func() *Addr)
- func (c *CoreClient) TRC(ctx context.Context, id cppki.TRCID) (cppki.SignedTRC, error)
- type CoreClientConfig
- type Discovery
- func (d *Discovery) Close() error
- func (d *Discovery) CoreEndpoint() (addr.IA, netip.AddrPort, bool)
- func (d *Discovery) Neighbors() map[uint16]Neighbor
- func (d *Discovery) Register(provider *dataplane.UDPProvider) error
- func (d *Discovery) Run(ctx context.Context)
- func (d *Discovery) SetCoreEndpoint(ia addr.IA, addr netip.AddrPort)
- type DiscoveryConfig
- type EndpointTLSConfig
- type EnrollmentConfig
- type Greeting
- type LookupService
- type Neighbor
- type PathProvider
- type PeerClient
- func (c *PeerClient) Beacon(ctx context.Context, peer *Addr, pcb *cppb.PathSegment) error
- func (c *PeerClient) Close() error
- func (c *PeerClient) RegisterSegments(ctx context.Context, peer *Addr, segments []*cppb.PathSegment) error
- func (c *PeerClient) Segments(ctx context.Context, peer *Addr, src, dst addr.IA) (*cppb.SegmentsResponse, error)
- type PeerClientConfig
- type SCIONConn
- func (c *SCIONConn) Close() error
- func (c *SCIONConn) LocalAddr() net.Addr
- func (c *SCIONConn) ReadFrom(b []byte) (int, net.Addr, error)
- func (c *SCIONConn) SetDeadline(t time.Time) error
- func (c *SCIONConn) SetReadDeadline(t time.Time) error
- func (c *SCIONConn) SetWriteDeadline(t time.Time) error
- func (c *SCIONConn) WriteTo(b []byte, addr net.Addr) (int, error)
- type SCIONConnConfig
- type SegmentSender
- type SegmentService
- func (s *SegmentService) Beacon(ctx context.Context, req *connect.Request[cppb.BeaconRequest]) (*connect.Response[cppb.BeaconResponse], error)
- func (s *SegmentService) Segments(ctx context.Context, req *connect.Request[cppb.SegmentsRequest]) (*connect.Response[cppb.SegmentsResponse], error)
- func (s *SegmentService) SegmentsRegistration(ctx context.Context, req *connect.Request[cppb.SegmentsRegistrationRequest]) (*connect.Response[cppb.SegmentsRegistrationResponse], error)
- type Server
- type Services
- type TLSCertConfig
- type TrustService
- func (s *TrustService) ChainRenewal(ctx context.Context, req *connect.Request[cppb.ChainRenewalRequest]) (*connect.Response[cppb.ChainRenewalResponse], error)
- func (s *TrustService) Chains(ctx context.Context, req *connect.Request[cppb.ChainsRequest]) (*connect.Response[cppb.ChainsResponse], error)
- func (s *TrustService) TRC(ctx context.Context, req *connect.Request[cppb.TRCRequest]) (*connect.Response[cppb.TRCResponse], error)
Constants ¶
const ( // PropagationInterval is the beaconing period: the draft's intra-ISD // floor of five seconds (Section 2.3.4). PropagationInterval = 5 * time.Second // RegistrationInterval is the registration period (Section 3.1), on the // order of a minute. RegistrationInterval = time.Minute // BestSetSize is the fixed bounded set of PCBs selected for forwarding // and termination (ADR-0004: no policy engine, no per-policy // configuration). BestSetSize = 5 // SendTimeout bounds each beacon and registration RPC: a wedged // connection must not stall the loop that sends it. SendTimeout = 5 * time.Second )
const ( // EnrollmentRetryInterval is the pause between enrollment attempts. EnrollmentRetryInterval = 5 * time.Second // ChainInspectInterval is the pause between validity inspections of a // valid chain. ChainInspectInterval = time.Minute // EnrollmentTimeout bounds one enrollment attempt: a wedged connection // must not stall the loop renewing through it. EnrollmentTimeout = 10 * time.Second )
Chain lifecycle intervals (proposal 0004): while unenrolled the loop keeps a fast retry cadence; with a valid chain it settles to a calm inspection interval.
const DiscoveryPort = 30043
DiscoveryPort is the SCION UDP port used by the discovery greeting. The port is irrelevant for delivery (greetings are addressed to the CS service address), but a fixed value keeps the traffic identifiable.
const EndpointPort = 30044
EndpointPort is the SCION UDP port of the control endpoint. The port is fixed so that a node can reach a neighbor's endpoint knowing only the underlay address advertised in the discovery greeting.
Variables ¶
This section is empty.
Functions ¶
func EndpointTLS ¶
func EndpointTLS(cfg EndpointTLSConfig) *tls.Config
EndpointTLS composes the endpoint's TLS configuration: the bootstrap channel — the WebPKI certificate for clients offering the core's domain as the TLS server name — and the SCION-native channel for everything else (proposal 0004).
func ManageTLSCert ¶
ManageTLSCert returns the server TLS configuration for the endpoint. With certificate files configured it loads them once; otherwise the certificate for the domain is managed by certmagic, with the ACME HTTP-01 and TLS-ALPN-01 challenges answered on dedicated TCP listeners (ports 80 and 443) — ACME servers validate over TCP, never QUIC. DNS-01 support follows later.
func RunCoreEnrollment ¶
func RunCoreEnrollment(ctx context.Context, cfg EnrollmentConfig)
RunCoreEnrollment runs the founding core's chain lifecycle: the same loop with a local action — self-issuing through the core's issuer whenever the renewal threshold demands it. The synchronous startup self-enrollment is the first pass; this loop keeps the chain valid for the node's lifetime.
func RunEnrollment ¶
func RunEnrollment(ctx context.Context, cfg EnrollmentConfig)
RunEnrollment runs the chain lifecycle of a non-core node: each pass reads the newest chain's remaining validity, re-enrolls when it drops below the renewal threshold or when no valid chain exists, and watches the pinned TRC's validity the same way — log only, since a new base TRC means redeploying (ADR-0003).
Types ¶
type Addr ¶
type Addr struct {
// IA is the ISD-AS of the peer.
IA addr.IA
// Addr is the peer's underlay address.
Addr netip.AddrPort
// IfID is the local egress interface toward the peer; zero means it is
// resolved from the link table on write.
IfID uint16
// Path is the full data-plane path to the peer, supplied by the path
// provider; nil sends over a one-hop path resolved from the link table.
// The hop-field MACs come from the segment, computed by each on-path AS
// at beacon time, not by the sender.
Path *scion.Decoded
}
Addr is the SCION network address of a control endpoint. It doubles as the return route: replies leave on the IfID the peer's packet arrived on, or over the reversed arrival path when the peer reached us over a full SCION path.
The interface ID and path are deliberately not part of String, so the address quic-go sees for a connection stays stable regardless of the interface a particular packet traveled on.
type BeaconStore ¶
type BeaconStore struct {
// contains filtered or unexported fields
}
BeaconStore holds candidate PCBs in memory (draft Section 2.3.2): keyed by ingress interface and segment ID, keeping the latest origination per key, expiring entries with their hops. A restarted node is rebuilt by the next period's beacons.
func NewBeaconStore ¶
func NewBeaconStore() *BeaconStore
func (*BeaconStore) BestSet ¶
func (s *BeaconStore) BestSet(n int) []Candidate
BestSet returns the fixed bounded set of freshest unexpired candidates — the store's per-key freshness ordering is the only selection rule (ADR-0004: no policy engine).
func (*BeaconStore) Insert ¶
func (s *BeaconStore) Insert(ingress uint16, pcb *segment.PCB)
Insert stores the beacon, replacing the entry with the same key when the new origination is fresher, and keeping per-interface capacity bounded by evicting the stalest candidates.
func (*BeaconStore) Len ¶
func (s *BeaconStore) Len() int
Len returns the number of stored candidates.
type Beaconer ¶
type Beaconer struct {
// contains filtered or unexported fields
}
Beaconer runs ADR-0004's exploration: the founding core originates signed path-segment beacons on its links, every node verifies the accumulated signatures against the TRC before storing or propagating them, propagation floods outward with the TRC naming the cores whose interfaces are pruned, and non-cores terminate accepted beacons into registered segments. Link roles are not configured: the interface a beacon arrives on is the node's parent side, the interfaces beacons are propagated to are child sides, and a link whose neighbor the TRC names as a core is a core link.
func NewBeaconer ¶
func NewBeaconer(cfg BeaconerConfig) (*Beaconer, error)
NewBeaconer returns a beaconer with the defaults filled in.
func (*Beaconer) BootstrapRoute ¶
BootstrapRoute returns the reversed data-plane path of the freshest unverified beacon originating at dst, extended with the node's own unsigned hop — the route of a node that has not yet verified any up segment to that core: its enrollment fetch and the trust fetches around it ride it, all protected by the WebPKI-authenticated channel. It is never stored, propagated, or registered, serves only its originating core, and verified up segments take over the moment one exists.
func (*Beaconer) HandleBeacon ¶
HandleBeacon applies the reception checks of Section 2.3.1 to the received PCB and stores it as a candidate. A node that has not pinned the TRC cannot verify beacons; it records the freshest one as its bootstrap route for the enrollment fetch instead.
func (*Beaconer) HandleRegistration ¶
func (b *Beaconer) HandleRegistration( ctx context.Context, pb *control_plane.PathSegment, ) error
HandleRegistration verifies a down segment registered with this core and stores it in the path database (Sections 3.1.3 and 3.3).
type BeaconerConfig ¶
type BeaconerConfig struct {
// IA is the local ISD-AS.
IA addr.IA
// Engine signs AS entries and verifies received ones.
Engine *trust.Engine
// MACKey is the data-plane forwarding key, MACing created hop fields
// with the same algorithm the processor verifies.
MACKey []byte
// Store is the in-memory beacon store for candidates.
Store *BeaconStore
// DB is the persistent path database for registered segments.
DB pathdb.DB
// Links maps each external interface ID to the IA of the neighbor.
Links map[uint16]addr.IA
// Neighbors returns the currently discovered neighbors; nil disables
// sending beacons (reception still works).
Neighbors func() map[uint16]Neighbor
// Sender sends beacon and registration RPCs over the SCION-native
// channel.
Sender SegmentSender
// CoreRoute resolves the core's endpoint — the one-hop path when the
// core is a neighbor, else the provider's route.
CoreRoute func() *Addr
// Core marks the founding core, which originates beacons.
Core bool
// PropagationInterval and RegistrationInterval override the defaults;
// zero keeps them.
PropagationInterval time.Duration
RegistrationInterval time.Duration
// Now is the clock; nil uses time.Now.
Now func() time.Time
// SendTimeout bounds each RPC; zero uses the default.
SendTimeout time.Duration
}
BeaconerConfig configures a Beaconer.
type Candidate ¶
type Candidate struct {
// Ingress is the interface the beacon arrived on: the node's parent
// side of that link (ADR-0004's emergent link roles).
Ingress uint16
// PCB is the candidate beacon.
PCB *segment.PCB
}
Candidate is a stored beacon with the interface it arrived on.
type Client ¶
type Client struct {
control_planeconnect.SegmentCreationServiceClient
control_planeconnect.TrustMaterialServiceClient
control_planeconnect.SegmentRegistrationServiceClient
control_planeconnect.SegmentLookupServiceClient
control_planeconnect.ChainRenewalServiceClient
}
Client implements the Interface by making RPC calls to a remote server.
func NewClient ¶
func NewClient(clt connect.HTTPClient, baseURL string, opts ...connect.ClientOption) *Client
NewClient creates a new control plane client.
type ControlPlane ¶
type ControlPlane interface {
control_planeconnect.SegmentCreationServiceHandler
control_planeconnect.TrustMaterialServiceHandler
control_planeconnect.SegmentRegistrationServiceHandler
control_planeconnect.SegmentLookupServiceHandler
control_planeconnect.ChainRenewalServiceHandler
}
ControlPlane covers all control plane RPCs.
type CoreClient ¶
type CoreClient struct {
// contains filtered or unexported fields
}
CoreClient resolves trust material from the core's control endpoint: ConnectRPC over HTTP/3 (QUIC) riding the SCION network, TLS-verified end-to-end against the core's domain. The domain is a TLS identity, not a locator; the locator supplies the SCION route — a one-hop neighbor's address from discovery, or the provider's multi-hop path.
func NewCoreClient ¶
func NewCoreClient(cfg CoreClientConfig) (*CoreClient, error)
NewCoreClient dials the core's control endpoint. The client fails on use, not on creation: until the locator names a reachable core, requests fail fast and are retried by the caller.
func (*CoreClient) Chains ¶
func (c *CoreClient) Chains( ctx context.Context, q trust.ChainQuery, ) ([][]*x509.Certificate, error)
Chains fetches the chains matching the query.
func (*CoreClient) Close ¶
func (c *CoreClient) Close() error
Close releases the underlying QUIC transport.
func (*CoreClient) RenewChain ¶
func (c *CoreClient) RenewChain( ctx context.Context, csr *x509.CertificateRequest, key crypto.Signer, ) ([]*x509.Certificate, error)
RenewChain requests a chain for the CSR. The CMS wrapper is signed by the subject key itself, the proof of possession a first-issuance request offers.
func (*CoreClient) SetCore ¶
func (c *CoreClient) SetCore(ia addr.IA, addr netip.AddrPort)
SetCore sets the SCION locator of the core: its IA and the underlay address of its control endpoint, the discovery greeting's control address with the endpoint port.
func (*CoreClient) SetLocator ¶
func (c *CoreClient) SetLocator(locator func() *Addr)
SetLocator sets the locator resolving the core's SCION address at dial time; it overrides SetCore's address.
type CoreClientConfig ¶
type CoreClientConfig struct {
// Domain is the core's DNS domain, verified as the TLS server name.
Domain string
// Conn is the SCION connection QUIC rides to the core.
Conn *SCIONConn
// RootCAs anchors the TLS verification; nil means the system roots.
RootCAs *x509.CertPool
// Locator resolves the core's SCION address: its IA, underlay endpoint,
// and path — the one-hop path when the core is a neighbor, else the
// reversed freshest up segment (proposal 0004). It is consulted at dial
// time, so later dials pick up fresh paths. Nil falls back to SetCore.
Locator func() *Addr
}
CoreClientConfig configures a CoreClient.
type Discovery ¶
type Discovery struct {
// contains filtered or unexported fields
}
Discovery exchanges greetings with directly connected neighbors and keeps the resulting neighbor table. Greetings are sent over the router's internal network and forwarded by the data plane over each external link; incoming greetings are delivered back to the control service via the CS service address.
func NewDiscovery ¶
func NewDiscovery(cfg DiscoveryConfig) (*Discovery, error)
func (*Discovery) Close ¶
Close releases the resources of the discovery service, unblocking Run. The instance cannot be used afterwards.
func (*Discovery) CoreEndpoint ¶
CoreEndpoint returns the core control endpoint learned from greetings, fresh within the greeting timeout.
func (*Discovery) Neighbors ¶
Neighbors returns the currently reachable neighbors, by interface ID. Neighbors whose last greeting is older than three intervals are omitted.
func (*Discovery) Register ¶
func (d *Discovery) Register(provider *dataplane.UDPProvider) error
Register advertises the control service address in the data plane so that greetings addressed to the CS service are delivered to this instance.
type DiscoveryConfig ¶
type DiscoveryConfig struct {
// IA is the local ISD-AS.
IA addr.IA
// ControlAddr is the underlay address to listen on and to advertise to
// neighbors. It must be reachable from the neighbor ASes.
ControlAddr string
// MACKey is the forwarding key, shared with the data plane, used to MAC
// the one-hop paths of outgoing greetings.
MACKey []byte
// InternalAddr is the router's internal underlay address.
InternalAddr string
// Links maps each external interface ID to the IA of the neighbor.
Links map[uint16]addr.IA
// Interval between greetings; defaults to 1s if zero.
Interval time.Duration
}
DiscoveryConfig configures a Discovery instance.
type EndpointTLSConfig ¶
type EndpointTLSConfig struct {
// Domain is the core's WebPKI identity; clients offering it as the TLS
// server name are served the bootstrap channel. Empty on non-core nodes,
// which serve only the SCION-native channel.
Domain string
// WebPKI serves the bootstrap channel; typically from ManageTLSCert. Nil
// disables the channel.
WebPKI *tls.Config
// Engine provides the node's AS chain for the SCION-native channel.
Engine *trust.Engine
}
EndpointTLSConfig configures the endpoint's two channels.
type EnrollmentConfig ¶
type EnrollmentConfig struct {
// IA is the node's ISD-AS.
IA addr.IA
// DB holds the node's chains and the pinned TRC.
DB trust.DB
// Key is the node's AS key.
Key crypto.Signer
// Remote enrolls against the core's endpoint; nil on the founding
// core, which self-issues through the Issuer.
Remote trust.Remote
// Issuer self-issues the core's chains.
Issuer *trust.Issuer
// RetryInterval and InspectInterval override the defaults; zero keeps
// them.
RetryInterval time.Duration
InspectInterval time.Duration
// Timeout bounds one enrollment attempt; zero uses the default.
Timeout time.Duration
// Now is the clock for validity decisions; nil uses time.Now. Tests
// advance it past a chain's validity to exercise re-enrollment.
Now func() time.Time
}
EnrollmentConfig configures the lifetime chain lifecycle of a node (proposal 0004): every node keeps a valid chain — the founding core included — by re-enrolling before expiry, with warnings as expiry approaches and errors once it passes.
type Greeting ¶
type Greeting struct {
// IA is the ISD-AS of the sender.
IA addr.IA
// IfID is the sender's interface ID of the link the greeting travels on.
IfID uint16
// ControlAddr is the underlay address of the sender's control service.
ControlAddr netip.AddrPort
// CoreIA and CoreAddr name the control endpoint of the core the sender
// reaches — itself, on the core. Nodes relay what they learned, so a
// node without a direct link to the core learns where its enrollment
// fetch is aimed once beaconing supplies the path. Zero CoreIA omits
// the fields.
CoreIA addr.IA
CoreAddr netip.AddrPort
}
Greeting is the discovery message exchanged between directly connected nodes. It is carried as the payload of a SCION/UDP packet addressed to the CS service of the neighbor, over a one-hop path; the one-hop path serves both directions of the link and requires no path state on either side.
func ParseGreeting ¶
type LookupService ¶
type LookupService struct {
// IA is the local ISD-AS.
IA addr.IA
// DB is the local path database.
DB pathdb.DB
// IsCore selects the core's handler behavior.
IsCore bool
// Cores enumerates the core ASes of an ISD named by the pinned TRC; nil
// cores mean the TRC is not pinned.
Cores func(isd addr.ISD) []addr.IA
// Fetch requests segments from a core's control service.
Fetch func(ctx context.Context, peer *Addr, src, dst addr.IA) (*cppb.SegmentsResponse, error)
// CoreRoute resolves the core's endpoint to fetch through.
CoreRoute func() *Addr
// Now is the clock; nil uses time.Now.
Now func() time.Time
// contains filtered or unexported fields
}
LookupService implements the draft's segment-request handlers: the source- AS handler of a non-core (Section 4.2.2) — up segments from the local path database, core and down segments fetched from the core's control service with expiry-aware caching, source wildcards expanded per Table 4 — and the core handler (Section 4.2.3), which serves from the local database.
func NewLookupService ¶
func NewLookupService() *LookupService
NewLookupService returns a lookup service with an empty cache.
func (*LookupService) DBGet ¶
func (s *LookupService) DBGet(q pathdb.Query) []*pathdb.Segment
DBGet reads the local database.
func (*LookupService) Down ¶
Down returns the down segments serving dst, fetching and caching them from the core's control service as needed; the path provider composes them.
func (*LookupService) Segments ¶
func (s *LookupService) Segments( ctx context.Context, req *connect.Request[cppb.SegmentsRequest], ) (*connect.Response[cppb.SegmentsResponse], error)
Segments serves a segment request (draft Section 5).
type Neighbor ¶
type Neighbor struct {
// IA is the ISD-AS of the neighbor.
IA addr.IA
// IfID is the neighbor's interface ID of the direct link.
IfID uint16
// ControlAddr is the underlay address of the neighbor's control service.
ControlAddr netip.AddrPort
// LastSeen is the time of the last received greeting.
LastSeen time.Time
}
Neighbor is the state of a directly connected neighbor AS, learned from discovery greetings.
type PathProvider ¶
type PathProvider struct {
// IA is the local ISD-AS.
IA addr.IA
// DB holds the local up segments.
DB pathdb.DB
// Lookup resolves down segments, fetching them from the core's control
// service with expiry-aware caching.
Lookup *LookupService
// Bootstrap yields the reversed data-plane path of the freshest
// unverified beacon originating at a core: the enrollment route of a
// node that has not pinned the TRC yet — the WebPKI-authenticated
// channel protects that exchange (proposal 0004).
Bootstrap func(core addr.IA) *scion.Decoded
// Cores enumerates the core ASes of an ISD named by the pinned TRC.
Cores func(isd addr.ISD) []addr.IA
}
PathProvider composes up, core, and down segments into end-to-end SCION paths — reversal, expiry filtering, and segment combination written once — and is the only consumer seam of ADR-0004: the control transport and, later, endhost exposure consume identical paths through it.
func (*PathProvider) LocalPath ¶
LocalPath resolves a data-plane path from local state only: up segments and the bootstrap beacon, never a fetch. It is the variant safe to call from inside a dial — resolving a route must not spawn RPCs over the very transport being dialed.
func (*PathProvider) Path ¶
Path returns a data-plane path from the local AS to dst: to a core, the reversed freshest up segment — or, before any is verified, the reversed bootstrap beacon; anywhere else, a down segment from a core the node can reach — fetched with expiry-aware caching — composed after the reversed up segment to that core.
type PeerClient ¶
type PeerClient struct {
// contains filtered or unexported fields
}
PeerClient is the SCION-native channel's RPC client: ConnectRPC over HTTP/3 (QUIC) riding SCION paths, peers authenticated by AS certificate chains verified against the pinned TRC (proposal 0004). The peer address carries either a neighbor — sent over a one-hop path — or a SCION path supplied by the provider.
Beacons ride a client-authenticated channel whose server certificate is not verified: their receivers may not be enrolled yet, and the PCB's signatures authenticate the path authoritatively anyway. Registrations and lookups verify the peer's chain against the pinned TRC.
func NewPeerClient ¶
func NewPeerClient(cfg PeerClientConfig) *PeerClient
NewPeerClient creates the client for the SCION-native channel.
func (*PeerClient) Beacon ¶
func (c *PeerClient) Beacon(ctx context.Context, peer *Addr, pcb *cppb.PathSegment) error
Beacon propagates the extended PCB to the peer's beacon service (draft Section 2.3.5.1).
func (*PeerClient) Close ¶
func (c *PeerClient) Close() error
Close releases the underlying QUIC transport.
func (*PeerClient) RegisterSegments ¶
func (c *PeerClient) RegisterSegments( ctx context.Context, peer *Addr, segments []*cppb.PathSegment, ) error
RegisterSegments registers down segments with the core's control service (Sections 3.1.3 and 3.3).
type PeerClientConfig ¶
type PeerClientConfig struct {
// Engine provides the node's AS chain as the client certificate.
Engine *trust.Engine
// Conn is the SCION connection QUIC rides.
Conn *SCIONConn
// PathTo resolves the data-plane path to a destination that is not a
// direct neighbor; nil, or a nil result, sends over a one-hop path.
PathTo func(dst addr.IA) *scion.Decoded
}
PeerClientConfig configures a PeerClient.
type SCIONConn ¶
type SCIONConn struct {
// contains filtered or unexported fields
}
SCIONConn is a net.PacketConn that carries datagrams over the SCION network on one-hop paths to directly connected neighbors. It implements the interface quic-go requires of a connection, so an HTTP/3 server or client rides the SCION data plane unchanged.
func NewSCIONConn ¶
func NewSCIONConn(cfg SCIONConnConfig) (*SCIONConn, error)
NewSCIONConn binds the endpoint's underlay address. Packets it sends are submitted to the router's internal link; packets the router delivers to the bound address are received from it.
func (*SCIONConn) ReadFrom ¶
ReadFrom reads the next datagram, returning it with the peer's address. Packets that are not SCION/UDP over a one-hop path are dropped silently; greetings share the CS service address and are none of our business.
func (*SCIONConn) SetDeadline ¶
SetDeadline sets the read and write deadlines of the underlay socket.
func (*SCIONConn) SetReadDeadline ¶
SetReadDeadline sets the read deadline of the underlay socket.
func (*SCIONConn) SetWriteDeadline ¶
SetWriteDeadline sets the write deadline of the underlay socket.
func (*SCIONConn) WriteTo ¶
WriteTo sends the datagram to the peer as a SCION packet. A peer address carrying a path sends over that path — serialized fresh for every packet, so the routers' in-flight segment-ID updates never accumulate. A one-hop peer address has its path created fresh for every packet instead: the egress interface is taken from the address if the peer set one (replies), and resolved from the link table otherwise (client traffic).
type SCIONConnConfig ¶
type SCIONConnConfig struct {
// IA is the local ISD-AS.
IA addr.IA
// Bind is the underlay "host:port" address to listen on and advertise.
Bind string
// InternalAddr is the router's internal underlay address.
InternalAddr string
// MACKey is the data-plane forwarding key, used to MAC one-hop paths.
MACKey []byte
// Links maps each external interface ID to the IA of the neighbor.
Links map[uint16]addr.IA
}
SCIONConnConfig configures a SCIONConn.
type SegmentSender ¶
type SegmentSender interface {
// Beacon propagates the extended PCB to the peer's beacon service.
Beacon(ctx context.Context, peer *Addr, pcb *control_plane.PathSegment) error
// RegisterSegments registers down segments with the core's control
// service.
RegisterSegments(ctx context.Context, peer *Addr,
segments []*control_plane.PathSegment) error
}
SegmentSender sends beacon and registration RPCs over the SCION-native channel; PeerClient satisfies it.
type SegmentService ¶
type SegmentService struct {
// Beaconer receives and verifies beacons and registrations.
Beaconer *Beaconer
// Lookup serves segment requests.
Lookup *LookupService
}
SegmentService implements the segment RPCs of the control endpoint (ADR-0004): beacon reception on SegmentCreationService, down-segment registration on SegmentRegistrationService, and the source-AS segment-request handler on SegmentLookupService.
func (*SegmentService) Beacon ¶
func (s *SegmentService) Beacon( ctx context.Context, req *connect.Request[cppb.BeaconRequest], ) (*connect.Response[cppb.BeaconResponse], error)
Beacon receives a propagated PCB (draft Section 2.3.5.1), applying the reception checks of Section 2.3.1 before anything is stored. Beacons terminate on each node's control service, so every node serves this RPC.
func (*SegmentService) Segments ¶
func (s *SegmentService) Segments( ctx context.Context, req *connect.Request[cppb.SegmentsRequest], ) (*connect.Response[cppb.SegmentsResponse], error)
Segments serves a segment request (Section 5).
func (*SegmentService) SegmentsRegistration ¶
func (s *SegmentService) SegmentsRegistration( ctx context.Context, req *connect.Request[cppb.SegmentsRegistrationRequest], ) (*connect.Response[cppb.SegmentsRegistrationResponse], error)
SegmentsRegistration receives down segments registered by a non-core (Sections 3.1.3 and 3.3); the receiving core verifies each registered segment as on beacon reception.
type Server ¶
Server implements the control plane server.
func NewServer ¶
func NewServer(svc ControlPlane) *Server
NewServer creates a new control plane server.
type Services ¶
type Services struct {
*TrustService
*SegmentService
}
Services composes the trust and segment services into one ControlPlane; the segment service's methods take precedence over the trust service's unimplemented embeds.
type TLSCertConfig ¶
type TLSCertConfig struct {
// Domain is the DNS domain of the certificate. It is a TLS identity,
// never resolved: the SCION link is the locator.
Domain string
// CertFile and KeyFile point at the certificate and key in PEM format;
// when set, they take precedence over ACME. This is the fallback for
// offline deployments.
CertFile string
KeyFile string
// Storage is the directory for ACME state, e.g. account keys and
// obtained certificates. Empty defaults to certmagic's data directory.
Storage string
}
TLSCertConfig describes how the endpoint's TLS certificate is obtained: explicit certificate files, or a certificate for the domain managed via ACME (certmagic) as the default.
type TrustService ¶
type TrustService struct {
control_planeconnect.UnimplementedSegmentCreationServiceHandler
control_planeconnect.UnimplementedSegmentRegistrationServiceHandler
control_planeconnect.UnimplementedSegmentLookupServiceHandler
// DB serves trust material from the local trust database.
DB trust.DB
// Issuer signs certificate chains. It is nil on nodes that do not issue
// chains — everything but the founding core, in this milestone.
Issuer *trust.Issuer
// AllowAS optionally restricts enrollment to the listed ISD-ASes; nil
// means open enrollment.
AllowAS map[addr.IA]bool
// Now is the clock used for chain lookups; tests replace it.
Now func() time.Time
}
TrustService implements the trust material and chain renewal RPCs of the control endpoint. The segment services are not implemented yet; they arrive with beaconing (proposal 0004).
func (*TrustService) ChainRenewal ¶
func (s *TrustService) ChainRenewal( ctx context.Context, req *connect.Request[cppb.ChainRenewalRequest], ) (*connect.Response[cppb.ChainRenewalResponse], error)
ChainRenewal issues a certificate chain for the CSR carried by the request. First-issuance requests ride a CMS wrapper signed by the CSR's subject key itself — proof of possession of that key (PKI draft, Section 4.3) — since a fresh node has no certificate chain yet. The signed wrapper the reference implementation verifies against the requester's existing chain is honored for renewals only, which do not exist in this milestone.
func (*TrustService) Chains ¶
func (s *TrustService) Chains( ctx context.Context, req *connect.Request[cppb.ChainsRequest], ) (*connect.Response[cppb.ChainsResponse], error)
Chains serves the certificate chains matching the request.
func (*TrustService) TRC ¶
func (s *TrustService) TRC( ctx context.Context, req *connect.Request[cppb.TRCRequest], ) (*connect.Response[cppb.TRCResponse], error)
TRC serves a signed TRC. A request without base and serial numbers asks for the latest TRC of the ISD, which in a base-TRC-only milestone is the base TRC.