// NsEnter locks the current goroutine the OS thread and switches to a // new network namespace. The returned function must be called in order // to restore the previous state and unlock the thread. func NsEnter(ns netns.NsHandle) (func() error, error) { runtime.LockOSThread() origns, err := netns.Get() if err != nil { runtime.UnlockOSThread() return nil, err } err = netns.Set(ns) if err != nil { origns.Close() runtime.UnlockOSThread() return nil, err } return func() error { defer runtime.UnlockOSThread() defer origns.Close() if err := netns.Set(origns); err != nil { return err } return nil }, nil }
// NsCreate returns a handle to a new network namespace. // NsEnter must be used to safely enter and exit the new namespace. func NsCreate() (netns.NsHandle, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return netns.None(), err } defer origns.Close() defer netns.Set(origns) return netns.New() }
func TestLinkSetNs(t *testing.T) { tearDown := setUpNetlinkTest(t) defer tearDown() basens, err := netns.Get() if err != nil { t.Fatal("Failed to get basens") } defer basens.Close() newns, err := netns.New() if err != nil { t.Fatal("Failed to create newns") } defer newns.Close() link := &Veth{LinkAttrs{Name: "foo"}, "bar"} if err := LinkAdd(link); err != nil { t.Fatal(err) } peer, err := LinkByName("bar") if err != nil { t.Fatal(err) } LinkSetNsFd(peer, int(basens)) if err != nil { t.Fatal("Failed to set newns for link") } _, err = LinkByName("bar") if err == nil { t.Fatal("Link bar is still in newns") } err = netns.Set(basens) if err != nil { t.Fatal("Failed to set basens") } peer, err = LinkByName("bar") if err != nil { t.Fatal("Link is not in basens") } if err := LinkDel(peer); err != nil { t.Fatal(err) } err = netns.Set(newns) if err != nil { t.Fatal("Failed to set newns") } _, err = LinkByName("foo") if err == nil { t.Fatal("Other half of veth pair not deleted") } }