libnet: bridge: ignore EINVAL when configuring bridge MTU
Since964ab7158c
, we explicitly set the bridge MTU if it was specified. Unfortunately, kernel <v4.17 have a check preventing us to manually set the MTU to anything greater than 1500 if no links is attached to the bridge, which is how we do things -- create the bridge, set its MTU and later on, attach veths to it. Relevant kernel commit:804b854d37
As we still have to support CentOS/RHEL 7 (and their old v3.10 kernels) for a few more months, we need to ignore EINVAL if the MTU is > 1500 (but <= 65535). Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This commit is contained in:
parent
7964cae9e8
commit
89470a7114
2 changed files with 44 additions and 0 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue