Browse code

Fix issue for `--fixed-cidr` when bridge has multiple addresses

This fix tries to address the issue raised in 26341
where multiple addresses in a bridge may cause `--fixed-cidr`
to not have the correct addresses.

The issue is that `netutils.ElectInterfaceAddresses(bridgeName)`
only returns the first IPv4 address.

This fix (together with the PR created in libnetwork )
changes `ElectInterfaceAddresses()` and `addresses()`
so that all IPv4 addresses are returned. This will allow the
possibility of selectively choose the address needed.

In `daemon_unix.go`, bridge address is chosen by comparing with
the `--fixed-cidr` first, thus resolve the issue in 26341.

This fix is tested manually, as is described in 26341:
```
brctl addbr cbr0
ip addr add 10.111.111.111/20 dev cbr0 label cbr0:main
ip addr add 10.222.222.222/12 dev cbr0 label cbr0:docker
ip link set cbr0 up
docker daemon --bridge=cbr0 --iptables=false --ip-masq=false --fixed-cidr=10.222.222.222/24
docker run --rm busybox ip route get 8.8.8.8 | grep -Po 'src.*'
src 10.222.222.0
```

This fix fixes 26341.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

Yong Tang authored on 2016/09/17 14:46:20
Showing 1 changed files
... ...
@@ -41,6 +41,7 @@ import (
41 41
 	rsystem "github.com/opencontainers/runc/libcontainer/system"
42 42
 	"github.com/opencontainers/runc/libcontainer/user"
43 43
 	specs "github.com/opencontainers/runtime-spec/specs-go"
44
+	"github.com/pkg/errors"
44 45
 	"github.com/vishvananda/netlink"
45 46
 )
46 47
 
... ...
@@ -710,13 +711,30 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
710 710
 
711 711
 	ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
712 712
 
713
-	nw, nw6List, err := netutils.ElectInterfaceAddresses(bridgeName)
714
-	if err == nil {
715
-		ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String()
716
-		hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask)
717
-		if hip.IsGlobalUnicast() {
718
-			ipamV4Conf.Gateway = nw.IP.String()
713
+	nwList, nw6List, err := netutils.ElectInterfaceAddresses(bridgeName)
714
+	if err != nil {
715
+		return errors.Wrap(err, "list bridge addresses failed")
716
+	}
717
+
718
+	nw := nwList[0]
719
+	if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" {
720
+		_, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR)
721
+		if err != nil {
722
+			return errors.Wrap(err, "parse CIDR failed")
719 723
 		}
724
+		// Iterate through in case there are multiple addresses for the bridge
725
+		for _, entry := range nwList {
726
+			if fCIDR.Contains(entry.IP) {
727
+				nw = entry
728
+				break
729
+			}
730
+		}
731
+	}
732
+
733
+	ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String()
734
+	hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask)
735
+	if hip.IsGlobalUnicast() {
736
+		ipamV4Conf.Gateway = nw.IP.String()
720 737
 	}
721 738
 
722 739
 	if config.bridgeConfig.IP != "" {