diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 34f9c4139..41a215bec 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -31,8 +31,9 @@ var ( ) const ( - totalVfFile = "sriov_totalvfs" - configuredVfFile = "sriov_numvfs" + totalVfFile = "sriov_totalvfs" + configuredVfFile = "sriov_numvfs" + eswitchModeSwitchdev = "switchdev" ) // DetectPluginWatchMode returns true if plugins registry directory exist @@ -76,7 +77,21 @@ func GetPfName(pciAddr string) (string, error) { } return "", err } else if len(files) > 0 { + pfEswitchMode, err := GetPfEswitchMode(pciAddr) + if err != nil { + return "", err + } + if pfEswitchMode == eswitchModeSwitchdev { + name, err := GetSriovnetProvider().GetUplinkRepresentor(pciAddr) + + if err != nil { + return "", err + } + + return name, nil + } return files[0].Name(), nil + } return "", fmt.Errorf("the PF name is not found for device %s", pciAddr) } @@ -393,3 +408,17 @@ func GetVFID(pciAddr string) (vfID int, err error) { vfID = -1 return vfID, nil } + +// GetPfEswitchMode returns PF's eswitch mode for the given VF +// If device is not VF then it will return its own eswitch mode +func GetPfEswitchMode(pciAddr string) (string, error) { + pfAddr, err := GetPfAddr(pciAddr) + if err != nil { + return "", fmt.Errorf("error getting PF eswitch mode for PCI device %s %v", pciAddr, err) + } + devLinkDeviceAttrs, err := GetNetlinkProvider().GetDevLinkDeviceEswitchAttrs(pfAddr) + if err != nil { + return "", err + } + return devLinkDeviceAttrs.Mode, nil +} diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index 45dfca867..7cf51034d 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -4,6 +4,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" + "github.com/stretchr/testify/mock" + nl "github.com/vishvananda/netlink" + + mocks "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils/mocks" ) func assertShouldFail(err error, shouldFail bool) { @@ -396,35 +400,68 @@ var _ = Describe("In the utils package", func() { ) DescribeTable("getting PF names", - func(fs *FakeFilesystem, device string, expected string, shouldFail bool) { + func(fs *FakeFilesystem, eswitchMode string, device string, expected string, shouldFail bool) { + fakeNetlinkProvider := mocks.NetlinkProvider{} + fakeNetlinkProvider. + On("GetDevLinkDeviceEswitchAttrs", mock.AnythingOfType("string")). + Return(&nl.DevlinkDevEswitchAttr{Mode: eswitchMode}, nil) + SetNetlinkProviderInst(&fakeNetlinkProvider) + + fakeSriovnetProvider := mocks.SriovnetProvider{} + fakeSriovnetProvider. + On("GetUplinkRepresentor", "0000:01:10.0"). + Return("fakeSwitchdevPF", nil) + SetSriovnetProviderInst(&fakeSriovnetProvider) + defer fs.Use()() actual, err := GetPfName(device) Expect(actual).To(Equal(expected)) assertShouldFail(err, shouldFail) }, - Entry("device doesn't exist", &FakeFilesystem{}, "0000:01:10.0", nil, true), + Entry("device doesn't exist", &FakeFilesystem{}, "fake", "0000:01:10.0", nil, true), Entry("device is a VF and interface name exists", - &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/physfn/net/fakePF"}}, - "0000:01:10.0", "fakePF", false, + &FakeFilesystem{ + Dirs: []string{ + "sys/bus/pci/devices/0000:01:10.0", + "sys/bus/pci/devices/0000:01:00.0/net/fakePF", + }, + Symlinks: map[string]string{ + "sys/bus/pci/devices/0000:01:10.0/physfn/": "../0000:01:00.0", + }, + }, + "fake", "0000:01:10.0", "fakePF", false, ), Entry("device is a VF and interface name does not exist", &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/physfn/net/"}}, - "0000:01:10.0", "", true, + "fake", "0000:01:10.0", "", true, ), Entry("device is a PF and interface name exists", &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/net/fakeIF"}}, - "0000:01:10.0", "fakeIF", false, + "fake", "0000:01:10.0", "fakeIF", false, ), Entry("device is a PF interface name does not exist", &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/net/fakeIF"}}, - "0000:01:10.0", "fakeIF", false, + "fake", "0000:01:10.0", "fakeIF", false, ), Entry("net is not a directory at all", &FakeFilesystem{ Dirs: []string{"sys/bus/pci/devices/0000:01:10.0"}, Files: map[string][]byte{"sys/bus/pci/devices/0000:01:10.0/net": []byte("junk")}, }, - "0000:01:10.0", "", true, + "fake", "0000:01:10.0", "", true, + ), + Entry("device is a VF and PF is in switchdev mode", + &FakeFilesystem{ + Dirs: []string{ + "sys/bus/pci/devices/0000:01:10.0", + "sys/bus/pci/devices/0000:01:00.0/net/fakePF", + "sys/bus/pci/devices/0000:01:00.0/net/fakeVF", + }, + Symlinks: map[string]string{ + "sys/bus/pci/devices/0000:01:10.0/physfn/": "../0000:01:00.0", + }, + }, + "switchdev", "0000:01:10.0", "fakeSwitchdevPF", false, ), )