ipam

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: 14 Imported by: 0

Documentation

Overview

Package ipam allocates the addresses of an om network on one node.

The allocation is node local, which is what makes it safe without a lock held across the cluster. A routed_bridge network gives every node a subnet of its own, so two nodes never draw from the same addresses. A bridge network gives every node the whole subnet, but its addresses are node local and not routable, so the same address on two nodes never meets.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DropPeerRecords

func DropPeerRecords(dir string, keep func(PeerRecord) bool) (int, error)

DropPeerRecords removes the records keep says no to, and returns how many.

func Gateway

func Gateway(rng *net.IPNet) net.IP

Gateway returns the address the bridge of a range answers for, which is the first address of the range plus one.

Both network drivers derive the address of their bridge that way, from the range they hand out: the bridge driver from the whole subnet, the routed_bridge driver from the subnet of the node. So the allocator has one rule to keep and no second place for it to drift from.

func Key

func Key(p naming.Path, rid string) string

Key returns the reservation key of an ip resource.

An address belongs to a resource, not to an object: an instance holds as many ip resources as it needs, several of them in one network, and each has an address of its own. Keying on the object alone would have ip#0 and ip#1 draw the same one.

func PathOfKey

func PathOfKey(key string) (naming.Path, bool)

PathOfKey returns the object a key names, and whether it names one.

func PeerDir

func PeerDir(name string) string

PeerDir is where a node records the addresses the other nodes reported holding in a network every node draws from, one file per address naming the node and the reservation key.

The draws read the stores of the nodes alive, and the status the cluster keeps of the others, which it drops when it stops hearing from them, and forgets when the node restarts. What a node down holds stays on its interfaces all the same: the records are what this node remembers of it for as long as it is not told otherwise.

func PoolsString

func PoolsString(pools []Pool) string

PoolsString returns the pools as a list is written.

func SetPeerRecords

func SetPeerRecords(dir, node, path string, addrs map[string]string) (int, int, error)

SetPeerRecords makes the records of an object on a node the addresses given, by address, the key each is held for: the ones it no longer reports are removed, and the others written. It returns how many it wrote and removed.

func StoreDir

func StoreDir(name string) string

StoreDir returns where the reservations of a network are recorded.

One place, so the allocator a resource builds and the adoption a network setup runs record in the same directory.

Types

type PeerRecord

type PeerRecord struct {
	IP   net.IP
	Node string
	Key  string
}

PeerRecord is an address another node reported one of its instances holds in a network every node draws from.

func ReadPeerRecords

func ReadPeerRecords(dir string) ([]PeerRecord, error)

ReadPeerRecords returns the records of a peer directory.

type Pool

type Pool struct {
	First net.IP
	Last  net.IP
}

Pool is a span of addresses om hands out, from First to Last included.

func ParsePool

func ParsePool(s string) (Pool, error)

ParsePool reads a pool written as a subnet, as 192.168.10.128/26, or as its first and last addresses, as 192.168.10.100-192.168.10.199, the form nftables and ipset read.

func ParsePools

func ParsePools(l []string) ([]Pool, error)

ParsePools reads the pools of a list, and refuses pools that overlap: an address handed out from two pools would be drawn twice as often as the others, and two pools written to overlap are a mistake.

func PoolOf

func PoolOf(ipnet *net.IPNet) Pool

PoolOf returns the pool of all the addresses of a subnet.

func (Pool) Contains

func (p Pool) Contains(ip net.IP) bool

Contains says ip is one of the addresses of the pool.

func (Pool) In

func (p Pool) In(ipnet *net.IPNet) bool

In says every address of the pool is one of the subnet.

func (Pool) Overlaps

func (p Pool) Overlaps(o Pool) bool

Overlaps says the two pools have an address in common.

func (Pool) Size

func (p Pool) Size() *big.Int

Size returns the number of addresses of the pool.

func (Pool) String

func (p Pool) String() string

String returns the pool as it is written: a subnet when it is one, else its first and last addresses.

type Reservation

type Reservation struct {
	IP  net.IP
	Key string
}

Reservation is an address already held by a resource, which an adoption records so the resource keeps it.

type T

type T struct {
	// Name is the network the addresses are drawn from.
	Name string

	// Range is the subnet of the addresses this node draws from: its
	// first address, and the last of an ipv4 one, are never handed out.
	Range *net.IPNet

	// Pools are the addresses of Range this node draws from, all of
	// them when there is none.
	Pools []Pool

	// Gateway is not allocated: it is the address of the bridge.
	Gateway net.IP

	// Dir is where the reservations are recorded, one file per address.
	Dir string

	// PeerDirs are the reservation stores of the allocators sharing this
	// range, read and never written. While ip.cni is still served by the
	// host-local plugin, its store is one of these: an address it handed
	// out has no reservation here, and would be handed out twice.
	PeerDirs []string

	// ClusterDir holds the addresses the other nodes reported holding
	// in a range every node draws from, which this node remembers for
	// as long as it is not told otherwise: see PeerDir.
	ClusterDir string

	// InUse reports the addresses the cluster says are taken. The daemon
	// replicates the resource status of every instance, so this sees the
	// addresses of objects whose reservation file this node cannot read.
	//
	// Neither network driver needs it: a routed_bridge gives this node a
	// range no other node draws from, and the addresses of a bridge are
	// node local and not routable. It is here for a network type that is
	// neither.
	InUse func() ([]net.IP, error)

	// ClusterWide says every node draws from the pools, as the nodes of a
	// lan network do: an address is the cluster's, not this node's, so
	// a resource takes the address it holds on another node, and the
	// addresses the other resources hold anywhere are taken.
	ClusterWide bool
}

T allocates in one network, on one node.

func (*T) Adopt

func (t *T) Adopt(reservations []Reservation) (int, error)

Adopt records the addresses resources already hold, so the allocator hands out the addresses that are free rather than the addresses that have no reservation yet.

It is how the allocation of a network moves from an allocator that was keeping its own record. The record of the host-local plugin cannot serve: it names the holder of an address by the pid of a network namespace, which says nothing about which resource that is. The cluster status can, since it carries the object and the rid alongside the address.

An address already reserved is left alone, whoever holds it, so an adoption run twice changes nothing and an adoption run late does not take an address from the resource that drew it. The count returned is of the addresses this call recorded, which is how a setup says whether it had anything to adopt.

func (*T) Allocate

func (t *T) Allocate(key string) (net.IP, error)

Allocate returns the address reserved for key, reserving it when it has none.

The same key draws the same address as long as it stays free, so an object keeps its address across restarts and its name keeps meaning what it meant. The reservation is a file created exclusively, which is the whole of the locking: one node draws from this range, so there is no other writer.

func (*T) Allocated

func (t *T) Allocated(key string) (net.IP, error)

Allocated returns the address key holds, or nil when it holds none.

func (*T) Contains

func (t *T) Contains(ip net.IP) bool

Contains says ip is one of the addresses this node draws from, whether it may be handed out or not.

func (*T) DrainPeers

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

DrainPeers removes, from the stores of the allocators sharing this range, the record of every address this one now holds.

A store is read to know what an allocator om is replacing handed out. Once om reserves an address, that record says nothing om does not know, and leaving it makes the address unusable for as long as the file lasts: the allocator that wrote it does not run any more, so nothing else will ever remove it.

Only the addresses om holds are removed. An address in the store that om accounts for in no way is left, and stays excluded, because the reason it is there may be a resource whose status this node has not read.

func (*T) DropReplaced

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

DropReplaced releases the addresses held out of the ranges by the keys holding one in them, as a replacement drawn by a key whose stale address could not be dropped then, or adopted at the address its resource has configured, leaves them. It returns the number of addresses released.

func (*T) DropStale

func (t *T) DropStale(key string) error

DropStale releases the addresses key holds out of the ranges, once it holds one in them: the one the ranges hold replaced them.

func (*T) Free

func (t *T) Free(key string) error

Free releases the addresses key holds, and does nothing when it holds none.

Only the holder frees an address: the file names who took it, and a reservation another key made is left alone.

func (*T) Keep

func (t *T) Keep(ip net.IP, key string) error

Keep reserves ip for key, in the ranges or out of them, and releases the other addresses key holds: ip is the address the resource has configured, and could not give up for the one it drew. An address another key holds is refused.

func (*T) PoolsString

func (t *T) PoolsString() string

PoolsString returns the addresses this node draws from, as they are written.

func (*T) Reap

func (t *T) Reap(exists func(key string) bool) (int, error)

Reap releases the reservations held for keys that no longer exist.

A resource releases its address when it stops, and a start that fails rolls the allocation back, so a reservation outliving its holder takes a crash at the wrong moment. It outlives it for good though: the key names an object that is gone, so nothing will ever come to release it, and the address is lost until someone reads the store and works out why.

A key is kept unless it is known not to exist. Anything else would race a resource that has just reserved an address and not yet finished starting.

func (*T) Reservations

func (t *T) Reservations() ([]Reservation, error)

Reservations returns the addresses this allocator holds, with the key each is held for.

It reads the store rather than the cluster status, so an address shows up the moment it is reserved, before the object holding it has published a status saying so.

Jump to

Keyboard shortcuts

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