forked from jaypipes/ghw
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support to report SRIOV devices. Much like GPU devices, support is added using a new top-level package. SRIOV devices are either Physical Functions or Virtual functions. The preferred representation for ghw is Physical Functions, whose dependent devices will be Virtual Functions; however, for the sake of practicality, the API also exposes soft references to Virtual Functions, so consumers of the API can access them directly and not navigating the parent devices. This patch also adds support in `ghwc`, to report the sriov information, and in the `snapshot` package, to make sure to capture all the files in sysfs that ghw cares about. Last but not least, lacking access to suitable non-linux systems, support is provided only on linux OS, even though the API tries hard not to be linux-specific. Resolves: jaypipes#92 Signed-off-by: Francesco Romani <[email protected]>
- Loading branch information
Showing
13 changed files
with
545 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// Use and distribution licensed under the Apache license version 2. | ||
// | ||
// See the COPYING file in the root project directory for full text. | ||
// | ||
|
||
package commands | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/jaypipes/ghw" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// sriovCmd represents the listing command | ||
var sriovCmd = &cobra.Command{ | ||
Use: "sriov", | ||
Short: "Show SRIOV devices information for the host system", | ||
RunE: showSRIOV, | ||
} | ||
|
||
// showSRIOV show SRIOV physical device information for the host system. | ||
func showSRIOV(cmd *cobra.Command, args []string) error { | ||
sriov, err := ghw.SRIOV() | ||
if err != nil { | ||
return errors.Wrap(err, "error getting SRIOV info") | ||
} | ||
|
||
switch outputFormat { | ||
case outputFormatHuman: | ||
fmt.Printf("%v\n", sriov) | ||
|
||
for _, dev := range sriov.PhysicalFunctions { | ||
fmt.Printf(" %v\n", dev) | ||
} | ||
case outputFormatJSON: | ||
fmt.Printf("%s\n", sriov.JSONString(pretty)) | ||
case outputFormatYAML: | ||
fmt.Printf("%s", sriov.YAMLString()) | ||
} | ||
return nil | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(sriovCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// | ||
// Use and distribution licensed under the Apache license version 2. | ||
// | ||
// See the COPYING file in the root project directory for full text. | ||
// | ||
|
||
package pci | ||
|
||
// Function describes an SR-IOV physical or virtual function. Physical functions | ||
// will have no Parent Function struct pointer and will have one or more Function | ||
// structs in the Functions field. | ||
type Function struct { | ||
Device // All Functions are PCI Devices | ||
// Parent contains a pointer to the parent physical function. | ||
// Will be empty when this is a physical function | ||
Parent *Function `json:"parent,omitempty"` | ||
// MaxVFs contains the maximum number of supported virtual | ||
// functions for this physical function | ||
MaxVFs int `json:"max_vfs"` | ||
// Functions contains the physical function's virtual functions | ||
Functions []*Function `json:"functions"` | ||
} | ||
|
||
// IsPhysical returns true if the PCIe function is a physical function, false | ||
// if it is a virtual function | ||
func (f *Function) IsPhysical() bool { | ||
return f.Parent == nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Use and distribution licensed under the Apache license version 2. | ||
// | ||
// See the COPYING file in the root project directory for full text. | ||
// | ||
|
||
package pci | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/jaypipes/ghw/pkg/context" | ||
"github.com/jaypipes/ghw/pkg/linuxpath" | ||
pciaddress "github.com/jaypipes/ghw/pkg/pci/address" | ||
"github.com/jaypipes/ghw/pkg/util" | ||
) | ||
|
||
func (info *Info) scanDevice(dev *pci.Device) error { | ||
paths := linuxpath.New(info.ctx) | ||
devPath := filepath.Join(paths.SysBusPciDevices, dev.Address) | ||
|
||
buf, err := ioutil.ReadFile(filepath.Join(devPath, "sriov_totalvfs")) | ||
if err != nil { | ||
// is not a physfn. Since we will fill virtfn from physfn, we can give up now | ||
return nil | ||
} | ||
|
||
maxVFs, err := strconv.Atoi(strings.TrimSpace(string(buf))) | ||
if err != nil { | ||
info.ctx.Warn("error reading sriov_totalvfn for %q: %v", devPath, err) | ||
return nil | ||
} | ||
|
||
virtFNs := findVFsFromPF(info, info, dev.Address, devPath) | ||
physFN := PhysicalFunction{ | ||
Device: info.newDevice(dev, devPath), | ||
MaxVFNum: maxVFs, | ||
VFs: virtFNs, | ||
} | ||
|
||
info.PhysicalFunctions = append(info.PhysicalFunctions, &physFN) | ||
for idx := 0; idx < len(virtFNs); idx++ { | ||
info.VirtualFunctions = append(info.VirtualFunctions, &virtFNs[idx]) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func findVFsFromPF(info *Info, pciInfo *pci.Info, parentAddr, parentPath string) []VirtualFunction { | ||
numVfs := util.SafeIntFromFile(info.ctx, filepath.Join(parentPath, "sriov_numvfs")) | ||
if numVfs == -1 { | ||
return nil | ||
} | ||
|
||
var vfs []VirtualFunction | ||
for vfnIdx := 0; vfnIdx < numVfs; vfnIdx++ { | ||
virtFn := fmt.Sprintf("virtfn%d", vfnIdx) | ||
vfnDest, err := os.Readlink(filepath.Join(parentPath, virtFn)) | ||
if err != nil { | ||
info.ctx.Warn("error reading backing device for virtfn %q physfn %q: %v", virtFn, parentPath, err) | ||
return nil | ||
} | ||
|
||
vfnPath := filepath.Clean(filepath.Join(parentPath, vfnDest)) | ||
vfnAddr := filepath.Base(vfnDest) | ||
vfnDev := pciInfo.GetDevice(vfnAddr) | ||
if vfnDev == nil { | ||
info.ctx.Warn("error finding the PCI device for virtfn %s physfn %s", vfnAddr, parentAddr) | ||
return nil | ||
} | ||
|
||
vfs = append(vfs, VirtualFunction{ | ||
Device: info.newDevice(vfnDev, vfnPath), | ||
Index: vfnIdx, | ||
ParentAddress: pciaddress.FromString(parentAddr), | ||
}) | ||
} | ||
return vfs | ||
} | ||
|
||
func (info *Info) newDevice(dev *pci.Device, devPath string) Device { | ||
// see: https://doc.dpdk.org/guides/linux_gsg/linux_drivers.html | ||
return Device{ | ||
Address: pciaddress.FromString(dev.Address), | ||
Interfaces: findNetworkInterfaceNames(info.ctx, devPath), | ||
PCI: dev, | ||
} | ||
} | ||
|
||
func findNetworkInterfaceNames(ctx *context.Context, devPath string) []string { | ||
netPath := filepath.Join(devPath, "net") | ||
|
||
netEntries, err := ioutil.ReadDir(netPath) | ||
if err != nil { | ||
ctx.Warn("cannot enumerate network names for %q: %v", devPath, err) | ||
return nil | ||
} | ||
|
||
var networks []string | ||
for _, netEntry := range netEntries { | ||
networks = append(networks, netEntry.Name()) | ||
} | ||
|
||
return networks | ||
} |
Oops, something went wrong.