network

package
v3.0.0-rc41 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: Apache-2.0 Imports: 38 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.

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 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 IncIP

func IncIP(ip net.IP)

func IncIPN

func IncIPN(ip net.IP, n int)

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 Setup

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

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 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 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 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 Noder

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

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

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) 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"`
}

Jump to

Keyboard shortcuts

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