Repository: moby/moby (language: go)

Issue:
docker fails to start after upgrade to 23.0.4
### Description

I updated to docker-ce `5:23.0.4-1~debian.11~bullseye` (tested with a fresh installation) and now dockerd fails to start:
```
failed to start daemon: Error initializing network controller: Error creating default "bridge" network: failed to parse pool request for address space "LocalDefault" pool "" subpool "100.64.0.0/26": Invalid Address SubPool
```
It worked with the previous version (`5:23.0.3-1~debian.11~bullseye`).

My `/etc/docker/daemon.json` contains:
```json
{
  "fixed-cidr": "100.64.0.0/26"
}
```

I suspect this is caused by #45246.

### Reproduce

Install docker as explained in the issue description and `systemctl start docker`.

### Expected behavior

normal docker startup

### docker version

```bash
Client: Docker Engine - Community
 Version:           23.0.4
 API version:       1.42
 Go version:        go1.19.8
 Git commit:        f480fb1
 Built:             Fri Apr 14 10:32:17 2023
 OS/Arch:           linux/amd64
 Context:           default
```


### docker info

```bash
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.10.4
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.17.2
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
  scan: Docker Scan (Docker Inc.)
    Version:  v0.23.0
    Path:     /usr/libexec/docker/cli-plugins/docker-scan

Server:
ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
errors pretty printing info
```


### Additional Info

_No response_


Discussion / hints:
Docker starts again when specifying a `bip` in `/etc/docker/daemon.json`:
```json
{
  "bip": "100.64.0.1/26",
  "fixed-cidr": "100.64.0.0/26"
}
```
Was the `bip` config option made mandatory?
I would not expect such changes in a patch release.
@akerouanton ptal
Yeah, it's definitely a bug caused by #45246. I'm working on a fix.

Fix patch:
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index 503c227261116..e8e6498cfd959 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -997,6 +997,9 @@ func initBridgeDriver(controller *libnetwork.Controller, config *config.Config)
 		}
 
 		ipamV4Conf.SubPool = fCIDR.String()
+		if ipamV4Conf.PreferredPool == "" {
+			ipamV4Conf.PreferredPool = fCIDR.String()
+		}
 	}
 
 	if config.BridgeConfig.DefaultGatewayIPv4 != nil {
diff --git a/libnetwork/drivers/bridge/setup_device.go b/libnetwork/drivers/bridge/setup_device.go
index 73d8647b0ee47..974115603bb34 100644
--- a/libnetwork/drivers/bridge/setup_device.go
+++ b/libnetwork/drivers/bridge/setup_device.go
@@ -16,8 +16,14 @@ import (
 // SetupDevice create a new bridge interface/
 func setupDevice(config *networkConfiguration, i *bridgeInterface) error {
 	// We only attempt to create the bridge when the requested device name is
-	// the default one.
-	if config.BridgeName != DefaultBridgeName && config.DefaultBridge {
+	// the default one. The default bridge name can be overridden with the
+	// DOCKER_TEST_CREATE_DEFAULT_BRIDGE env var. It should be used only for
+	// test purpose.
+	var defaultBridgeName string
+	if defaultBridgeName = os.Getenv("DOCKER_TEST_CREATE_DEFAULT_BRIDGE"); defaultBridgeName == "" {
+		defaultBridgeName = DefaultBridgeName
+	}
+	if config.BridgeName != defaultBridgeName && config.DefaultBridge {
 		return NonDefaultBridgeExistError(config.BridgeName)
 	}
 


Test patch:
diff --git a/integration/daemon/daemon_test.go b/integration/daemon/daemon_test.go
index 2242d3d4f136a..7ecb2c0aa4793 100644
--- a/integration/daemon/daemon_test.go
+++ b/integration/daemon/daemon_test.go
@@ -21,6 +21,7 @@ import (
 	"github.com/docker/docker/testutil/daemon"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
+	"gotest.tools/v3/icmd"
 	"gotest.tools/v3/skip"
 )
 
@@ -400,3 +401,30 @@ func testLiveRestoreVolumeReferences(t *testing.T) {
 		runTest(t, "no")
 	})
 }
+
+func TestDaemonDefaultBridgeWithFixedCidrButNoBip(t *testing.T) {
+	skip.If(t, runtime.GOOS == "windows")
+
+	bridgeName := "ext-bridge1"
+	d := daemon.New(t, daemon.WithEnvVars("DOCKER_TEST_CREATE_DEFAULT_BRIDGE="+bridgeName))
+	defer func() {
+		d.Stop(t)
+		d.Cleanup(t)
+	}()
+
+	defer func() {
+		// No need to clean up when running this test in rootless mode, as the
+		// interface is deleted when the daemon is stopped and the netns
+		// reclaimed by the kernel.
+		if !testEnv.IsRootless() {
+			deleteInterface(t, bridgeName)
+		}
+	}()
+	d.StartWithBusybox(t, "--bridge", bridgeName, "--fixed-cidr", "192.168.130.0/24")
+}
+
+func deleteInterface(t *testing.T, ifName string) {
+	icmd.RunCommand("ip", "link", "delete", ifName).Assert(t, icmd.Success)
+	icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(t, icmd.Success)
+	icmd.RunCommand("iptables", "--flush").Assert(t, icmd.Success)
+}