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") } }
func AddConnection(nspid int, networkName string) (ovsConnection OvsConnection, err error) { var ( bridge = OvsBridge.Name prefix = "ovs" ) ovsConnection = OvsConnection{} err = nil if bridge == "" { err = fmt.Errorf("bridge is not available") return } if networkName == "" { networkName = DefaultNetworkName } bridgeNetwork, err := GetNetwork(networkName) if err != nil { return ovsConnection, err } portName, err := createOvsInternalPort(prefix, bridge, bridgeNetwork.Vlan) if err != nil { return } // Add a dummy sleep to make sure the interface is seen by the subsequent calls. time.Sleep(time.Second * 1) _, subnet, _ := net.ParseCIDR(bridgeNetwork.Subnet) ip := IPAMRequest(*subnet) mac := generateMacAddr(ip).String() subnetString := subnet.String() subnetPrefix := subnetString[len(subnetString)-3 : len(subnetString)] ovsConnection = OvsConnection{portName, ip.String(), subnetPrefix, mac, bridgeNetwork.Gateway} if err = SetMtu(portName, mtu); err != nil { return } if err = InterfaceUp(portName); err != nil { return } if err = os.Symlink(filepath.Join(os.Getenv("PROCFS"), strconv.Itoa(nspid), "ns/net"), filepath.Join("/var/run/netns", strconv.Itoa(nspid))); err != nil { return } // Lock the OS Thread so we don't accidentally switch namespaces runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return } defer origns.Close() targetns, err := netns.GetFromName(strconv.Itoa(nspid)) if err != nil { return } defer targetns.Close() if err = SetInterfaceInNamespaceFd(portName, uintptr(int(targetns))); err != nil { return } if err = netns.Set(targetns); err != nil { return } defer netns.Set(origns) if err = InterfaceDown(portName); err != nil { return } /* TODO : Find a way to change the interface name to defaultDevice (eth0). Currently using the Randomly created OVS port as is. refer to veth.go where one end of the veth pair is renamed to eth0 */ if err = ChangeInterfaceName(portName, portName); err != nil { return } if err = SetInterfaceIp(portName, ip.String()+subnetPrefix); err != nil { return } if err = SetInterfaceMac(portName, generateMacAddr(ip).String()); err != nil { return } if err = InterfaceUp(portName); err != nil { return } if err = SetDefaultGateway(bridgeNetwork.Gateway, portName); err != nil { return } return ovsConnection, nil }