diff --git a/libnetwork/drivers/bridge/setup_device_linux.go b/libnetwork/drivers/bridge/setup_device_linux.go index 050aaa1710482..374c6b7b6f8a5 100644 --- a/libnetwork/drivers/bridge/setup_device_linux.go +++ b/libnetwork/drivers/bridge/setup_device_linux.go @@ -2,9 +2,11 @@ package bridge import ( "context" + "errors" "fmt" "os" "path/filepath" + "syscall" "github.com/containerd/log" "github.com/docker/docker/libnetwork/netutils" @@ -47,6 +49,14 @@ func setupDevice(config *networkConfiguration, i *bridgeInterface) error { func setupMTU(config *networkConfiguration, i *bridgeInterface) error { if err := i.nlh.LinkSetMTU(i.Link, config.Mtu); err != nil { + // Before Linux v4.17, bridges couldn't be configured "manually" with an MTU greater than 1500, although it + // could be autoconfigured with such a value when interfaces were added to the bridge. In that case, the + // bridge MTU would be set automatically by the kernel to the lowest MTU of all interfaces attached. To keep + // compatibility with older kernels, we need to discard -EINVAL. + // TODO(aker): remove this once we drop support for CentOS/RHEL 7. + if config.Mtu > 1500 && config.Mtu <= 0xFFFF && errors.Is(err, syscall.EINVAL) { + return nil + } log.G(context.TODO()).WithError(err).Errorf("Failed to set bridge MTU %s via netlink", config.BridgeName) return err } diff --git a/libnetwork/drivers/bridge/setup_device_linux_test.go b/libnetwork/drivers/bridge/setup_device_linux_test.go index a7868a00ea7a6..05f3513314885 100644 --- a/libnetwork/drivers/bridge/setup_device_linux_test.go +++ b/libnetwork/drivers/bridge/setup_device_linux_test.go @@ -3,11 +3,13 @@ package bridge import ( "bytes" "net" + "syscall" "testing" "github.com/docker/docker/internal/testutils/netnsutils" "github.com/docker/docker/libnetwork/netutils" "github.com/vishvananda/netlink" + "gotest.tools/v3/assert" ) func TestSetupNewBridge(t *testing.T) { @@ -92,3 +94,35 @@ func TestGenerateRandomMAC(t *testing.T) { t.Fatalf("Generated twice the same MAC address %v", mac1) } } + +func TestMTUBiggerThan1500(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + + nh, err := netlink.NewHandle() + if err != nil { + t.Fatal(err) + } + defer nh.Close() + + config := &networkConfiguration{BridgeName: DefaultBridgeName, Mtu: 9000} + br := &bridgeInterface{nlh: nh} + + assert.NilError(t, setupDevice(config, br)) + assert.NilError(t, setupMTU(config, br)) +} + +func TestMTUBiggerThan64K(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + + nh, err := netlink.NewHandle() + if err != nil { + t.Fatal(err) + } + defer nh.Close() + + config := &networkConfiguration{BridgeName: DefaultBridgeName, Mtu: 65536} + br := &bridgeInterface{nlh: nh} + + assert.NilError(t, setupDevice(config, br)) + assert.ErrorIs(t, setupMTU(config, br), syscall.EINVAL) +}