Files
podman/libpod/network/internal/util/ip.go
Paul Holzinger 4febe55769 netavark IPAM assignment
Add a new boltdb to handle IPAM assignment.

The db structure is the following:
Each network has their own bucket with the network name as bucket key.
Inside the network bucket there is an ID bucket which maps the container ID (key)
to a json array of ip addresses (value).
The network bucket also has a bucket for each subnet, the subnet is used as key.
Inside the subnet bucket an ip is used as key and the container ID as value.

The db should be stored on a tmpfs to ensure we always have a clean
state after a reboot.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2021-11-11 16:25:19 +01:00

71 lines
1.5 KiB
Go

package util
import (
"crypto/rand"
"net"
"github.com/pkg/errors"
)
func incByte(subnet *net.IPNet, idx int, shift uint) error {
if idx < 0 {
return errors.New("no more subnets left")
}
if subnet.IP[idx] == 255 {
subnet.IP[idx] = 0
return incByte(subnet, idx-1, 0)
}
subnet.IP[idx] += 1 << shift
return nil
}
// NextSubnet returns subnet incremented by 1
func NextSubnet(subnet *net.IPNet) (*net.IPNet, error) {
newSubnet := &net.IPNet{
IP: subnet.IP,
Mask: subnet.Mask,
}
ones, bits := newSubnet.Mask.Size()
if ones == 0 {
return nil, errors.Errorf("%s has only one subnet", subnet.String())
}
zeroes := uint(bits - ones)
shift := zeroes % 8
idx := ones/8 - 1
if idx < 0 {
idx = 0
}
if err := incByte(newSubnet, idx, shift); err != nil {
return nil, err
}
return newSubnet, nil
}
func NetworkIntersectsWithNetworks(n *net.IPNet, networklist []*net.IPNet) bool {
for _, nw := range networklist {
if networkIntersect(n, nw) {
return true
}
}
return false
}
func networkIntersect(n1, n2 *net.IPNet) bool {
return n2.Contains(n1.IP) || n1.Contains(n2.IP)
}
// getRandomIPv6Subnet returns a random internal ipv6 subnet as described in RFC3879.
func getRandomIPv6Subnet() (net.IPNet, error) {
ip := make(net.IP, 8, net.IPv6len)
// read 8 random bytes
_, err := rand.Read(ip)
if err != nil {
return net.IPNet{}, nil
}
// first byte must be FD as per RFC3879
ip[0] = 0xfd
// add 8 zero bytes
ip = append(ip, make([]byte, 8)...)
return net.IPNet{IP: ip, Mask: net.CIDRMask(64, 128)}, nil
}