Skip to content

Commit

Permalink
Support VF self Management
Browse files Browse the repository at this point in the history
  • Loading branch information
hustcat authored and rkamudhan committed May 9, 2017
1 parent 184aa51 commit 73f3ce1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ options ixgbe max_vfs=8,8

## Extra arguments

* `vf` (int, optional): VF index, default value is 0
* `vf` (int, optional): VF index. This plugin will allocate a free VF if not assigned
* `vlan` (int, optional): VLAN ID for VF device
* `mac` (string, optional): mac address for VF device

Expand Down
94 changes: 77 additions & 17 deletions sriov/sriov.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net"
"os"
"runtime"
"strconv"
"strings"

"github.com/containernetworking/cni/pkg/ipam"
"github.com/containernetworking/cni/pkg/ns"
Expand All @@ -24,36 +26,33 @@ func init() {
}

func setupVF(conf *SriovConf, ifName string, netns ns.NetNS) error {
var (
err error
vfDevName string
)

vfIdx := 0
masterName := conf.Net.Master
args := conf.Args

if args.VF != 0 {
vfIdx = int(args.VF)
vfDevName, err = getVFDeviceName(masterName, vfIdx)
if err != nil {
return err
}
} else {
// alloc a free virtual function
if vfIdx, vfDevName, err = allocFreeVF(masterName); err != nil {
return err
}
}
// TODO: if conf.VF == nil, alloc vf randomly

m, err := netlink.LinkByName(masterName)
if err != nil {
return fmt.Errorf("failed to lookup master %q: %v", masterName, err)
}

vfDir := fmt.Sprintf("/sys/class/net/%s/device/virtfn%d/net", masterName, vfIdx)
if _, err := os.Lstat(vfDir); err != nil {
return err
}

infos, err := ioutil.ReadDir(vfDir)
if err != nil {
return err
}

if len(infos) != 1 {
return fmt.Errorf("no network devices in directory %s", vfDir)
}

// VF NIC name
vfDevName := infos[0].Name()
vfDev, err := netlink.LinkByName(vfDevName)
if err != nil {
return fmt.Errorf("failed to lookup vf device %q: %v", vfDevName, err)
Expand Down Expand Up @@ -202,6 +201,67 @@ func renameLink(curName, newName string) error {
return netlink.LinkSetName(link, newName)
}

func allocFreeVF(master string) (int, string, error) {
vfIdx := -1
devName := ""

sriovFile := fmt.Sprintf("/sys/class/net/%s/device/sriov_numvfs", master)
if _, err := os.Lstat(sriovFile); err != nil {
return -1, "", fmt.Errorf("failed to open the sriov_numfs of device %q: %v", master, err)
}

data, err := ioutil.ReadFile(sriovFile)
if err != nil {
return -1, "", fmt.Errorf("failed to read the sriov_numfs of device %q: %v", master, err)
}

if len(data) == 0 {
return -1, "", fmt.Errorf("no data in the file %q", sriovFile)
}

sriovNumfs := strings.TrimSpace(string(data))
vfTotal, err := strconv.Atoi(sriovNumfs)
if err != nil {
return -1, "", fmt.Errorf("failed to convert sriov_numfs(byte value) to int of device %q: %v", master, err)
}

if vfTotal <= 0 {
return -1, "", fmt.Errorf("no virtual function in the device %q: %v", master)
}

for vf := 0; vf < vfTotal; vf++ {
devName, err = getVFDeviceName(master, vf)

// got a free vf
if err == nil {
vfIdx = vf
break
}
}

if vfIdx == -1 {
return -1, "", fmt.Errorf("can not get a free virtual function in directory %s", master)
}
return vfIdx, devName, nil
}

func getVFDeviceName(master string, vf int) (string, error) {
vfDir := fmt.Sprintf("/sys/class/net/%s/device/virtfn%d/net", master, vf)
if _, err := os.Lstat(vfDir); err != nil {
return "", fmt.Errorf("failed to open the virtfn%d dir of the device %q: %v", vf, master, err)
}

infos, err := ioutil.ReadDir(vfDir)
if err != nil {
return "", fmt.Errorf("failed to read the virtfn%d dir of the device %q: %v", vf, master, err)
}

if len(infos) != 1 {
return "", fmt.Errorf("no network device in directory %s", vfDir)
}
return infos[0].Name(), nil
}

func main() {
skel.PluginMain(cmdAdd, cmdDel)
}

0 comments on commit 73f3ce1

Please sign in to comment.