Skip to content

Commit

Permalink
sriov: Improve teardown of VFs
Browse files Browse the repository at this point in the history
Followup for #503
This commit covers third bullet point, providing recreated network
interface in container namespace ready to reconfigure with original IPAM
configuration needed for later CNI DEL invocation.
  • Loading branch information
jellonek committed Dec 12, 2017
1 parent 7da06d8 commit 3f0bcb8
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 25 deletions.
79 changes: 54 additions & 25 deletions pkg/nettools/nettools.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"crypto/rand"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"os"
Expand Down Expand Up @@ -647,10 +648,28 @@ func getPCIAddressOfVF(devName string) (string, error) {
if linkDestination[:13] != "../../../0000" {
return "", fmt.Errorf("unknown address as device symlink: %q", linkDestination)
}
// we need pci address without leading "0000:"
// we need pci address without leading "../../../"
return linkDestination[9:], nil
}

func getDevNameByPCIAddress(address string) (string, error) {
desiredLinkLocation := "../../../" + address
devices, err := ioutil.ReadDir("/sys/class/net")
if err != nil {
return "", err
}
for _, fi := range devices {
linkDestination, err := os.Readlink(filepath.Join("/sys/class/net", fi.Name(), "device"))
if err != nil {
return "", err
}
if linkDestination == desiredLinkLocation {
return fi.Name(), nil
}
}
return "", fmt.Errorf("can not find network device with pci address %q", address)
}

func writeStringToFile(s, path string, mode os.FileMode) error {
f, err := os.OpenFile(path, os.O_WRONLY, mode)
if err != nil {
Expand Down Expand Up @@ -921,23 +940,6 @@ func ConfigureLink(link netlink.Link, info *cnicurrent.Result) error {
return nil
}

func renameLink(mac, name string) error {
links, err := netlink.LinkList()
if err != nil {
return err
}

for _, link := range links {
if link.Attrs().HardwareAddr.String() == mac {
if err := netlink.LinkSetName(link, name); err != nil {
return err
}
}
}

return fmt.Errorf("link with mac address %q not found, can't rename it to %q", mac, name)
}

// Teardown cleans up container network configuration.
// It does so by invoking teardown sequence which removes ebtables rules, links
// and addresses in an order opposite to that of their creation in SetupContainerSideNetwork.
Expand Down Expand Up @@ -994,13 +996,6 @@ func (csn *ContainerSideNetwork) Teardown() error {
if err := SetHardwareAddr(contLink, csn.HardwareAddrs[i]); err != nil {
return err
}
} else {
if err := rebindDriverToDevice(csn.PCIAddresses[i]); err != nil {
return err
}
if err := renameLink(csn.HardwareAddrs[i].String(), csn.InterfaceNames[i]); err != nil {
return err
}
}

rereadedLink, err := netlink.LinkByName(contLink.Attrs().Name)
Expand All @@ -1015,6 +1010,40 @@ func (csn *ContainerSideNetwork) Teardown() error {
return nil
}

// ReconstructVFs iterating over stored pci addresses rebinds each interface to it's host
// driver, changes mac address to stored one, then moves it to container namespace
// to original host kernel driver, updates it's mac address to saved one, changes it's name
// to stored one, than moves it to container namespace
func (csn *ContainerSideNetwork) ReconstructVFs(ns ns.NetNS) error {
for i, ifType := range csn.InterfaceTypes {
if ifType != InterfaceTypeVF {
continue
}
if err := rebindDriverToDevice(csn.PCIAddresses[i]); err != nil {
return err
}
devName, err := getDevNameByPCIAddress(csn.PCIAddresses[i])
if err != nil {
return err
}
link, err := netlink.LinkByName(devName)
if err != nil {
return err
}
if err := netlink.LinkSetHardwareAddr(link, csn.HardwareAddrs[i]); err != nil {
return err
}
if err := netlink.LinkSetName(link, csn.InterfaceNames[i]); err != nil {
return err
}
if err := netlink.LinkSetNsFd(link, int(ns.Fd())); err != nil {
return err
}
}

return nil
}

// copied from:
// https://github.com/coreos/rkt/blob/56564bac090b44788684040f2ffd66463f29d5d0/stage1/init/kvm/network.go#L71
func GenerateMacAddress() (net.HardwareAddr, error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/tapmanager/tapfdsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ func (s *TapFDSource) Release(key string) error {
return fmt.Errorf("failed to open network namespace at %q: %v", netNSPath, err)
}

if err := pn.csn.ReconstructVFs(vmNS); err != nil {
return fmt.Errorf("failed to reconstruct SR-IOV devices: %v", err)
}

if err := vmNS.Do(func(ns.NetNS) error {
if err := pn.dhcpServer.Close(); err != nil {
return fmt.Errorf("failed to stop dhcp server: %v", err)
Expand Down

0 comments on commit 3f0bcb8

Please sign in to comment.