dataplane

package
v0.0.0-...-83008cd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2026 License: Apache-2.0 Imports: 40 Imported by: 0

Documentation

Index

Constants

View Source
const (
	UDPIPv4Name  = "UDP/IPv4"
	UDPIPv6Name  = "UDP/IPv6"
	UDPIPv46Name = "UDP/IPv4+6"
)
View Source
const (
	// TODO(karampok). Investigate whether that value should be higher.  In
	// theory, PayloadLen in SCION header is 16 bits long, supporting a maximum
	// payload size of 64KB. At the moment we are limited by Ethernet size
	// usually ~1500B, but 9000B to support jumbo frames.
	// TODO(multi_underlay): The buffer size should be a function of the collection of
	// underlays (the largest frame size of all the enabled ones).
	BufferSize = 9000
)
View Source
const (
	// EndhostPort is the underlay port that SCION binds to on non-routers. Subject to
	// change during standardisation.
	EndhostPort = 30041
)

Variables

View Source
var (
	ErrUnsupportedV4MappedV6Address  = errors.New("unsupported v4mapped IP v6 address")
	ErrUnsupportedUnspecifiedAddress = errors.New("unsupported unspecified address")
	ErrNoSVCBackend                  = errors.New("cannot find internal IP for the SVC")
)

Functions

func ClassOfSize

func ClassOfSize(pktSize int) sizeClass

func ResolveAddrPort

func ResolveAddrPort(s string) (netip.AddrPort, error)

ResolveAddrPort resolves a "host:port" address. IPv4 addresses in the v4-mapped IPv6 form are normalized to plain IPv4.

func UpdateOutputMetrics

func UpdateOutputMetrics(ctx context.Context, metrics *InterfaceMetrics, packets []*Packet)

UpdateOutputMetrics accounts for the given packets in the output metrics, aggregated by traffic type and size class.

Types

type DataPlane

type DataPlane struct {
	RunConfig RunConfig
	// contains filtered or unexported fields
}

func NewDataPlane

func NewDataPlane(
	ia addr.IA,
	host addr.Host,
	key []byte,
	provider UnderlayProvider,
	links []Link,
) (*DataPlane, error)

NewDataPlane creates a data plane for the given IA. The links must include at most one link with IfID 0 (the internal link) and are indexed by their interface ID. All links must have been created by the given provider.

func (*DataPlane) Serve

func (d *DataPlane) Serve(ctx context.Context) error

type InterfaceMetrics

type InterfaceMetrics [maxSizeClass]trafficMetrics

interfaceMetrics is the set of metrics that are relevant for one given interface. It is a map that associates each (traffic-type, size-class) pair with the set of metrics belonging to that interface that have these label values. This set of metrics is itself a trafficMetric structure. Explanation: Metrics are labeled by interface, local-as, neighbor-as, packet size, and (for output metrics only) traffic type. Instances are grouped in a hierarchical manner for efficient access by the using code. forwardingMetrics is a map of interface to interfaceMetrics. To access a specific InputPacketsTotal counter, one refers to:

dataplane.forwardingMetrics[interface][size-class].

trafficMetrics.Output is an array of outputMetrics indexed by traffic type.

type Link interface {
	// IsUp returns whether this link is functional according to the associated BFD session.
	IsUp() bool
	// IfID returns the interface ID associated with this link. 0 for sibling and internal links.
	IfID() uint16
	// Metrics returns the metrics specific to this link.
	Metrics() *InterfaceMetrics
	// Scope returns the scope of this link: internal, external, or sibling.
	Scope() LinkScope
	// BFDSession returns the BFD session associated with this link.
	BFDSession() Session
	// Resolve finds and sets the packet's internal underlay destination for the given dst and port.
	Resolve(p *Packet, dst addr.Host, port uint16) error
	// Send queues the packet for sending over this link; discarding if the queue is full.
	Send(p *Packet) bool
	// SendBlocking queues the packet for sending over this link; blocking while the queue is full.
	SendBlocking(p *Packet)
}

Link embodies the router's idea of a point to point connection. A link associates the underlay connection with a BFDSession, a destination address, etc. It also allows the concrete send operation to be delegated to different underlay implementations. The association between link and underlay connection is a channel, on the sending side, and a demultiplexer on the receiving side. The demultiplexer must have a src-addr:link map in all cases where links share connections.

Regardless of underlay, links come in three scopes: internal, sibling, and external. The difference in behaviour is hidden from the rest of the router. The router only needs to associate an interface ID with a link. If the interface ID belongs to a sibling router, then the link is a sibling link. If the interface ID is zero, then the link is the internal link.

Note about Resolve. It resolves the given SCION host/svc address to an address on this underlay. This functionality is really only needed on the internal link,

type LinkScope

type LinkScope int

LinkScope describes the kind (or scope) of a link: internal, sibling, or external.

const (
	Internal LinkScope = iota // to/from end-hosts in the local AS
	Sibling                   // to/from (external interfaces owned by) a sibling router
	External                  // to/from routers in another AS
)

type Metrics

type Metrics struct {
	// contains filtered or unexported fields
}

Metrics holds the metric instruments shared by all interfaces of a data plane. The instruments are created from the global otel meter provider; if none is configured, all counters are no-ops.

func NewMetrics

func NewMetrics() (*Metrics, error)

func (*Metrics) NewInterfaceMetrics

func (m *Metrics) NewInterfaceMetrics(ifID uint16, localIA, neighbor addr.IA) *InterfaceMetrics

NewInterfaceMetrics returns the metrics for one interface, labeled by the given interface ID, local IA, and neighbor IA.

type Packet

type Packet struct {
	// The useful part of the raw packet at a point in time (i.e. a slice of the full buffer).  It
	// can be any portion of the full buffer; not necessarily the start. This code maintains the
	// invariant that RawPacket always represents the portion of a packet that immediately follows
	// any underlay provider header. See also dataplane.underlayHeadroom.
	RawPacket []byte

	// The source address during ingest and the destination during forwarding. We never need both
	// src and dst at the same time. The real type is only known to underlay provider that sets it.
	RemoteAddr unsafe.Pointer
	// The ingest link; which can give us the ifID, scope, bfdSession...
	Link Link
	// contains filtered or unexported fields
}

Packet aggregates buffers and ancillary metadata related to one packet. That is everything we need to pass-around while processing a packet. The motivation is to save on copy (pass everything via one reference) AND garbage collection (reuse everything). The buffer is allocated in a separate location (but still reused) to keep the packet structures tightly packed (might not matter, though). Golang gives precious little guarantees about alignment and padding. We do it ourselves in such a way that Go has no sane reason to add any padding. Everything is 8 byte aligned (on 64 bit arch) until SlowpathRequest which is 4 bytes long. The rest is in decreasing order of size and size-aligned. We want to fit neatly into cache lines, so we need to fit in 64 bytes. The padding required to occupy exactly 64 bytes depends on the architecture.

func (*Packet) WithHeader

func (p *Packet) WithHeader(n int) []byte

WithHeader returns the a slice of the underlying packet buffer that represents the same bytes as p.rawPacket[:] plus the n prededing bytes. This slice is meant to be used when receiving a raw packet with an n bytes header, such that the payload is exactly at p.rawPacket[0:]. p.RawPacket is *not* modified. This method panics if n is greater than the available headroom in the packet buffer.

type PacketPool

type PacketPool struct {
	// contains filtered or unexported fields
}

PacketPool allocates and resets packets. There is one packet pool per instance of the dataplane, shared between all its underlay instances. This structure can be shared by copying (and doing so is more efficient) because headroom is never changed after construction and channel is a reference type.

func (*PacketPool) Get

func (p *PacketPool) Get() *Packet

Get fetches a packet from the pool and returns it initialized with the proper headroom. That is, pkt.rawPacket[0:] is where the packet's payload must go. Underlay providers may use any part of that, and MUST update the pkt.rawPacket slice to indicate where the packet's payload starts. However they may only use the preceding portion of the packet buffer to store a link-layer header. See also WithHeader

func (*PacketPool) Put

func (p *PacketPool) Put(pkt *Packet)

Put returns the given packet to the pool.

type RunConfig

type RunConfig struct {
	NumProcessors         int
	NumSlowPathProcessors int
	BatchSize             int
	ReceiveBufferSize     int
	SendBufferSize        int
}

type Services

type Services[addrT comparable] struct {
	// contains filtered or unexported fields
}

Services is a generic anycast address map, for use by underlay providers to implement the SCION service mapping.

func NewServices

func NewServices[addrT comparable]() *Services[addrT]

func (*Services[addrT]) AddSvc

func (s *Services[addrT]) AddSvc(svc addr.SVC, a addrT)

func (*Services[addrT]) Any

func (s *Services[addrT]) Any(svc addr.SVC) (addrT, bool)

func (*Services[addrT]) DelSvc

func (s *Services[addrT]) DelSvc(svc addr.SVC, a addrT)

type Session

type Session interface {
	ReceiveMessage(msg *layers.BFD)
}

type Type

type Type int
const (
	Invalid Type = iota
	UDPIPv4
	UDPIPv6
	UDPIPv46
)

func TypeFromString

func TypeFromString(s string) (Type, error)

func (Type) IsUDP

func (ot Type) IsUDP() bool

func (Type) MarshalJSON

func (ot Type) MarshalJSON() ([]byte, error)

func (Type) String

func (ot Type) String() string

func (*Type) UnmarshalJSON

func (ot *Type) UnmarshalJSON(data []byte) error

type UDPProvider

type UDPProvider struct {
	// contains filtered or unexported fields
}

UDPProvider implements UnderlayProvider over UDP/IP. External links get an exclusive connected socket; the internal link uses a single unconnected socket.

func NewUDPProvider

func NewUDPProvider(batchSize int, receiveBufferSize int, sendBufferSize int) *UDPProvider

NewUDPProvider returns a new provider for exclusive use by the caller.

func (*UDPProvider) AddSvc

func (u *UDPProvider) AddSvc(svc addr.SVC, host addr.Host, port uint16) error

AddSvc adds the address for the given service.

func (*UDPProvider) DelSvc

func (u *UDPProvider) DelSvc(svc addr.SVC, host addr.Host, port uint16) error

DelSvc deletes the address for the given service.

func (*UDPProvider) Headroom

func (u *UDPProvider) Headroom() int
func (u *UDPProvider) NewExternalLink(
	qSize int,
	bfd Session,
	local string,
	remote string,
	ifID uint16,
	metrics *InterfaceMetrics,
) (Link, error)

NewExternalLink returns an external link over the UDP/IP underlay, always implemented with a connectedLink.

func (u *UDPProvider) NewInternalLink(
	local string, qSize int, metrics *InterfaceMetrics,
) (Link, error)

NewInternalLink returns an internal link over the UDP/IP underlay. At most one internal link is supported.

func (*UDPProvider) NumConnections

func (u *UDPProvider) NumConnections() int

func (*UDPProvider) Start

func (u *UDPProvider) Start(
	ctx context.Context,
	pool PacketPool,
	procQs []chan *Packet,
)

Start puts the provider in the running state. The queues to be used by the receiver tasks are supplied at this point because they must be sized according to the number of connections that will be started.

func (*UDPProvider) Stop

func (u *UDPProvider) Stop()

type UnderlayProvider

type UnderlayProvider interface {
	// NumConnections returns the current number of configured connections.
	NumConnections() int

	// Headroom returns the length of the largest header possibly added by this underlay.
	// The dataplane ensures that all received packets are stored at an offset in the packet
	// buffer such that the largest underlay header declared across all underlay providers can
	// be prepended to the SCION header without having to copy the packet or to allocate a
	// separate buffer.
	Headroom() int

	// NewExternalLink returns a link that addresses a single remote AS at a unique underlay
	// address. Outgoing packets do not need an underlay destination as metadata. Incoming
	// packets have a defined ingress ifID.
	NewExternalLink(
		qSize int,
		bfd Session,
		local string,
		remote string,
		ifID uint16,
		metrics *InterfaceMetrics,
	) (Link, error)

	// NewInternalLink returns a link that addresses any host internal to the enclosing AS.
	// Outgoing packets need to have a destination address as metadata. Incoming packets have
	// no defined ingress ifID.
	NewInternalLink(localAddr string, qSize int, metrics *InterfaceMetrics) (Link, error)

	// Start puts the provider in the running state. In that state, the provider delivers
	// incoming packets to the given processor queues and sends the packets queued on its
	// links. Only connections in existence at the time of calling Start are started.
	Start(ctx context.Context, pool PacketPool, procQs []chan *Packet)

	// Stop puts the provider in the stopped state. In that state, the provider no longer
	// delivers incoming packets and ignores packets present on its input channels.
	Stop()
}

UnderlayProvider is a provider of connectivity over some underlay implementation. It owns the connections that carry the traffic of the links it creates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL