ip: place veth peer in host namspace directly

Instead of moving the host side of the veth peer into the host
network namespace later, just create it in the host namespace
directly.

Signed-off-by: Dan Williams <dcbw@redhat.com>
This commit is contained in:
Dan Williams 2021-07-21 09:39:06 -05:00
parent f14ff6687a
commit a49f908168
2 changed files with 11 additions and 17 deletions

View File

@ -32,14 +32,16 @@ var (
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{
LinkAttrs: netlink.LinkAttrs{
Name: name,
Flags: net.FlagUp,
MTU: mtu,
},
PeerName: peer,
PeerName: peer,
PeerNamespace: netlink.NsFd(int(hostNS.Fd())),
}
if 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 {
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)
if err != nil {
netlink.LinkDel(veth) // try and clean up the link if possible.
@ -68,7 +70,7 @@ func peerExists(name string) bool {
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++ {
if 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 {
case err == nil:
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.
// On success, SetupVethWithName returns (hostVeth, containerVeth, nil)
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 {
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)
}
hostVeth, err := netlink.LinkByName(hostVethName)
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)
}
var hostVeth netlink.Link
err = hostNS.Do(func(_ ns.NetNS) error {
hostVeth, err = netlink.LinkByName(hostVethName)
if err != nil {

View File

@ -188,8 +188,8 @@ var _ = Describe("Link", func() {
_ = containerNetNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
_, _, 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
})
})