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)
| ... | ... |
@@ -150,6 +150,21 @@ func InitDriver(job *engine.Job) engine.Status {
|
| 150 | 150 |
} |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 |
+ // a bridge might exist but not have any IPv6 addr associated with it yet |
|
| 154 |
+ // (for example, an existing Docker installation that has only been used |
|
| 155 |
+ // with IPv4 and docker0 already is set up) In that case, we can perform |
|
| 156 |
+ // the bridge init for IPv6 here, else we will error out below if --ipv6=true |
|
| 157 |
+ if len(addrsv6) == 0 && enableIPv6 {
|
|
| 158 |
+ if err := setupIPv6Bridge(bridgeIPv6); err != nil {
|
|
| 159 |
+ return job.Error(err) |
|
| 160 |
+ } |
|
| 161 |
+ // recheck addresses now that IPv6 is setup on the bridge |
|
| 162 |
+ addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface) |
|
| 163 |
+ if err != nil {
|
|
| 164 |
+ return job.Error(err) |
|
| 165 |
+ } |
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 153 | 168 |
// TODO: Check if route to fixedCIDRv6 is set |
| 154 | 169 |
} |
| 155 | 170 |
|
| ... | ... |
@@ -401,21 +416,9 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error |
| 401 | 401 |
} |
| 402 | 402 |
|
| 403 | 403 |
if enableIPv6 {
|
| 404 |
- // Enable IPv6 on the bridge |
|
| 405 |
- procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6" |
|
| 406 |
- if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
|
|
| 407 |
- return fmt.Errorf("unable to enable IPv6 addresses on bridge: %s\n", err)
|
|
| 408 |
- } |
|
| 409 |
- |
|
| 410 |
- ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6) |
|
| 411 |
- if err != nil {
|
|
| 412 |
- log.Errorf("BridgeIPv6 parsing failed")
|
|
| 404 |
+ if err := setupIPv6Bridge(bridgeIPv6); err != nil {
|
|
| 413 | 405 |
return err |
| 414 | 406 |
} |
| 415 |
- |
|
| 416 |
- if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
|
|
| 417 |
- return fmt.Errorf("Unable to add private IPv6 network: %s", err)
|
|
| 418 |
- } |
|
| 419 | 407 |
} |
| 420 | 408 |
|
| 421 | 409 |
if err := netlink.NetworkLinkUp(iface); err != nil {
|
| ... | ... |
@@ -424,6 +427,30 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error |
| 424 | 424 |
return nil |
| 425 | 425 |
} |
| 426 | 426 |
|
| 427 |
+func setupIPv6Bridge(bridgeIPv6 string) error {
|
|
| 428 |
+ |
|
| 429 |
+ iface, err := net.InterfaceByName(bridgeIface) |
|
| 430 |
+ if err != nil {
|
|
| 431 |
+ return err |
|
| 432 |
+ } |
|
| 433 |
+ // Enable IPv6 on the bridge |
|
| 434 |
+ procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6" |
|
| 435 |
+ if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
|
|
| 436 |
+ return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
|
|
| 437 |
+ } |
|
| 438 |
+ |
|
| 439 |
+ ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6) |
|
| 440 |
+ if err != nil {
|
|
| 441 |
+ return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
|
|
| 442 |
+ } |
|
| 443 |
+ |
|
| 444 |
+ if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
|
|
| 445 |
+ return fmt.Errorf("Unable to add private IPv6 network: %v", err)
|
|
| 446 |
+ } |
|
| 447 |
+ |
|
| 448 |
+ return nil |
|
| 449 |
+} |
|
| 450 |
+ |
|
| 427 | 451 |
func createBridgeIface(name string) error {
|
| 428 | 452 |
kv, err := kernel.GetKernelVersion() |
| 429 | 453 |
// only set the bridge's mac address if the kernel version is > 3.3 |
| ... | ... |
@@ -74,7 +74,7 @@ func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
|
| 74 | 74 |
return netIP.Mask(network.Mask), net.IP(lastIP) |
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 |
-// Return the IPv4 address of a network interface |
|
| 77 |
+// Return the first IPv4 address and slice of IPv6 addresses for the specified network interface |
|
| 78 | 78 |
func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
|
| 79 | 79 |
iface, err := net.InterfaceByName(name) |
| 80 | 80 |
if err != nil {
|