mirror of
https://github.com/containers/podman.git
synced 2025-06-19 16:33:24 +08:00
podman support for IPv6 networks
podman containers using IPv6 were missing the default route, breaking deployments trying to use them. The problem is that the default route was hardcoded to IPv4, this takes into consideration the podman subnet IP family to generate the corresponding default route. Signed-off-by: Antonio Ojea <aojea@redhat.com>
This commit is contained in:
@ -191,7 +191,7 @@ func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreate
|
||||
var plugins []network.CNIPlugins
|
||||
var routes []network.IPAMRoute
|
||||
|
||||
defaultRoute, err := network.NewIPAMDefaultRoute()
|
||||
defaultRoute, err := network.NewIPAMDefaultRoute(network.IsIPv6(subnet.IP))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -12,3 +12,8 @@ func CalcGatewayIP(ipn *net.IPNet) net.IP {
|
||||
nid := ipn.IP.Mask(ipn.Mask)
|
||||
return ip.NextIP(nid)
|
||||
}
|
||||
|
||||
// IsIPv6 returns if netIP is IPv6.
|
||||
func IsIPv6(netIP net.IP) bool {
|
||||
return netIP != nil && netIP.To4() == nil
|
||||
}
|
||||
|
@ -6,6 +6,11 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultIPv4Route = "0.0.0.0/0"
|
||||
defaultIPv6Route = "::/0"
|
||||
)
|
||||
|
||||
// NcList describes a generic map
|
||||
type NcList map[string]interface{}
|
||||
|
||||
@ -86,9 +91,13 @@ func NewIPAMRoute(r *net.IPNet) IPAMRoute { //nolint:interfacer
|
||||
}
|
||||
|
||||
// NewIPAMDefaultRoute creates a new IPAMDefault route of
|
||||
// 0.0.0.0/0
|
||||
func NewIPAMDefaultRoute() (IPAMRoute, error) {
|
||||
_, n, err := net.ParseCIDR("0.0.0.0/0")
|
||||
// 0.0.0.0/0 for IPv4 or ::/0 for IPv6
|
||||
func NewIPAMDefaultRoute(isIPv6 bool) (IPAMRoute, error) {
|
||||
route := defaultIPv4Route
|
||||
if isIPv6 {
|
||||
route = defaultIPv6Route
|
||||
}
|
||||
_, n, err := net.ParseCIDR(route)
|
||||
if err != nil {
|
||||
return IPAMRoute{}, err
|
||||
}
|
||||
|
38
pkg/network/netconflist_test.go
Normal file
38
pkg/network/netconflist_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewIPAMDefaultRoute(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
isIPv6 bool
|
||||
want IPAMRoute
|
||||
}{
|
||||
{
|
||||
name: "IPv4 default route",
|
||||
isIPv6: false,
|
||||
want: IPAMRoute{defaultIPv4Route},
|
||||
},
|
||||
{
|
||||
name: "IPv6 default route",
|
||||
isIPv6: true,
|
||||
want: IPAMRoute{defaultIPv6Route},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := NewIPAMDefaultRoute(tt.isIPv6)
|
||||
if err != nil {
|
||||
t.Errorf("no errorr expected: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("NewIPAMDefaultRoute() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -178,6 +178,47 @@ var _ = Describe("Podman network create", func() {
|
||||
Expect(subnet.Contains(containerIP)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman network create with name and IPv6 subnet", func() {
|
||||
SkipIfRemote()
|
||||
var (
|
||||
results []network.NcList
|
||||
)
|
||||
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", "newIPv6network"})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
Expect(nc.ExitCode()).To(BeZero())
|
||||
|
||||
defer podmanTest.removeCNINetwork("newIPv6network")
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", "newIPv6network"})
|
||||
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("newIPv6network"))
|
||||
|
||||
// JSON the bridge info
|
||||
bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0"))
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(bridgePlugin.BrName)
|
||||
|
||||
try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newIPv6network", ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"})
|
||||
try.WaitWithDefaultTimeout()
|
||||
|
||||
_, subnet, err := net.ParseCIDR("fd00:1:2:3:4::/64")
|
||||
Expect(err).To(BeNil())
|
||||
containerIP, _, err := net.ParseCIDR(try.OutputToString())
|
||||
Expect(err).To(BeNil())
|
||||
// Ensure that the IP the container got is within the subnet the user asked for
|
||||
Expect(subnet.Contains(containerIP)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman network create with invalid subnet", func() {
|
||||
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", "fail"})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
|
Reference in New Issue
Block a user