diff options
author | baude <bbaude@redhat.com> | 2019-08-08 06:01:00 -0500 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-09-09 09:32:43 -0500 |
commit | ee432cf2792c5dbe81953007f1fd5c87beb3ebd5 (patch) | |
tree | dc0646e4b2faeadf9cca58bf80f1e90d98c50165 /pkg/network/subnet.go | |
parent | 30cbb0091515a7f802f0f3f3ee486be6ff98f645 (diff) | |
download | podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.tar.gz podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.tar.bz2 podman-ee432cf2792c5dbe81953007f1fd5c87beb3ebd5.zip |
podman network create
initial implementation of network create. we only support bridging
networks with this first pass.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'pkg/network/subnet.go')
-rw-r--r-- | pkg/network/subnet.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/pkg/network/subnet.go b/pkg/network/subnet.go new file mode 100644 index 000000000..82ab9a8c8 --- /dev/null +++ b/pkg/network/subnet.go @@ -0,0 +1,78 @@ +package network + +/* + The code in this was kindly contributed by Dan Williams(dcbw@redhat.com). Many thanks + for his contributions. +*/ + +import ( + "fmt" + "net" +) + +func incByte(subnet *net.IPNet, idx int, shift uint) error { + if idx < 0 { + return fmt.Errorf("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, fmt.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 +} + +// LastIPInSubnet gets the last IP in a subnet +func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer + // re-parse to ensure clean network address + _, cidr, err := net.ParseCIDR(addr.String()) + if err != nil { + return nil, err + } + + ones, bits := cidr.Mask.Size() + if ones == bits { + return FirstIPInSubnet(cidr) + } + hostStart := ones / 8 + // Handle the first host byte + cidr.IP[hostStart] |= (0xff & cidr.Mask[hostStart]) + // Fill the rest with ones + for i := hostStart; i < len(cidr.IP); i++ { + cidr.IP[i] = 0xff + } + return cidr.IP, nil +} + +// FirstIPInSubnet gets the first IP in a subnet +func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer + // re-parse to ensure clean network address + _, cidr, err := net.ParseCIDR(addr.String()) + if err != nil { + return nil, err + } + cidr.IP[len(cidr.IP)-1]++ + return cidr.IP, nil +} |