Merge pull request #645 from dcbw/veth-peer-to-host-ns

ip: place veth peer in host namspace directly
This commit is contained in:
Dan Williams 2021-07-27 13:59:05 -05:00 committed by GitHub
commit 649e0181fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 17 deletions

View File

@ -32,14 +32,16 @@ var (
ErrLinkNotFound = errors.New("link not found") ErrLinkNotFound = errors.New("link not found")
) )
func makeVethPair(name, peer string, mtu int, mac string) (netlink.Link, error) { // makeVethPair is called from within the container's network namespace
func makeVethPair(name, peer string, mtu int, mac string, hostNS ns.NetNS) (netlink.Link, error) {
veth := &netlink.Veth{ veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{ LinkAttrs: netlink.LinkAttrs{
Name: name, Name: name,
Flags: net.FlagUp, Flags: net.FlagUp,
MTU: mtu, MTU: mtu,
}, },
PeerName: peer, PeerName: peer,
PeerNamespace: netlink.NsFd(int(hostNS.Fd())),
} }
if mac != "" { if mac != "" {
m, err := net.ParseMAC(mac) m, err := net.ParseMAC(mac)
@ -51,7 +53,7 @@ func makeVethPair(name, peer string, mtu int, mac string) (netlink.Link, error)
if err := netlink.LinkAdd(veth); err != nil { if err := netlink.LinkAdd(veth); err != nil {
return nil, err return nil, err
} }
// Re-fetch the link to get its creation-time parameters, e.g. index and mac // Re-fetch the container link to get its creation-time parameters, e.g. index and mac
veth2, err := netlink.LinkByName(name) veth2, err := netlink.LinkByName(name)
if err != nil { if err != nil {
netlink.LinkDel(veth) // try and clean up the link if possible. netlink.LinkDel(veth) // try and clean up the link if possible.
@ -68,7 +70,7 @@ func peerExists(name string) bool {
return true return true
} }
func makeVeth(name, vethPeerName string, mtu int, mac string) (peerName string, veth netlink.Link, err error) { func makeVeth(name, vethPeerName string, mtu int, mac string, hostNS ns.NetNS) (peerName string, veth netlink.Link, err error) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
if vethPeerName != "" { if vethPeerName != "" {
peerName = vethPeerName peerName = vethPeerName
@ -79,7 +81,7 @@ func makeVeth(name, vethPeerName string, mtu int, mac string) (peerName string,
} }
} }
veth, err = makeVethPair(name, peerName, mtu, mac) veth, err = makeVethPair(name, peerName, mtu, mac, hostNS)
switch { switch {
case err == nil: case err == nil:
return return
@ -139,7 +141,7 @@ func ifaceFromNetlinkLink(l netlink.Link) net.Interface {
// hostVethName: If hostVethName is not specified, the host-side veth name will use a random string. // hostVethName: If hostVethName is not specified, the host-side veth name will use a random string.
// On success, SetupVethWithName returns (hostVeth, containerVeth, nil) // On success, SetupVethWithName returns (hostVeth, containerVeth, nil)
func SetupVethWithName(contVethName, hostVethName string, mtu int, contVethMac string, hostNS ns.NetNS) (net.Interface, net.Interface, error) { func SetupVethWithName(contVethName, hostVethName string, mtu int, contVethMac string, hostNS ns.NetNS) (net.Interface, net.Interface, error) {
hostVethName, contVeth, err := makeVeth(contVethName, hostVethName, mtu, contVethMac) hostVethName, contVeth, err := makeVeth(contVethName, hostVethName, mtu, contVethMac, hostNS)
if err != nil { if err != nil {
return net.Interface{}, net.Interface{}, err return net.Interface{}, net.Interface{}, err
} }
@ -148,15 +150,7 @@ func SetupVethWithName(contVethName, hostVethName string, mtu int, contVethMac s
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to set %q up: %v", contVethName, err) return net.Interface{}, net.Interface{}, fmt.Errorf("failed to set %q up: %v", contVethName, err)
} }
hostVeth, err := netlink.LinkByName(hostVethName) var hostVeth netlink.Link
if err != nil {
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
}
if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
return net.Interface{}, net.Interface{}, fmt.Errorf("failed to move veth to host netns: %v", err)
}
err = hostNS.Do(func(_ ns.NetNS) error { err = hostNS.Do(func(_ ns.NetNS) error {
hostVeth, err = netlink.LinkByName(hostVethName) hostVeth, err = netlink.LinkByName(hostVethName)
if err != nil { if err != nil {

View File

@ -188,8 +188,8 @@ var _ = Describe("Link", func() {
_ = containerNetNS.Do(func(ns.NetNS) error { _ = containerNetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover() defer GinkgoRecover()
_, _, err := ip.SetupVeth(containerVethName, mtu, "", hostNetNS) _, _, err := ip.SetupVeth(containerVethName, mtu, "", hostNetNS)
Expect(err.Error()).To(HavePrefix("failed to move veth to host netns: ")) Expect(err.Error()).To(HavePrefix("container veth name provided"))
Expect(err.Error()).To(HaveSuffix("already exists"))
return nil return nil
}) })
}) })