
This PR attempts to work around bugs present in kernel version 3.18-4.0.1 relating to namespace creation and destruction. This fix attempts to avoid certain systemmcalls to not get in the kkernel bug path as well as lazily garbage collecting the name paths when they are removed. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/docker/libnetwork/netutils"
|
|
"github.com/vishvananda/netlink"
|
|
"github.com/vishvananda/netns"
|
|
)
|
|
|
|
const (
|
|
vethName1 = "wierdlongname1"
|
|
vethName2 = "wierdlongname2"
|
|
vethName3 = "wierdlongname3"
|
|
vethName4 = "wierdlongname4"
|
|
sboxIfaceName = "containername"
|
|
)
|
|
|
|
func newKey(t *testing.T) (string, error) {
|
|
name, err := netutils.GenerateRandomName("netns", 12)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
name = filepath.Join("/tmp", name)
|
|
if _, err := os.Create(name); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Set the rpmCleanupPeriod to be low to make the test run quicker
|
|
gpmCleanupPeriod = 2
|
|
|
|
return name, nil
|
|
}
|
|
|
|
func newInfo(t *testing.T) (*Info, error) {
|
|
veth := &netlink.Veth{
|
|
LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
|
|
PeerName: vethName2}
|
|
if err := netlink.LinkAdd(veth); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store the sandbox side pipe interface
|
|
// This is needed for cleanup on DeleteEndpoint()
|
|
intf1 := &Interface{}
|
|
intf1.SrcName = vethName2
|
|
intf1.DstName = sboxIfaceName
|
|
|
|
ip4, addr, err := net.ParseCIDR("192.168.1.100/24")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf1.Address = addr
|
|
intf1.Address.IP = ip4
|
|
|
|
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
|
ip6, addrv6, err := net.ParseCIDR("fe80::2/64")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf1.AddressIPv6 = addrv6
|
|
intf1.AddressIPv6.IP = ip6
|
|
|
|
_, route, err := net.ParseCIDR("192.168.2.1/32")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
intf1.Routes = []*net.IPNet{route}
|
|
|
|
veth = &netlink.Veth{
|
|
LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0},
|
|
PeerName: vethName4}
|
|
|
|
if err := netlink.LinkAdd(veth); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
intf2 := &Interface{}
|
|
intf2.SrcName = vethName4
|
|
intf2.DstName = sboxIfaceName
|
|
|
|
ip4, addr, err = net.ParseCIDR("192.168.2.100/24")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf2.Address = addr
|
|
intf2.Address.IP = ip4
|
|
|
|
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
|
ip6, addrv6, err = net.ParseCIDR("fe80::3/64")
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf2.AddressIPv6 = addrv6
|
|
intf2.AddressIPv6.IP = ip6
|
|
|
|
sinfo := &Info{Interfaces: []*Interface{intf1, intf2}}
|
|
|
|
sinfo.Gateway = net.ParseIP("192.168.1.1")
|
|
// sinfo.GatewayIPv6 = net.ParseIP("2001:DB8::1")
|
|
sinfo.GatewayIPv6 = net.ParseIP("fe80::1")
|
|
|
|
return sinfo, nil
|
|
}
|
|
|
|
func verifySandbox(t *testing.T, s Sandbox) {
|
|
_, ok := s.(*networkNamespace)
|
|
if !ok {
|
|
t.Fatalf("The sandox interface returned is not of type networkNamespace")
|
|
}
|
|
|
|
origns, err := netns.Get()
|
|
if err != nil {
|
|
t.Fatalf("Could not get the current netns: %v", err)
|
|
}
|
|
defer origns.Close()
|
|
|
|
f, err := os.OpenFile(s.Key(), os.O_RDONLY, 0)
|
|
if err != nil {
|
|
t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err)
|
|
}
|
|
defer f.Close()
|
|
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
nsFD := f.Fd()
|
|
if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
|
|
t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", s.Key(), err)
|
|
}
|
|
defer netns.Set(origns)
|
|
|
|
_, err = netlink.LinkByName(sboxIfaceName + "0")
|
|
if err != nil {
|
|
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+"0",
|
|
err)
|
|
}
|
|
|
|
_, err = netlink.LinkByName(sboxIfaceName + "1")
|
|
if err != nil {
|
|
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+"1",
|
|
err)
|
|
}
|
|
}
|
|
|
|
func verifyCleanup(t *testing.T, s Sandbox) {
|
|
time.Sleep(time.Duration(gpmCleanupPeriod*2) * time.Second)
|
|
if _, err := os.Stat(s.Key()); err == nil {
|
|
t.Fatalf("The sandbox path %s is not getting cleanup event after twice the cleanup period", s.Key())
|
|
}
|
|
}
|