Browse code

Restore IPv6 from MAC on default bridge network

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2015/11/11 14:14:05
Showing 2 changed files
... ...
@@ -455,12 +455,25 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
455 455
 		ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String()
456 456
 	}
457 457
 
458
-	var ipamV6Conf *libnetwork.IpamConf
458
+	var (
459
+		ipamV6Conf     *libnetwork.IpamConf
460
+		deferIPv6Alloc bool
461
+	)
459 462
 	if config.Bridge.FixedCIDRv6 != "" {
460 463
 		_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
461 464
 		if err != nil {
462 465
 			return err
463 466
 		}
467
+
468
+		// In case user has specified the daemon flag --fixed-cidr-v6 and the passed network has
469
+		// at least 48 host bits, we need to guarantee the current behavior where the containers'
470
+		// IPv6 addresses will be constructed based on the containers' interface MAC address.
471
+		// We do so by telling libnetwork to defer the IPv6 address allocation for the endpoints
472
+		// on this network until after the driver has created the endpoint and returned the
473
+		// constructed address. Libnetwork will then reserve this address with the ipam driver.
474
+		ones, _ := fCIDRv6.Mask.Size()
475
+		deferIPv6Alloc = ones <= 80
476
+
464 477
 		if ipamV6Conf == nil {
465 478
 			ipamV6Conf = &libnetwork.IpamConf{}
466 479
 		}
... ...
@@ -485,7 +498,8 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
485 485
 			netlabel.GenericData: netOption,
486 486
 			netlabel.EnableIPv6:  config.Bridge.EnableIPv6,
487 487
 		}),
488
-		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf))
488
+		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf),
489
+		libnetwork.NetworkOptionDeferIPv6Alloc(deferIPv6Alloc))
489 490
 	if err != nil {
490 491
 		return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
491 492
 	}
... ...
@@ -377,6 +377,29 @@ func (s *DockerSuite) TestDaemonIPv6FixedCIDR(c *check.C) {
377 377
 	}
378 378
 }
379 379
 
380
+// TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR
381
+// the running containers are given a an IPv6 address derived from the MAC address and the ipv6 fixed CIDR
382
+func (s *DockerSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) {
383
+	err := setupV6()
384
+	c.Assert(err, checker.IsNil)
385
+
386
+	d := NewDaemon(c)
387
+
388
+	err = d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'")
389
+	c.Assert(err, checker.IsNil)
390
+	defer d.Stop()
391
+
392
+	out, err := d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox")
393
+	c.Assert(err, checker.IsNil)
394
+
395
+	out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test")
396
+	c.Assert(err, checker.IsNil)
397
+	c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff")
398
+
399
+	err = teardownV6()
400
+	c.Assert(err, checker.IsNil)
401
+}
402
+
380 403
 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) {
381 404
 	c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level"))
382 405
 }