package bridge
import (
"context"
"testing"
cerrdefs "github.com/containerd/errdefs"
"github.com/moby/moby/v2/daemon/libnetwork/drvregistry"
"github.com/moby/moby/v2/daemon/libnetwork/netlabel"
"github.com/moby/moby/v2/daemon/libnetwork/nlwrap"
"github.com/moby/moby/v2/internal/testutil/netnsutils"
"github.com/moby/moby/v2/internal/testutil/storeutils"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
func TestLinkCreate(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()
d, err := newDriver(storeutils.NewTempStore(t), Configuration{}, &drvregistry.PortMappers{})
assert.NilError(t, err)
mtu := 1490
option := map[string]any{
netlabel.GenericData: &networkConfiguration{
BridgeName: DefaultBridgeName,
EnableIPv4: true,
EnableIPv6: true,
Mtu: mtu,
},
}
ipdList := getIPv4Data(t)
ipd6List := getIPv6Data(t)
err = d.CreateNetwork(context.Background(), "dummy", option, nil, ipdList, ipd6List)
assert.NilError(t, err, "Failed to create bridge")
te := newTestEndpoint46(ipdList[0].Pool, ipd6List[0].Pool, 10)
err = d.CreateEndpoint(context.Background(), "dummy", "", te.Interface(), nil)
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
assert.Check(t, is.Error(err, "invalid endpoint id: "))
// Good endpoint creation
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te.Interface(), nil)
assert.NilError(t, err)
err = d.Join(context.Background(), "dummy", "ep", "sbox", te, nil, nil)
assert.NilError(t, err)
assert.Assert(t, te.iface.dstPrefix != "", "got: %q, want: %q", te.iface.dstPrefix, "")
// Verify sbox endpoint interface inherited MTU value from bridge config
sboxLnk, err := nlwrap.LinkByName(te.iface.srcName)
assert.NilError(t, err)
assert.Assert(t, is.Equal(sboxLnk.Attrs().MTU, mtu), "Sandbox endpoint interface did not inherit bridge interface MTU config")
// TODO: if we could get peer name from (sboxLnk.(*netlink.Veth)).PeerName
// then we could check the MTU on hostLnk as well.
te1 := newTestEndpoint(ipdList[0].Pool, 11)
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te1.Interface(), nil)
assert.Check(t, is.ErrorType(err, cerrdefs.IsPermissionDenied))
assert.Assert(t, is.Error(err, "Endpoint (ep) already exists (Only one endpoint allowed)"), "Failed to detect duplicate endpoint id on same network")
_, err = nlwrap.LinkByName(te.iface.srcName)
assert.Check(t, err, "Could not find source link %s", te.iface.srcName)
n, ok := d.networks["dummy"]
assert.Check(t, ok, "Failed to find dummy network inside driveer")
ip := te.iface.addr.IP
assert.Check(t, n.bridge.bridgeIPv4.Contains(ip), "IP %s should be a valid ip in the subnet %s", ip.String(), n.bridge.bridgeIPv4.String())
ip6 := te.iface.addrv6.IP
assert.Check(t, n.bridge.bridgeIPv6.Contains(ip6), "IP %s should be a valid ip in the subnet %s", ip6.String(), n.bridge.bridgeIPv6.String())
assert.Check(t, te.gw.Equal(n.bridge.bridgeIPv4.IP), "Invalid default gateway. Expected %s. Got %s", n.bridge.bridgeIPv4.IP.String(), te.gw.String())
assert.Check(t, te.gw6.Equal(n.bridge.bridgeIPv6.IP), "Invalid default gateway for IPv6. Expected %s. Got %s", n.bridge.bridgeIPv6.IP.String(), te.gw6.String())
}
func TestLinkCreateTwo(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()
d, err := newDriver(storeutils.NewTempStore(t), Configuration{}, &drvregistry.PortMappers{})
assert.NilError(t, err)
option := map[string]any{
netlabel.GenericData: &networkConfiguration{
BridgeName: DefaultBridgeName,
EnableIPv4: true,
EnableIPv6: true,
},
}
ipdList := getIPv4Data(t)
err = d.CreateNetwork(context.Background(), "dummy", option, nil, ipdList, getIPv6Data(t))
assert.NilError(t, err, "Failed to create bridge")
te1 := newTestEndpoint(ipdList[0].Pool, 11)
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te1.Interface(), nil)
assert.NilError(t, err)
te2 := newTestEndpoint(ipdList[0].Pool, 12)
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te2.Interface(), nil)
assert.Check(t, is.ErrorType(err, cerrdefs.IsPermissionDenied))
assert.Assert(t, is.Error(err, "Endpoint (ep) already exists (Only one endpoint allowed)"), "Failed to detect duplicate endpoint id on same network")
}
func TestLinkCreateNoEnableIPv6(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()
d, err := newDriver(storeutils.NewTempStore(t), Configuration{}, &drvregistry.PortMappers{})
assert.NilError(t, err)
option := map[string]any{
netlabel.GenericData: &networkConfiguration{
BridgeName: DefaultBridgeName,
EnableIPv4: true,
},
}
ipdList := getIPv4Data(t)
err = d.CreateNetwork(context.Background(), "dummy", option, nil, ipdList, getIPv6Data(t))
assert.NilError(t, err, "Failed to create bridge")
te := newTestEndpoint(ipdList[0].Pool, 30)
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te.Interface(), nil)
assert.NilError(t, err)
assert.Check(t, is.Nil(te.iface.addrv6), "Expected IPv6 address to be nil when IPv6 is not enabled, got %s", te.iface.addrv6)
assert.Check(t, is.Nil(te.gw6), "Expected GatewayIPv6 to be nil when IPv6 is not enabled, got %s", te.gw6)
}
func TestLinkDelete(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()
d, err := newDriver(storeutils.NewTempStore(t), Configuration{}, &drvregistry.PortMappers{})
assert.NilError(t, err)
option := map[string]any{
netlabel.GenericData: &networkConfiguration{
BridgeName: DefaultBridgeName,
EnableIPv4: true,
EnableIPv6: true,
},
}
ipdList := getIPv4Data(t)
err = d.CreateNetwork(context.Background(), "dummy", option, nil, ipdList, getIPv6Data(t))
assert.NilError(t, err, "Failed to create bridge")
te := newTestEndpoint(ipdList[0].Pool, 30)
err = d.CreateEndpoint(context.Background(), "dummy", "ep1", te.Interface(), nil)
assert.NilError(t, err)
err = d.DeleteEndpoint("dummy", "")
assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
assert.Assert(t, is.Error(err, "invalid endpoint id: "))
err = d.DeleteEndpoint("dummy", "ep1")
assert.NilError(t, err)
}