Fix bridge initialization for IPv6 if IPv4-only docker0 exists

This fixes the daemon's failure to start when setting --ipv6=true for
the first time without deleting `docker0` bridge from a prior use with
only IPv4 addressing.

The addition of the IPv6 bridge address is factored out into a separate
initialization routine which is called even if the bridge exists but no
IPv6 addresses are found.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com> (github: estesp)
This commit is contained in:
Phil Estes 2015-01-27 22:03:27 -05:00
parent 3ac5596fe0
commit 0c8d17b5c1
2 changed files with 41 additions and 14 deletions

View File

@ -150,6 +150,21 @@ func InitDriver(job *engine.Job) engine.Status {
}
}
// a bridge might exist but not have any IPv6 addr associated with it yet
// (for example, an existing Docker installation that has only been used
// with IPv4 and docker0 already is set up) In that case, we can perform
// the bridge init for IPv6 here, else we will error out below if --ipv6=true
if len(addrsv6) == 0 && enableIPv6 {
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
return job.Error(err)
}
// recheck addresses now that IPv6 is setup on the bridge
addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
if err != nil {
return job.Error(err)
}
}
// TODO: Check if route to fixedCIDRv6 is set
}
@ -401,21 +416,9 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error
}
if enableIPv6 {
// Enable IPv6 on the bridge
procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
return fmt.Errorf("unable to enable IPv6 addresses on bridge: %s\n", err)
}
ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
if err != nil {
log.Errorf("BridgeIPv6 parsing failed")
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
return err
}
if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
return fmt.Errorf("Unable to add private IPv6 network: %s", err)
}
}
if err := netlink.NetworkLinkUp(iface); err != nil {
@ -424,6 +427,30 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error
return nil
}
func setupIPv6Bridge(bridgeIPv6 string) error {
iface, err := net.InterfaceByName(bridgeIface)
if err != nil {
return err
}
// Enable IPv6 on the bridge
procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
}
ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
if err != nil {
return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
}
if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
return fmt.Errorf("Unable to add private IPv6 network: %v", err)
}
return nil
}
func createBridgeIface(name string) error {
kv, err := kernel.GetKernelVersion()
// only set the bridge's mac address if the kernel version is > 3.3

View File

@ -74,7 +74,7 @@ func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
return netIP.Mask(network.Mask), net.IP(lastIP)
}
// Return the IPv4 address of a network interface
// Return the first IPv4 address and slice of IPv6 addresses for the specified network interface
func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
iface, err := net.InterfaceByName(name)
if err != nil {