2017-11-07 19:49:48 +00:00
|
|
|
// +build linux
|
|
|
|
|
2014-09-01 03:27:34 +00:00
|
|
|
package netlink
|
|
|
|
|
|
|
|
import (
|
2017-05-05 09:02:53 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2014-09-01 03:27:34 +00:00
|
|
|
"os"
|
|
|
|
"runtime"
|
2017-05-05 09:02:53 +00:00
|
|
|
"strings"
|
2014-09-01 03:27:34 +00:00
|
|
|
"testing"
|
2015-02-10 23:00:36 +00:00
|
|
|
|
|
|
|
"github.com/vishvananda/netns"
|
2017-10-20 20:38:07 +00:00
|
|
|
"golang.org/x/sys/unix"
|
2014-09-01 03:27:34 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type tearDownNetlinkTest func()
|
|
|
|
|
2017-02-06 16:14:07 +00:00
|
|
|
func skipUnlessRoot(t *testing.T) {
|
2014-09-01 03:27:34 +00:00
|
|
|
if os.Getuid() != 0 {
|
2017-11-07 23:41:07 +00:00
|
|
|
t.Skip("Test requires root privileges.")
|
2014-09-01 03:27:34 +00:00
|
|
|
}
|
2017-02-06 16:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func setUpNetlinkTest(t *testing.T) tearDownNetlinkTest {
|
|
|
|
skipUnlessRoot(t)
|
2014-09-01 03:27:34 +00:00
|
|
|
|
|
|
|
// new temporary namespace so we don't pollute the host
|
|
|
|
// lock thread since the namespace is thread local
|
|
|
|
runtime.LockOSThread()
|
|
|
|
var err error
|
|
|
|
ns, err := netns.New()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("Failed to create newns", ns)
|
|
|
|
}
|
|
|
|
|
|
|
|
return func() {
|
|
|
|
ns.Close()
|
|
|
|
runtime.UnlockOSThread()
|
|
|
|
}
|
|
|
|
}
|
2017-02-19 03:22:09 +00:00
|
|
|
|
|
|
|
func setUpMPLSNetlinkTest(t *testing.T) tearDownNetlinkTest {
|
|
|
|
if _, err := os.Stat("/proc/sys/net/mpls/platform_labels"); err != nil {
|
2017-11-07 23:41:07 +00:00
|
|
|
t.Skip("Test requires MPLS support.")
|
2017-02-19 03:22:09 +00:00
|
|
|
}
|
|
|
|
f := setUpNetlinkTest(t)
|
|
|
|
setUpF := func(path, value string) {
|
|
|
|
file, err := os.Create(path)
|
|
|
|
defer file.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Failed to open %s: %s", path, err)
|
|
|
|
}
|
|
|
|
file.WriteString(value)
|
|
|
|
}
|
|
|
|
setUpF("/proc/sys/net/mpls/platform_labels", "1024")
|
|
|
|
setUpF("/proc/sys/net/mpls/conf/lo/input", "1")
|
|
|
|
return f
|
|
|
|
}
|
2017-05-05 09:02:53 +00:00
|
|
|
|
|
|
|
func setUpNetlinkTestWithKModule(t *testing.T, name string) tearDownNetlinkTest {
|
|
|
|
file, err := ioutil.ReadFile("/proc/modules")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("Failed to open /proc/modules", err)
|
|
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, line := range strings.Split(string(file), "\n") {
|
|
|
|
n := strings.Split(line, " ")[0]
|
|
|
|
if n == name {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if !found {
|
2017-11-07 23:41:07 +00:00
|
|
|
t.Skipf("Test requires kmodule %q.", name)
|
2017-05-05 09:02:53 +00:00
|
|
|
}
|
|
|
|
return setUpNetlinkTest(t)
|
|
|
|
}
|
2017-06-06 09:09:16 +00:00
|
|
|
|
|
|
|
func remountSysfs() error {
|
2017-10-20 20:38:07 +00:00
|
|
|
if err := unix.Mount("", "/", "none", unix.MS_SLAVE|unix.MS_REC, ""); err != nil {
|
2017-06-06 09:09:16 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-10-20 20:38:07 +00:00
|
|
|
if err := unix.Unmount("/sys", unix.MNT_DETACH); err != nil {
|
2017-06-06 09:09:16 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-10-20 20:38:07 +00:00
|
|
|
return unix.Mount("", "/sys", "sysfs", 0, "")
|
2017-06-06 09:09:16 +00:00
|
|
|
}
|
2017-11-07 23:14:34 +00:00
|
|
|
|
|
|
|
func minKernelRequired(t *testing.T, kernel, major int) {
|
|
|
|
k, m, err := KernelVersion()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if k < kernel || k == kernel && m < major {
|
|
|
|
t.Skipf("Host Kernel (%d.%d) does not meet test's minimum required version: (%d.%d)",
|
|
|
|
k, m, kernel, major)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func KernelVersion() (kernel, major int, err error) {
|
|
|
|
uts := unix.Utsname{}
|
|
|
|
if err = unix.Uname(&uts); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ba := make([]byte, 0, len(uts.Release))
|
|
|
|
for _, b := range uts.Release {
|
|
|
|
if b == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ba = append(ba, byte(b))
|
|
|
|
}
|
|
|
|
var rest string
|
|
|
|
if n, _ := fmt.Sscanf(string(ba), "%d.%d%s", &kernel, &major, &rest); n < 2 {
|
|
|
|
err = fmt.Errorf("can't parse kernel version in %q", string(ba))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|