Skip to content

Commit

Permalink
dual-stack network: fix duplicated subnet assignment
Browse files Browse the repository at this point in the history
Make sure podman network create reads all subnets from existing cni configs
and not only the first one.

Fixes containers#11032

Signed-off-by: Paul Holzinger <[email protected]>
  • Loading branch information
Luap99 committed Jul 26, 2021
1 parent 21e1c31 commit 8d5d5fa
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
6 changes: 4 additions & 2 deletions libpod/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,10 @@ func allocatorToIPNets(networks []*allocator.Net) []*net.IPNet {
if len(network.IPAM.Ranges) > 0 {
// this is the new IPAM range style
// append each subnet from ipam the rangeset
for _, r := range network.IPAM.Ranges[0] {
nets = append(nets, newIPNetFromSubnet(r.Subnet))
for _, allocatorRange := range network.IPAM.Ranges {
for _, r := range allocatorRange {
nets = append(nets, newIPNetFromSubnet(r.Subnet))
}
}
} else {
// looks like the old, deprecated style
Expand Down
49 changes: 49 additions & 0 deletions test/e2e/network_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,59 @@ var _ = Describe("Podman network create", func() {
Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0"))
Expect(bridgePlugin.IPAM.Routes[1].Dest).To(Equal("0.0.0.0/0"))

Expect(bridgePlugin.IPAM.Ranges).To(HaveLen(2))
Expect(bridgePlugin.IPAM.Ranges[0]).To(HaveLen(1))
Expect(bridgePlugin.IPAM.Ranges[0][0].Subnet).ToNot(BeEmpty())
Expect(bridgePlugin.IPAM.Ranges[1]).To(HaveLen(1))
Expect(bridgePlugin.IPAM.Ranges[1][0].Subnet).ToNot(BeEmpty())

_, subnet11, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[0][0].Subnet)
Expect(err).To(BeNil())
_, subnet12, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[1][0].Subnet)
Expect(err).To(BeNil())

// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(bridgePlugin.BrName)

// create a second network to check the auto assigned ipv4 subnet does not overlap
// https://github.com/containers/podman/issues/11032
netName2 := "dual-" + stringid.GenerateNonCryptoID()
nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:6:3:2:1::/64", "--ipv6", netName2})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeCNINetwork(netName2)
Expect(nc).Should(Exit(0))

// Inspect the network configuration
inspect = podmanTest.Podman([]string{"network", "inspect", netName2})
inspect.WaitWithDefaultTimeout()

// JSON the network configuration into something usable
err = json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).To(BeNil())
result = results[0]
Expect(result["name"]).To(Equal(netName2))

// JSON the bridge info
bridgePlugin, err = genericPluginsToBridge(result["plugins"], "bridge")
Expect(err).To(BeNil())
Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0"))
Expect(bridgePlugin.IPAM.Routes[1].Dest).To(Equal("0.0.0.0/0"))
Expect(bridgePlugin.IPAM.Ranges).To(HaveLen(2))
Expect(bridgePlugin.IPAM.Ranges[0]).To(HaveLen(1))
Expect(bridgePlugin.IPAM.Ranges[0][0].Subnet).ToNot(BeEmpty())
Expect(bridgePlugin.IPAM.Ranges[1]).To(HaveLen(1))
Expect(bridgePlugin.IPAM.Ranges[1][0].Subnet).ToNot(BeEmpty())

_, subnet21, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[0][0].Subnet)
Expect(err).To(BeNil())
_, subnet22, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[1][0].Subnet)
Expect(err).To(BeNil())

// check that the subnets do not overlap
Expect(subnet11.Contains(subnet21.IP)).To(BeFalse())
Expect(subnet12.Contains(subnet22.IP)).To(BeFalse())

try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"})
try.WaitWithDefaultTimeout()

Expand Down

0 comments on commit 8d5d5fa

Please sign in to comment.