Browse code

Fix selection of subnet from user-managed default bridge

When a user-managed bridge is used instead of docker0 (--bridge), with
a fixed-cidr - the bridge should have an IP address/subnet that
encompasses fixed-cidr ... the bridge address's subnet then defines
the network's subnet, and fixed-cidr defines the allocatable range
within that.

But, selection of the correct subnet/address from the bridge depended
on the address being within fixed-cidr (within the allocatable range).

This change removes that assumption. So, a bridge address with a
subnet that includes fixed-cidr is selected.

Signed-off-by: Rob Murray <rob.murray@docker.com>

Rob Murray authored on 2024/08/10 22:45:55
Showing 2 changed files
... ...
@@ -953,18 +953,26 @@ func initBridgeDriver(controller *libnetwork.Controller, cfg config.BridgeConfig
953 953
 	}
954 954
 
955 955
 	if len(nwList) > 0 {
956
+		// Pick any address from the bridge as a starting point.
956 957
 		nw := nwList[0]
957 958
 		if len(nwList) > 1 && cfg.FixedCIDR != "" {
958
-			_, fCIDR, err := net.ParseCIDR(cfg.FixedCIDR)
959
+			fCidrIP, fCidrNet, err := net.ParseCIDR(cfg.FixedCIDR)
959 960
 			if err != nil {
960
-				return errors.Wrap(err, "parse CIDR failed")
961
+				return errors.Wrap(err, "parse fixed-cidr failed")
961 962
 			}
962
-			// Iterate through in case there are multiple addresses for the bridge
963
+			// If there's an address with a subnet that contains fixed-cidr, use it.
963 964
 			for _, entry := range nwList {
964
-				if fCIDR.Contains(entry.IP) {
965
+				if entry.Contains(fCidrIP) {
965 966
 					nw = entry
966 967
 					break
967 968
 				}
969
+				// For backwards compatibility - prefer the first bridge address within
970
+				// fixed-cidr. If fixed-cidr has a bigger subnet than nw.IP, this doesn't really
971
+				// make sense - the allocatable range (fixed-cidr) will be bigger than the subnet
972
+				// (entry.IPNet).
973
+				if fCidrNet.Contains(entry.IP) && !fCidrNet.Contains(nw.IP) {
974
+					nw = entry
975
+				}
968 976
 			}
969 977
 		}
970 978
 
... ...
@@ -198,13 +198,12 @@ func TestDaemonDefaultBridgeIPAM_UserBr(t *testing.T) {
198 198
 			name:               "fcidr in bridge subnet and bridge ip not in fcidr",
199 199
 			initialBridgeAddrs: []string{"192.168.160.88/20", "192.168.176.88/20", "192.168.192.88/20"},
200 200
 			daemonArgs:         []string{"--fixed-cidr", "192.168.177.0/24"},
201
+			// Selected bridge subnet should be the one that encompasses fixed-cidr.
201 202
 			expIPAMConfig: []network.IPAMConfig{
202 203
 				{
203
-					// FIXME(robmry) - selected subnet should be the one that encompasses
204
-					//  fixed-cidr, allocatable range is outside the subnet.
205
-					Subnet:  "192.168.160.0/20",
204
+					Subnet:  "192.168.176.0/20",
206 205
 					IPRange: "192.168.177.0/24",
207
-					Gateway: "192.168.160.88",
206
+					Gateway: "192.168.176.88",
208 207
 				},
209 208
 			},
210 209
 		},