summaryrefslogtreecommitdiff
path: root/libpod/network/netavark/ipam_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/network/netavark/ipam_test.go')
-rw-r--r--libpod/network/netavark/ipam_test.go433
1 files changed, 433 insertions, 0 deletions
diff --git a/libpod/network/netavark/ipam_test.go b/libpod/network/netavark/ipam_test.go
new file mode 100644
index 000000000..4b3947501
--- /dev/null
+++ b/libpod/network/netavark/ipam_test.go
@@ -0,0 +1,433 @@
+package netavark
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "path/filepath"
+
+ "github.com/containers/podman/v3/libpod/network/types"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/sirupsen/logrus"
+)
+
+var _ = Describe("IPAM", func() {
+ var (
+ networkInterface *netavarkNetwork
+ networkConfDir string
+ logBuffer bytes.Buffer
+ )
+
+ BeforeEach(func() {
+ var err error
+ networkConfDir, err = ioutil.TempDir("", "podman_netavark_test")
+ if err != nil {
+ Fail("Failed to create tmpdir")
+
+ }
+ logBuffer = bytes.Buffer{}
+ logrus.SetOutput(&logBuffer)
+ })
+
+ JustBeforeEach(func() {
+ libpodNet, err := NewNetworkInterface(InitConfig{
+ NetworkConfigDir: networkConfDir,
+ IPAMDBPath: filepath.Join(networkConfDir, "ipam.db"),
+ LockFile: filepath.Join(networkConfDir, "netavark.lock"),
+ })
+ if err != nil {
+ Fail("Failed to create NewCNINetworkInterface")
+ }
+
+ networkInterface = libpodNet.(*netavarkNetwork)
+ // run network list to force a network load
+ networkInterface.NetworkList()
+ })
+
+ AfterEach(func() {
+ os.RemoveAll(networkConfDir)
+ })
+
+ It("simple ipam alloc", func() {
+ netName := types.DefaultNetworkName
+ for i := 2; i < 100; i++ {
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ err := networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.88.0.%d", i)).To4()))
+ }
+ })
+
+ It("ipam try to alloc same ip", func() {
+ netName := types.DefaultNetworkName
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ err := networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.88.0.2").To4()))
+
+ opts = &types.NetworkOptions{
+ ContainerID: "otherID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {StaticIPs: []net.IP{net.ParseIP("10.88.0.2")}},
+ },
+ }
+ err = networkInterface.allocIPs(opts)
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(Equal("IPAM error: requested ip address 10.88.0.2 is already allocated to container ID someContainerID"))
+ })
+
+ It("ipam try to alloc more ips as in range", func() {
+ s, _ := types.ParseCIDR("10.0.0.1/24")
+ network, err := networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s,
+ LeaseRange: &types.LeaseRange{
+ StartIP: net.ParseIP("10.0.0.10"),
+ EndIP: net.ParseIP("10.0.0.20"),
+ },
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName := network.Name
+
+ for i := 10; i < 21; i++ {
+ opts := &types.NetworkOptions{
+ ContainerID: fmt.Sprintf("someContainerID-%d", i),
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
+ }
+
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID-22",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ // now this should fail because all free ips are already assigned
+ err = networkInterface.allocIPs(opts)
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.10 - 10.0.0.20"))
+ })
+
+ It("ipam basic setup", func() {
+ netName := types.DefaultNetworkName
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ expectedIP := net.ParseIP("10.88.0.2").To4()
+
+ err := networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
+
+ // remove static ips from opts
+ netOpts := opts.Networks[netName]
+ netOpts.StaticIPs = nil
+ opts.Networks[netName] = netOpts
+
+ err = networkInterface.getAssignedIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(Equal("IPAM error: requested ip address 10.88.0.2 is already allocated to container ID someContainerID"))
+
+ // dealloc the ip
+ err = networkInterface.deallocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
+ })
+
+ It("ipam dual stack", func() {
+ s1, _ := types.ParseCIDR("10.0.0.0/26")
+ s2, _ := types.ParseCIDR("fd80::/24")
+ network, err := networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s1,
+ },
+ {
+ Subnet: s2,
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName := network.Name
+
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
+
+ // remove static ips from opts
+ netOpts := opts.Networks[netName]
+ netOpts.StaticIPs = nil
+ opts.Networks[netName] = netOpts
+
+ err = networkInterface.getAssignedIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
+
+ err = networkInterface.deallocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+
+ // try to alloc the same again
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
+ })
+
+ It("ipam with two networks", func() {
+ s, _ := types.ParseCIDR("10.0.0.0/24")
+ network, err := networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s,
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName1 := network.Name
+
+ s, _ = types.ParseCIDR("10.0.1.0/24")
+ network, err = networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s,
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName2 := network.Name
+
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName1: {},
+ netName2: {},
+ },
+ }
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName1))
+ Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks).To(HaveKey(netName2))
+ Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
+
+ // remove static ips from opts
+ netOpts := opts.Networks[netName1]
+ netOpts.StaticIPs = nil
+ opts.Networks[netName1] = netOpts
+ netOpts = opts.Networks[netName2]
+ netOpts.StaticIPs = nil
+ opts.Networks[netName2] = netOpts
+
+ err = networkInterface.getAssignedIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName1))
+ Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks).To(HaveKey(netName2))
+ Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
+
+ err = networkInterface.deallocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+
+ // try to alloc the same again
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName1))
+ Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
+ Expect(opts.Networks).To(HaveKey(netName2))
+ Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
+ })
+
+ It("ipam alloc more ips as in subnet", func() {
+ s, _ := types.ParseCIDR("10.0.0.0/26")
+ network, err := networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s,
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName := network.Name
+
+ for i := 2; i < 64; i++ {
+ opts := &types.NetworkOptions{
+ ContainerID: fmt.Sprintf("id-%d", i),
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+ err = networkInterface.allocIPs(opts)
+ if i < 63 {
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
+ } else {
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.1 - 10.0.0.62"))
+ }
+ }
+ })
+
+ It("ipam alloc -> dealloc -> alloc", func() {
+ s, _ := types.ParseCIDR("10.0.0.0/27")
+ network, err := networkInterface.NetworkCreate(types.Network{
+ Subnets: []types.Subnet{
+ {
+ Subnet: s,
+ },
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName := network.Name
+
+ for i := 2; i < 10; i++ {
+ opts := types.NetworkOptions{
+ ContainerID: fmt.Sprintf("id-%d", i),
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+ err = networkInterface.allocIPs(&opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
+
+ err = networkInterface.deallocIPs(&opts)
+ Expect(err).ToNot(HaveOccurred())
+ }
+
+ for i := 0; i < 30; i++ {
+ opts := types.NetworkOptions{
+ ContainerID: fmt.Sprintf("id-%d", i),
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+ err = networkInterface.allocIPs(&opts)
+ if i < 29 {
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
+ // The (i+8)%29+2 part looks cryptic but it is actually simple, we already have 8 ips allocated above
+ // so we expect the 8 available ip. We have 29 assignable ip addresses in this subnet because "i"+8 can
+ // be greater than 30 we have to modulo by 29 to go back to the beginning. Also the first free ip is
+ // network address + 2, so we have to add 2 to the result
+ Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", (i+8)%29+2)).To4()))
+ } else {
+ Expect(err).To(HaveOccurred())
+ Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.1 - 10.0.0.30"))
+ }
+ }
+ })
+
+ It("ipam with dhcp driver should not set ips", func() {
+ network, err := networkInterface.NetworkCreate(types.Network{
+ IPAMOptions: map[string]string{
+ "driver": types.DHCPIPAMDriver,
+ },
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ netName := network.Name
+
+ opts := &types.NetworkOptions{
+ ContainerID: "someContainerID",
+ Networks: map[string]types.PerNetworkOptions{
+ netName: {},
+ },
+ }
+
+ err = networkInterface.allocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(0))
+
+ err = networkInterface.getAssignedIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(opts.Networks).To(HaveKey(netName))
+ Expect(opts.Networks[netName].StaticIPs).To(HaveLen(0))
+
+ // dealloc the ip
+ err = networkInterface.deallocIPs(opts)
+ Expect(err).ToNot(HaveOccurred())
+ })
+
+})