network

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package network defines host-local networks and attaches instances to them, assigning their addresses and naming their interfaces. It is portable: it drives the host through Host, which internal/hostnet implements.

Index

Constants

View Source
const (
	MinMTU = 576
	MaxMTU = 9000
)

The MTU range a network may have.

View Source
const (
	// DefaultNameserver is the nameserver a network forwards to.
	DefaultNameserver = "8.8.8.8"
	// DefaultMTU is a network's MTU.
	DefaultMTU = 1500
)

Defaults applied to a network that does not specify them.

View Source
const (
	ProtocolTCP = "tcp"
	ProtocolUDP = "udp"
)

The protocols a port mapping may name.

View Source
const DefaultName = "default"

DefaultName is the name of the default network, which the daemon creates itself and an instance joins when it names no network.

Variables

View Source
var ErrNoAvailableIPs = errdefs.ResourceExhausted("the network has no free addresses left")

ErrNoAvailableIPs is returned when a network's subnet has no address left to give out.

Functions

func Assignable

func Assignable(ipNet *net.IPNet, ip net.IP) bool

Assignable reports whether ip can be given out on ipNet: an address in it other than its network and broadcast addresses.

func BridgeName

func BridgeName(networkName string) string

BridgeName returns the bridge name for a network: "dicer-<name>" if it fits in an interface name, otherwise "dbr-" and a hash of the name.

func CheckSubnetOverlap added in v0.4.0

func CheckSubnetOverlap(n Network, networks []Network, hostSubnets []netip.Prefix) error

CheckSubnetOverlap returns an ErrExists error if n's subnet overlaps one of networks, or one of hostSubnets, whose addresses n's would hide.

func IFBName added in v0.4.0

func IFBName(instanceID string) string

IFBName returns the name of the IFB device an instance's upload is shaped on: "ifb-" followed by the same hash as its TAP device's name.

func MetricDescriptions added in v0.4.0

func MetricDescriptions() []metric.Description

MetricDescriptions returns the descriptions of every metric the network manager serves, for the reference.

func ParseSubnet

func ParseSubnet(s string) (*net.IPNet, error)

ParseSubnet parses a network's subnet: an IPv4 CIDR with room for at least one instance. The result is normalised, so "10.0.0.5/24" is 10.0.0.0/24.

func TAPName

func TAPName(instanceID string) string

TAPName returns the TAP device name for an instance: "tap-" followed by the 8 hex digits of an FNV-1a hash of its ID. It is derived rather than stored, so every holder of an instance ID agrees on it.

Types

type Allocation added in v0.4.0

type Allocation struct {
	NetworkID  string `yaml:"network_id"`
	InstanceID string `yaml:"instance_id"`
	IP         string `yaml:"ip"`
	MAC        string `yaml:"mac"`

	// InstanceName and TAPDevice are derived when the allocation is read
	// and not stored.
	InstanceName string `yaml:"-"`
	TAPDevice    string `yaml:"-"`
}

Allocation is one instance's address on a network, held for as long as the instance is defined.

type AttachOptions added in v0.4.0

type AttachOptions struct {
	// StaticIP is the address the instance takes. Empty takes a free one.
	StaticIP string
	// Bandwidth limits what the instance's guest sends and receives.
	Bandwidth Bandwidth
	// Ports are the host ports forwarded to the instance's address.
	Ports []PortMapping
	// Disconnected keeps the instance's TAP device off the network's bridge
	// until ConnectInstance, so that nothing the guest sends reaches the
	// network. A fork needs this: it wakes with the address of the instance
	// it is a copy of.
	Disconnected bool
}

AttachOptions says how an instance attaches to a network.

type Attachment added in v0.4.0

type Attachment struct {
	Allocation Allocation
	// TAPDevice is the host's end of the guest's network interface.
	TAPDevice string
	// Nameservers are the nameservers the guest asks: the gateway while the
	// network's DNS server runs, and its upstream nameservers otherwise.
	Nameservers []string
}

Attachment is an instance's place on a network, as its VMM and guest are given it.

type Bandwidth

type Bandwidth struct {
	UploadBytesPerSecond   int64
	DownloadBytesPerSecond int64
}

Bandwidth limits the bytes per second an instance's guest sends and receives. Zero is unlimited.

type Config

type Config struct {
	// Dir is the directory the allocation tables are kept in.
	Dir string
	// Store keeps the network definitions. Creating, deleting and listing
	// networks need it, and allocating addresses does not.
	Store Store
	// Host sets up the networks' bridges and the instances' TAP devices
	// and published ports, and says which subnets a new network may not
	// overlap. Nil leaves the host alone and skips that check.
	Host Host
	// DNSServers serve each network's guests their nameserver. Nil serves
	// none.
	DNSServers DNSServers
	// Events records what happens to networks. Nil records nothing.
	Events Recorder
	// Logger is where the Manager logs. Nil is slog.Default().
	Logger *slog.Logger
}

Config configures a Manager.

type DNSServers added in v0.4.0

type DNSServers interface {
	// Serve starts serving a network, unless it already is. The network's
	// bridge must be up.
	Serve(ctx context.Context, nw Network) error
	// Stop stops serving a network.
	Stop(network string)
	// Serving reports whether a network is served.
	Serving(network string) bool
}

DNSServers answer the DNS queries of each network's guests, on the network's gateway address.

type Host added in v0.4.0

type Host interface {
	// SetupBridge sets up a network's bridge, or makes sure it is as it
	// should be when it is already there.
	SetupBridge(ctx context.Context, nw *Network) error
	// TeardownBridge removes a network's bridge, logging what it cannot.
	TeardownBridge(ctx context.Context, nw *Network)
	// Subnets returns the subnets the host's interfaces are on, which a new
	// network may not overlap.
	Subnets() ([]netip.Prefix, error)

	// CreateTAP creates an instance's TAP device, limited to bandwidth and
	// off the network's bridge. On failure the device may be left behind
	// for RemoveTAP.
	CreateTAP(ctx context.Context, nw *Network, instanceID string, bandwidth Bandwidth) error
	// ConnectTAP puts an instance's TAP device on the network's bridge.
	ConnectTAP(ctx context.Context, nw *Network, instanceID string) error
	// RemoveTAP removes an instance's TAP device, logging what it cannot.
	RemoveTAP(ctx context.Context, nw *Network, instanceID string)

	// PublishPorts forwards host ports to the instance's address, replacing
	// any it already published.
	PublishPorts(ctx context.Context, nw *Network, allocation *Allocation, ports []PortMapping) error
	// UnpublishPorts removes every port the instance published, logging
	// what it cannot.
	UnpublishPorts(ctx context.Context, instanceID string)
}

Host makes networks and their instances' attachments real on the host: bridges with their firewall rules, TAP devices and published ports. It also says which subnets the host is already on.

type Manager

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

Manager creates and deletes networks, whose definitions a Store keeps, with their bridges and DNS servers, and attaches instances to them. It persists the instances' address allocations, so an instance keeps its address across restarts. Allocations are released on delete and reconciled at daemon start.

The allocation tables are read from disk once, when the Manager is made, and kept in memory, so that looking an address up -- as the networks' DNS servers do for every query -- reads no file. The Manager must be the only writer of its directory. It is safe for concurrent use.

func NewManager

func NewManager(cfg Config) (*Manager, error)

NewManager returns a Manager storing its allocation tables under cfg.Dir, with those already there read. One that cannot be read fails the calls about its network, not NewManager.

func (*Manager) Allocate

func (m *Manager) Allocate(n Network, instanceID, staticIP string) (Allocation, error)

Allocate assigns an address to an instance, or returns the one it holds. A staticIP must be in the subnet and free.

func (*Manager) Allocation added in v0.4.0

func (m *Manager) Allocation(network, instanceID string) (Allocation, error)

Allocation returns the allocation held by an instance on a network, or an errdefs.ErrNotFound error if it holds none.

func (*Manager) AttachInstance added in v0.4.0

func (m *Manager) AttachInstance(
	ctx context.Context, n Network, instanceID string, opts AttachOptions,
) (Attachment, error)

AttachInstance gives an instance its address on a network, or the one it already holds, and sets up its TAP device and published ports. On failure the address is kept, and nothing is left on the host.

func (*Manager) Collect added in v0.4.0

func (m *Manager) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector: each defined network's address pool, as it is now. A network whose allocations cannot be read is left out.

func (*Manager) ConnectInstance added in v0.4.0

func (m *Manager) ConnectInstance(ctx context.Context, n Network, instanceID string) error

ConnectInstance puts the TAP device of an instance attached with Disconnected on its network's bridge.

func (*Manager) Create added in v0.4.0

func (m *Manager) Create(ctx context.Context, spec Spec) (Network, error)

Create defines the network spec asks for and sets up its bridge, refusing a name that is taken and a subnet another network or the host is on. Unset gateway, MTU and nameservers take their defaults. A network whose bridge cannot be set up is not created.

func (*Manager) Delete added in v0.4.0

func (m *Manager) Delete(ctx context.Context, nameOrID string) error

Delete removes a network's definition, its bridge and its allocations, refusing the default network and one an instance or snapshot is on.

func (*Manager) Describe added in v0.4.0

func (m *Manager) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

func (*Manager) DetachInstance added in v0.4.0

func (m *Manager) DetachInstance(ctx context.Context, n Network, instanceID string)

DetachInstance removes an instance's published ports and TAP device. Its address is kept, and so is the network's bridge, which lives as long as the network. Failures are logged rather than returned.

func (*Manager) EnsureDefault added in v0.4.0

func (m *Manager) EnsureDefault(subnet string) error

EnsureDefault defines the default network on subnet, unless it already exists. An existing one is left as it is. Its bridge is set up, as every network's, by SetupBridges.

func (*Manager) Forget

func (m *Manager) Forget(network string) error

Forget discards a network's whole allocation table, for use when the network itself is deleted. Forgetting a network with none is not an error.

func (*Manager) InstanceAt added in v0.4.0

func (m *Manager) InstanceAt(network, ip string) (string, bool)

InstanceAt returns the ID of the instance holding ip on a network. It reports false if none does, or if the network's allocation table cannot be read.

func (*Manager) List

func (m *Manager) List(nameOrID string) ([]Allocation, error)

List returns every allocation on a network, by name or ID. The slice is the caller's. A Manager without a Store, which only allocates addresses, takes the network's name alone.

func (*Manager) Network added in v0.4.0

func (m *Manager) Network(nameOrID string) (Network, error)

Network returns a network by name or ID.

func (*Manager) Networks added in v0.4.0

func (m *Manager) Networks() []Network

Networks returns every network, sorted by name.

func (*Manager) Reconcile

func (m *Manager) Reconcile(networks []string, live map[string]struct{}) (int, error)

Reconcile drops allocations on the given networks held by instances not in live, and returns how many it released.

func (*Manager) Release

func (m *Manager) Release(network, instanceID string) error

Release drops an instance's allocation. Releasing one that does not exist is not an error, so cleanup paths can call it unconditionally.

func (*Manager) SetupBridges added in v0.4.0

func (m *Manager) SetupBridges(ctx context.Context)

SetupBridges sets up every network's bridge, with its DNS server, as the daemon starts: a reboot removes them. A bridge that cannot be set up is logged, and costs only its own network's instances their start.

type Network added in v0.4.0

type Network struct {
	ID          string   `yaml:"id"`
	Name        string   `yaml:"name"`
	Gateway     string   `yaml:"gateway"`
	Subnet      string   `yaml:"subnet"`
	Bridge      string   `yaml:"bridge"`
	Nameservers []string `yaml:"nameservers,omitempty"`
	MTU         int      `yaml:"mtu,omitempty"`
	Isolated    bool     `yaml:"isolated,omitempty"`
	// Internal stops the network's instances reaching anything beyond it:
	// the outside, other networks, the host's services and upstream
	// nameservers.
	Internal  bool      `yaml:"internal,omitempty"`
	CreatedAt time.Time `yaml:"created_at"`
	UpdatedAt time.Time `yaml:"updated_at"`

	// TotalIPs and FreeIPs count the addresses for instances. They are
	// computed when the network is read and not stored.
	TotalIPs int64 `yaml:"-"`
	FreeIPs  int64 `yaml:"-"`
}

Network is a bridged network instances attach to, with an address pool of its own.

func New added in v0.4.0

func New(spec Spec) (Network, error)

New returns the network spec asks for, with a new ID, or an invalid argument error. It does not check the subnet against other networks or the host's: see CheckSubnetOverlap.

func (Network) IPCounts added in v0.4.0

func (n Network) IPCounts(allocated int) (total, free int64)

IPCounts returns how many addresses the network has for instances and how many of them are free with allocated taken. The network, broadcast and gateway addresses are excluded. Both are zero if the subnet is invalid.

func (Network) Netmask added in v0.4.0

func (n Network) Netmask() (string, error)

Netmask returns the network's subnet mask in dotted-quad form.

func (Network) PrefixLen added in v0.4.0

func (n Network) PrefixLen() (int, error)

PrefixLen returns the length of the network's subnet prefix.

func (Network) Validate added in v0.4.0

func (n Network) Validate() error

Validate returns an invalid argument error unless the network has a valid name, an MTU in range and nameservers that are IP addresses, and its settings agree with each other.

type PortMapping added in v0.4.0

type PortMapping struct {
	// HostIP is the host address to publish on. Empty means every
	// non-loopback address.
	HostIP    string `yaml:"host_ip,omitempty" json:"host_ip,omitempty"`
	HostPort  uint16 `yaml:"host_port" json:"host_port"`
	GuestPort uint16 `yaml:"guest_port" json:"guest_port"`

	// Protocol is tcp or udp. Empty means tcp.
	Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"`
}

PortMapping publishes a guest port on the host.

func (PortMapping) EffectiveProtocol added in v0.4.0

func (p PortMapping) EffectiveProtocol() string

EffectiveProtocol returns the mapping's protocol, filling in the default.

func (PortMapping) Overlaps added in v0.4.0

func (p PortMapping) Overlaps(other PortMapping) bool

Overlaps reports whether two mappings claim the same host port. A mapping on every address overlaps one on any single address.

func (PortMapping) String added in v0.4.0

func (p PortMapping) String() string

String is the mapping as a person writes it: "[hostIP:]hostPort:guestPort/protocol".

func (PortMapping) Validate added in v0.4.0

func (p PortMapping) Validate() error

Validate returns an invalid argument error if the mapping cannot be published.

type Recorder added in v0.4.0

type Recorder interface {
	Record(e event.Event)
}

Recorder records what happens to networks. It is declared here, and satisfied by internal/event, so that this package reports what it does without knowing who listens.

type Spec added in v0.4.0

type Spec struct {
	Name        string
	Subnet      string
	Gateway     string
	MTU         int
	Nameservers []string
	Isolated    bool
	Internal    bool
}

Spec is what a new network is asked to be. An unset gateway, MTU or nameservers take their defaults.

type Store added in v0.4.0

type Store interface {
	CreateNetwork(n Network) error
	Network(nameOrID string) (Network, error)
	Networks() []Network
	// DeleteNetwork refuses a network an instance or snapshot is on.
	DeleteNetwork(nameOrID string) error
}

Store keeps the network definitions.

Jump to

Keyboard shortcuts

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