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:
parent
f14ff6687a
commit
a49f908168
@ -32,7 +32,8 @@ 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,
|
||||||
@ -40,6 +41,7 @@ func makeVethPair(name, peer string, mtu int, mac string) (netlink.Link, error)
|
|||||||
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 {
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user