network

package
v3.0.0-rc49 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// CNIVersion is the version we write in the generated CNI network configuration files
	CNIVersion = "0.3.0"
)

Variables

View Source
var (
	ErrInvalidType = errors.New("invalid network type")
)

Functions

func AllocateFor

func AllocateFor(ctx context.Context, i *ipam.T, p naming.Path, rid string) (net.IP, error)

AllocateFor reserves an address for a resource, refusing when the namespace has already taken all it claimed of the network.

The claim is checked only when the reservation is a new one. An allocator is idempotent for a key, and it is asked again on every start, so a resource that already holds its address is not taking one more: refusing it there would stop an object the cluster let take the address in the first place, and a namespace that reached its limit could no longer restart what it runs.

func CNIConfigFile

func CNIConfigFile(dir string, nw Networker) string

func ClaimFits

func ClaimFits(ctx context.Context, networkName, namespace string, p naming.Path, rid string) (bool, string, error)

ClaimFits says whether a namespace may take one more address of a network for a resource of an object, and why not when it may not.

A namespace with no claim on the network is not capped on it, and is answered from the local configuration alone, which is what most allocations are.

A capped one is brokered. The claim is asked of the daemon, which hands the question to the node speaking for the cluster: what the namespace holds is read from what the objects of the cluster publish, an object publishes its address after it has taken it, and two claims answered from the same reading both fit where together they do not. One node answering them, counting what it has granted since, is what makes them fit one at a time.

Failing to reach the daemon leaves the claim unchecked rather than refused, for the same reason a pool claim is: a cap is something the cluster brokers, and where there is no daemon to ask there is nothing brokering.

func ClaimHeldByKey

func ClaimHeldByKey(ctx context.Context, networkName, namespace string) (int, map[string]bool, error)

ClaimHeldByKey is how many addresses of a network a namespace holds, and the reservations they are held for.

Addresses are counted, not reservations: a failover object holds the same address on every node it is configured on, and that is one address taken from the network, while the instances of a flex each hold one of their own. The reservations are answered alongside so that a claim granted a moment ago and not yet reported can be told apart from one the cluster has caught up with.

Two views are merged. The cluster reports the addresses its objects publish in their status, which is the only way to see the other nodes, but a status is published after the fact: an address reserved a moment ago is not in it yet. The allocator of this node has no such lag, and this is read where every claim is answered, so what it adds is this node's own reservations, including the ones made before there was anything brokering. An address in both is one address. A network every node draws from adds a third view, the stores of the other nodes.

func ClaimLimit

func ClaimLimit(namespace, networkName string) (int, bool, error)

ClaimLimit is the most addresses a namespace may hold in a network, and whether it is capped on it at all.

func ClusterWideAllocators

func ClusterWideAllocators(n *object.Node) []*ipam.T

ClusterWideAllocators returns the allocators of this node in the networks every node draws from.

func Driver

func Driver(t string) func() Networker

func GetNodeAddr

func GetNodeAddr(nodename string, network string) (net.IP, error)

func IPReachableFrom

func IPReachableFrom(peerIP net.IP) (net.IP, *net.IPNet, error)

func InReverseZones

func InReverseZones(name string, zones []string) bool

InReverseZones says whether the reverse name, as a PTR record names it, is in one of the zones.

func IncIP

func IncIP(ip net.IP)

func IncIPN

func IncIPN(ip net.IP, n int)

func InstanceAddrs

func InstanceAddrs(allocators []*ipam.T, p naming.Path, st instance.Status) map[string]map[string]string

InstanceAddrs returns the addresses an instance status reports holding in the ranges of the allocators, by network name, each the key of the resource reporting it.

func IsDisabled

func IsDisabled(t Networker) bool

IsDisabled returns true if the network keyword value is "none"

func IsSameNetwork

func IsSameNetwork(localIP, peerIP net.IP) (bool, error)

func IsValid

func IsValid(t Networker) bool

IsValid returns true if the network configuration is sane enough to setup.

func List

func List(noder Noder) []string

func MACFromIP4

func MACFromIP4(ip net.IP) (net.HardwareAddr, error)

MACFromIP4 returns a mac address using a 0a:58 prefix followed by the bridge ipv4 address converted to hexa (same algorithm used in k8s).

When the device with the lowest mac is removed from the bridge or when a new device with the lowest mac is added to the bridge, all containers can experience tcp hangs while the arp table resynchronizes.

Setting a mac address to the bridge explicitly avoids these mac address changes.

func NewAllocator

func NewAllocator(nw Networker, nodename string) (*ipam.T, error)

NewAllocator returns the allocator of a network on a node, or nil when the network is one om allocates no address in.

func RedrawFor

func RedrawFor(ctx context.Context, i *ipam.T, p naming.Path, rid string, previous net.IP) (net.IP, error)

RedrawFor releases the address a resource holds, previous, and reserves another one.

It is what a resource whose recorded address was taken away asks for: the address it holds is the one it is to give up, so neither the reservation of this node nor the one it holds on another node is taken back.

A redraw that fails holds previous again, so the next one still knows what to give up.

func ReleaseRemoved

func ReleaseRemoved(p naming.Path, rids map[string]bool) (int, error)

ReleaseRemoved releases the addresses this node holds for the resources of an object that its configuration no longer has, the resources of rids being the ones it still has.

A resource is released when it is unprovisioned, which a section taken away from the configuration skips: its reservation would stay, out of the pool and counted against the claim of the namespace, until the object is deleted.

func ReverseZones

func ReverseZones(nw Networker) ([]string, error)

ReverseZones returns the reverse zones holding the PTR records of the addresses om hands out from the network, with no trailing dot: the ones of the ranges of a network handing out some of its segment only, as a lan network, else the ones of the whole network.

A zone is cut at an octet boundary for ipv4 and at a nibble boundary for ipv6, the finest covering the addresses and no others: the zones the cluster answers for hold none of the addresses it does not hand out, as the ones of the nodes, which the cluster nameservers would otherwise say do not exist. A /22 is four /24 zones, a /16 one, a range of a few addresses a zone each.

The lo network hands out no address, and has none.

func Setup

func Setup(n *object.Node, names ...string) error

Setup sets up the networks named, all of them when none is named, and the firewall rules of every network.

The firewall rules of the networks are one ruleset, rewritten whole: rendered from the networks named only, as the daemon sets up the one whose configuration changed, it dropped the rules of the others, and the containers of their networks lost their way out.

Types

type By

type By func(p1, p2 *Status) bool

func (By) Sort

func (by By) Sort(l []Status)

type CNIer

type CNIer interface {
	CNIConfigData() (interface{}, error)
}

type ClusterWider

type ClusterWider interface {
	IsClusterWide() bool
}

ClusterWider is implemented by the network drivers whose range is the same on every node, its addresses routable to whichever node holds them: an address drawn there is one of the cluster, which a failover object takes along to the node it moves to, rather than one of a node.

type Gatewayer

type Gatewayer interface {
	Gateway() (net.IP, error)
}

Gatewayer is implemented by the network drivers that name the router the addresses drawn from them reach beyond the segment through, nil when they name none.

type Grants

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

Grants is the addresses a node has let namespaces take of the networks, waiting for the cluster to report them.

A claim counts the addresses the namespace holds, read from what the objects of the cluster publish. An object publishes its address after it has taken it, so a claim answered from that reading alone misses every address taken since: two resources reserving at once are each answered as though the other had not. Counting the grants too closes that window, and holding them here is what makes the answer and the record one step rather than two.

A grant is held for the reservation it was granted for, which is a resource of an object, so that the cluster reporting an address for that resource is what releases it.

func NewGrants

func NewGrants(ttl time.Duration) *Grants

NewGrants returns a table forgetting a grant nothing reserved after ttl.

func (*Grants) ExpiresAt

func (t *Grants) ExpiresAt(now time.Time) time.Time

ExpiresAt is when a grant made now stops being counted.

func (*Grants) Fits

func (t *Grants) Fits(namespace, networkName, key string, limit, held int, seen map[string]bool, now time.Time) (bool, string)

Fits says whether a namespace may take one more address of a network for a reservation, and records the grant when it may.

held is how many addresses of the network the namespace is known to hold, and seen is the reservations those addresses are held for. A reservation already holding an address takes no new one: an object failing over to another node reserves the address it already has, and a claim asked twice for the same resource is the same address twice.

func (*Grants) Seed

func (t *Grants) Seed(namespace, networkName, key string, now time.Time)

Seed records a grant this node did not answer.

It is how a table lost is rebuilt. The grants of a node are in memory, so a node that has just started, or has just become the one answering claims, has none of them and answers from what the objects of the cluster have published alone, which is the reading the grants exist to complete.

What was granted and reserved is not lost, though: the node that reserved it publishes it before the others hear of it. What was granted and never reserved is lost, and expiring is what would have become of it anyway.

type HostDever

type HostDever interface {
	HostDev() (string, error)
}

HostDever is implemented by the network drivers whose addresses are configured on an interface of the node, rather than on a bridge the network sets up. It returns the interface of this node.

type IPAMer

type IPAMer interface {
	// AllocatableRange returns the addresses a node draws from in this
	// network. The gateway of that range is its first address plus one,
	// which is how both drivers derive the address of their bridge.
	AllocatableRange(nodename string) (*net.IPNet, error)
}

IPAMer is implemented by the network drivers whose addresses om allocates. A driver that does not implement it has om allocate nothing in it, which is what the lo network wants.

type Moder

type Moder interface {
	Modes() []string
}

Moder is implemented by the network drivers saying the modes an ip.netns may join their segment with, the first being the one of an ip.netns naming none. None when the network says nothing of them.

type Nameserverer

type Nameserverer interface {
	Nameservers() []string
}

Nameserverer is implemented by the networks saying the nameservers reachable from them, none when they say none.

type Netmasker

type Netmasker interface {
	Netmask() (int, error)
}

Netmasker is implemented by the network drivers whose addresses are configured with the prefix length of the segment they are drawn from, rather than the one of a bridge.

type Networker

type Networker interface {
	// SetDriver sets the driver name, which is obtained from the
	// "type" keyword in the network configuration.
	SetDriver(string)

	// SetName sets the network name. See Name().
	SetName(string)

	// SetImplicit sets isImplicit. See IsImplicit().
	SetImplicit(bool)

	// SetNetwork sets the network CIDR. Normally read from the
	// merged cluster configuration.
	SetNetwork(string)

	// SetNeedCommit can be called by drivers to signal network
	// configuration changes are staged and // need to be written
	// to file.
	SetNeedCommit(bool)

	// SetNoder stores the Noder
	SetNoder(Noder)

	// IsImplicit returns true if the network is a builtin with
	// no override section in the configuration.
	IsImplicit() bool

	// IsIP6 returns true if the network is a CIDR representation
	// of a IPv6 network.
	IsIP6() bool

	// Name returns the name of the network. Which is the part
	// after the dash in the configuration section name.
	Name() string

	// Kops returns the list of cluster config changes queued by the
	// driver upon Setup.
	Kops() keyop.L

	// Network returns the CIDR representation of the network.
	Network() string

	// IPNet returns the result of ParseCIDR() on the Network()
	// CIDR string, without the net.IP
	IPNet() (*net.IPNet, error)

	// NeedCommit return true if the network configuration cache
	// has staged changes. This can be used by Networks() users to
	// do one commit per action instead of one per network.
	NeedCommit() bool

	// Type return the driver name.
	Type() string

	FilterIPs(clusterip.L) clusterip.L

	AllowEmptyNetwork() bool

	// Config is a wrapper for the noder MergedConfig
	Config() *xconfig.T

	// Log returns a zerolog Logger configured to add the network
	// name to log entries.
	Log() *plog.Logger

	// Nodes is a wrapper for the noder Nodes, which returns the
	// list of cluster nodes to make the network available on.
	Nodes() ([]string, error)

	NodeSubnet(nodename string) (*net.IPNet, error)
	NodeSubnetIP(nodename string) (net.IP, error)
}

func Lookup

func Lookup(name string) (Networker, []string, error)

Lookup returns the network of a name, or nil when no network has it.

func Networks

func Networks(noder Noder, names ...string) []Networker

func NewFromNoder

func NewFromNoder(name string, noder Noder) Networker

func NewTyped

func NewTyped(name, networkType, networkNetwork string, noder Noder) Networker

type NodeAddresser

type NodeAddresser interface {
	NodeAddr(nodename string) (net.IP, error)
}

NodeAddresser is implemented by the network drivers giving each node a subnet of its own, whose first address is the node's: what reaches a node in the network, as the drbd traffic a disk.drbd sends there.

type Noder

type Noder interface {
	MergedConfig() *xconfig.T
	Log() *plog.Logger
	Nodes() ([]string, error)
}

type Peer

type Peer struct {
	// Nodename is the name of the peer node.
	Nodename string

	// Local is the address of this node the network reaches the peer
	// from, and Remote the address of the peer it reaches.
	Local  net.IP
	Remote net.IP

	// Subnet is the part of the network the peer hands out.
	Subnet string

	// Tunnel is the device of the tunnel carrying the network to the
	// peer, empty when the network is routed to it.
	Tunnel string
}

Peer is another node of a network, as this node reaches it.

type Peerer

type Peerer interface {
	Peers() ([]Peer, error)
}

Peerer is implemented by the network drivers reaching the other nodes themselves, by a route or a tunnel. It returns how this node reaches each of them.

type Pooler

type Pooler interface {
	Pools() ([]ipam.Pool, error)
}

Pooler is implemented by the network drivers handing out some of the addresses of their range only, which it returns.

type Route

type Route struct {
	Nodename string     `json:"node"`
	Dev      string     `json:"dev"`
	Dst      *net.IPNet `json:"dst"`
	Src      net.IP     `json:"ip"`
	Gateway  net.IP     `json:"gw"`
	Table    string     `json:"table"`
}

func (Route) Add

func (t Route) Add() error

func (Route) String

func (t Route) String() string

type Routes

type Routes []Route

func (Routes) Add

func (t Routes) Add() error

type Setuper

type Setuper interface {
	Setup() error
}

type Status

type Status struct {
	Name    string      `json:"name"`
	Type    string      `json:"type"`
	Network string      `json:"network"`
	IPs     clusterip.L `json:"ips"`
	Errors  []string    `json:"errors,omitempty"`
	Usage
}

func GetStatus

func GetStatus(t Networker, ips clusterip.L) Status

GetStatus returns the usage of the network. The usage counts are always set, rather than leaving its readers a nil count to dereference: a network whose range does not parse has a zero size and says why in its errors, and a network whose driver allows no range, as the loopback one, has a zero size and no error, as IsValid accepts it.

func NewStatus

func NewStatus() Status

type StatusList

type StatusList []Status

func NewStatusList

func NewStatusList() StatusList

func ShowNetworks

func ShowNetworks(noder Noder, ips clusterip.L) StatusList

func ShowNetworksByName

func ShowNetworksByName(noder Noder, name string, ips clusterip.L) StatusList

func (StatusList) Add

func (t StatusList) Add(p Networker, ips clusterip.L) StatusList

func (StatusList) Len

func (t StatusList) Len() int

func (StatusList) Less

func (t StatusList) Less(i, j int) bool

func (StatusList) Swap

func (t StatusList) Swap(i, j int)

type T

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

func (*T) AllowEmptyNetwork

func (t *T) AllowEmptyNetwork() bool

AllowEmptyNetwork returns true if the driver supports empty "network" keyword value. For one, the loopback driver does support that.

func (*T) Config

func (t *T) Config() *xconfig.T

func (*T) FilterIPs

func (t *T) FilterIPs(ips clusterip.L) clusterip.L

func (*T) GetBool

func (t *T) GetBool(s string) bool

func (*T) GetInt

func (t *T) GetInt(s string) int

func (*T) GetString

func (t *T) GetString(s string) string

func (*T) GetStringAs

func (t *T) GetStringAs(s, nodename string) string

func (*T) GetStrings

func (t *T) GetStrings(s string) []string

func (*T) GetSubnetAs

func (t *T) GetSubnetAs(nodename string) string

func (*T) IPNet

func (t *T) IPNet() (*net.IPNet, error)

func (*T) IPsPerNode

func (t *T) IPsPerNode() (int, error)

func (*T) IsIP6

func (t *T) IsIP6() bool

func (*T) IsImplicit

func (t *T) IsImplicit() bool

func (*T) Kops

func (t *T) Kops() keyop.L

func (*T) Log

func (t *T) Log() *plog.Logger

func (*T) Name

func (t *T) Name() string

func (*T) Nameservers

func (t *T) Nameservers() []string

Nameservers returns the nameservers reachable from the network, which the dns keyword lists.

func (*T) NeedCommit

func (t *T) NeedCommit() bool

func (*T) Network

func (t *T) Network() string

func (*T) NodeSubnet

func (t *T) NodeSubnet(nodename string) (*net.IPNet, error)

NodeSubnet returns the network subnet assigned to a cluster node, as a *net.IPNet. This subnet is usually found in the network configuration, as a subnet@<nodename> option. If not found there, allocate and write one.

The subnet allocator uses ips_per_node to compute a netmask (narrower than the network mask). The subnet first ip is computed using the position of the node in the cluster nodes list.

Example: With

cluster.nodes = n1 n2 n3
net1.network = 10.0.0.0/24
net1.ips_per_node = 64

=>

subnet@n1 = 10.0.0.0/26
subnet@n2 = 10.0.0.64/26
subnet@n3 = 10.0.0.128/26

func (*T) NodeSubnetIP

func (t *T) NodeSubnetIP(nodename string) (net.IP, error)

func (*T) Nodes

func (t *T) Nodes() ([]string, error)

func (*T) Set

func (t *T) Set(option, value string) error

func (*T) SetAllowEmptyNetwork

func (t *T) SetAllowEmptyNetwork(v bool)

func (*T) SetDriver

func (t *T) SetDriver(name string)

func (*T) SetImplicit

func (t *T) SetImplicit(v bool)

func (*T) SetName

func (t *T) SetName(name string)

func (*T) SetNeedCommit

func (t *T) SetNeedCommit(v bool)

func (*T) SetNetwork

func (t *T) SetNetwork(s string)

func (*T) SetNoder

func (t *T) SetNoder(noder Noder)

func (*T) Tables

func (t *T) Tables() []string

func (*T) Type

func (t *T) Type() string

type Usage

type Usage struct {
	Free *big.Int `json:"free"`
	Used *big.Int `json:"used"`
	Size *big.Int `json:"size"`
}

type VLANer

type VLANer interface {
	VLAN() (tag, mode string)
}

VLANer is implemented by the network drivers saying the VLAN of their segment, the tag and the mode of the port an ip.netns joining it with openvswitch adds, empty when they say none.

Jump to

Keyboard shortcuts

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