Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[25.0 backport] libnet: bridge: ignore EINVAL when configuring bridge MTU #47311

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions libnetwork/drivers/bridge/setup_device_linux.go
Expand Up @@ -2,9 +2,11 @@ package bridge

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"syscall"

"github.com/containerd/log"
"github.com/docker/docker/libnetwork/netutils"
Expand Down Expand Up @@ -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
}
Expand Down
34 changes: 34 additions & 0 deletions libnetwork/drivers/bridge/setup_device_linux_test.go
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
}