mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
166 lines
4.9 KiB
Go
166 lines
4.9 KiB
Go
package bridge
|
|
|
|
import (
|
|
"net"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/moby/moby/v2/daemon/libnetwork/nlwrap"
|
|
"github.com/moby/moby/v2/internal/testutil/netnsutils"
|
|
"github.com/vishvananda/netlink"
|
|
"golang.org/x/sys/unix"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
)
|
|
|
|
func cidrToIPNet(t *testing.T, cidr string) *net.IPNet {
|
|
t.Helper()
|
|
ip, ipNet, err := net.ParseCIDR(cidr)
|
|
assert.Assert(t, is.Nil(err))
|
|
return &net.IPNet{IP: ip, Mask: ipNet.Mask}
|
|
}
|
|
|
|
func addAddr(t *testing.T, link netlink.Link, addr string) {
|
|
t.Helper()
|
|
ipNet := cidrToIPNet(t, addr)
|
|
err := netlink.AddrAdd(link, &netlink.Addr{IPNet: ipNet})
|
|
assert.Assert(t, is.Nil(err))
|
|
}
|
|
|
|
func prepTestBridge(t *testing.T, nc *networkConfiguration) *bridgeInterface {
|
|
t.Helper()
|
|
nh, err := nlwrap.NewHandle()
|
|
assert.Assert(t, err)
|
|
i, err := newInterface(nh, nc)
|
|
assert.Assert(t, err)
|
|
err = setupDevice(nc, i)
|
|
assert.Assert(t, err)
|
|
return i
|
|
}
|
|
|
|
func TestInterfaceDefaultName(t *testing.T) {
|
|
defer netnsutils.SetupTestOSContext(t)()
|
|
|
|
nh, err := nlwrap.NewHandle()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
config := &networkConfiguration{}
|
|
_, err = newInterface(nh, config)
|
|
assert.Check(t, err)
|
|
assert.Equal(t, config.BridgeName, DefaultBridgeName)
|
|
}
|
|
|
|
func TestAddressesNoInterface(t *testing.T) {
|
|
i := bridgeInterface{}
|
|
addrs, err := i.addresses(netlink.FAMILY_V6)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Len(addrs, 0))
|
|
}
|
|
|
|
func TestAddressesEmptyInterface(t *testing.T) {
|
|
defer netnsutils.SetupTestOSContext(t)()
|
|
|
|
nh, err := nlwrap.NewHandle()
|
|
assert.NilError(t, err)
|
|
|
|
inf, err := newInterface(nh, &networkConfiguration{})
|
|
assert.NilError(t, err)
|
|
|
|
addrsv4, err := inf.addresses(netlink.FAMILY_V4)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Len(addrsv4, 0))
|
|
|
|
addrsv6, err := inf.addresses(netlink.FAMILY_V6)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Len(addrsv6, 0))
|
|
}
|
|
|
|
func TestAddressesNonEmptyInterface(t *testing.T) {
|
|
defer netnsutils.SetupTestOSContext(t)()
|
|
|
|
i := prepTestBridge(t, &networkConfiguration{})
|
|
|
|
const expAddrV4, expAddrV6 = "192.168.1.2/24", "fd00:1234::/64"
|
|
addAddr(t, i.Link, expAddrV4)
|
|
addAddr(t, i.Link, expAddrV6)
|
|
|
|
addrs, err := i.addresses(netlink.FAMILY_V4)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Len(addrs, 1))
|
|
assert.Equal(t, addrs[0].IPNet.String(), expAddrV4)
|
|
|
|
addrs, err = i.addresses(netlink.FAMILY_V6)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Len(addrs, 1))
|
|
assert.Equal(t, addrs[0].IPNet.String(), expAddrV6)
|
|
}
|
|
|
|
func TestProgramIPv6Addresses(t *testing.T) {
|
|
defer netnsutils.SetupTestOSContext(t)()
|
|
|
|
checkAddrs := func(i *bridgeInterface, nc *networkConfiguration, expAddrs []string) {
|
|
t.Helper()
|
|
nladdrs, err := i.addresses(netlink.FAMILY_V6)
|
|
actual := []string{}
|
|
for _, a := range nladdrs {
|
|
actual = append(actual, a.String())
|
|
}
|
|
assert.NilError(t, err)
|
|
exp := append([]string(nil), expAddrs...)
|
|
sort.Strings(exp)
|
|
sort.Strings(actual)
|
|
assert.DeepEqual(t, actual, exp)
|
|
assert.Check(t, is.DeepEqual(i.bridgeIPv6, nc.AddressIPv6))
|
|
assert.Check(t, is.DeepEqual(i.gatewayIPv6, nc.AddressIPv6.IP))
|
|
}
|
|
|
|
nc := &networkConfiguration{}
|
|
i := prepTestBridge(t, nc)
|
|
|
|
// The bridge has no addresses, ask for a regular IPv6 network and expect it to
|
|
// be added to the bridge.
|
|
nc.AddressIPv6 = cidrToIPNet(t, "2000:3000::1/64")
|
|
err := i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"2000:3000::1/64"})
|
|
|
|
// Shrink the subnet of that regular address, the prefix length of the address
|
|
// will not be modified - but it's informational-only, the address itself has
|
|
// not changed.
|
|
nc.AddressIPv6 = cidrToIPNet(t, "2000:3000::1/80")
|
|
err = i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"2000:3000::1/64"})
|
|
|
|
// Ask for link-local only, by specifying an address with the Link Local prefix.
|
|
// The regular address should be removed.
|
|
nc.AddressIPv6 = cidrToIPNet(t, "fe80::1/64")
|
|
err = i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"fe80::1/64"})
|
|
|
|
// Swap the standard link local address for a nonstandard one. The standard LL
|
|
// address will not be removed.
|
|
nc.AddressIPv6 = cidrToIPNet(t, "fe80:5555::1/55")
|
|
err = i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"fe80:5555::1/55", "fe80::1/64"})
|
|
|
|
// Back to the original address, expect the nonstandard LL address to be replaced.
|
|
nc.AddressIPv6 = cidrToIPNet(t, "2000:3000::1/64")
|
|
err = i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"2000:3000::1/64", "fe80::1/64"})
|
|
|
|
// Add a multicast address to the bridge and check it's not removed.
|
|
mcNlAddr, err := netlink.ParseAddr("ff05::db8:0:1234/96")
|
|
assert.NilError(t, err)
|
|
mcNlAddr.Flags = unix.IFA_F_MCAUTOJOIN
|
|
err = i.nlh.AddrAdd(i.Link, mcNlAddr)
|
|
assert.NilError(t, err)
|
|
err = i.programIPv6Addresses(nc)
|
|
assert.NilError(t, err)
|
|
checkAddrs(i, nc, []string{"2000:3000::1/64", "fe80::1/64", "ff05::db8:0:1234/96"})
|
|
}
|