github.com/k8snetworkplumbingwg/sriov-network-operator@v1.2.1-0.20240408194816-2d2e5a45d453/pkg/host/internal/sriov/sriov_test.go (about)

     1  package sriov
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strconv"
     7  	"syscall"
     8  
     9  	"github.com/golang/mock/gomock"
    10  	"github.com/vishvananda/netlink"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  
    15  	sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
    16  	dputilsMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/dputils/mock"
    17  	netlinkMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink/mock"
    18  	hostMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/mock"
    19  	hostStoreMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store/mock"
    20  	"github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types"
    21  	"github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem"
    22  	"github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/helpers"
    23  )
    24  
    25  var _ = Describe("SRIOV", func() {
    26  	var (
    27  		s                types.SriovInterface
    28  		netlinkLibMock   *netlinkMockPkg.MockNetlinkLib
    29  		dputilsLibMock   *dputilsMockPkg.MockDPUtilsLib
    30  		hostMock         *hostMockPkg.MockHostManagerInterface
    31  		storeManagerMode *hostStoreMockPkg.MockManagerInterface
    32  
    33  		testCtrl *gomock.Controller
    34  
    35  		testError = fmt.Errorf("test")
    36  	)
    37  	BeforeEach(func() {
    38  		testCtrl = gomock.NewController(GinkgoT())
    39  		netlinkLibMock = netlinkMockPkg.NewMockNetlinkLib(testCtrl)
    40  		dputilsLibMock = dputilsMockPkg.NewMockDPUtilsLib(testCtrl)
    41  		hostMock = hostMockPkg.NewMockHostManagerInterface(testCtrl)
    42  		storeManagerMode = hostStoreMockPkg.NewMockManagerInterface(testCtrl)
    43  
    44  		s = New(nil, hostMock, hostMock, hostMock, hostMock, netlinkLibMock, dputilsLibMock)
    45  	})
    46  
    47  	AfterEach(func() {
    48  		testCtrl.Finish()
    49  	})
    50  
    51  	Context("SetSriovNumVfs", func() {
    52  		It("set", func() {
    53  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
    54  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
    55  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
    56  			})
    57  			Expect(s.SetSriovNumVfs("0000:d8:00.0", 5)).NotTo(HaveOccurred())
    58  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", strconv.Itoa(5))
    59  		})
    60  		It("fail - no such device", func() {
    61  			Expect(s.SetSriovNumVfs("0000:d8:00.0", 5)).To(HaveOccurred())
    62  		})
    63  	})
    64  
    65  	Context("GetNicSriovMode", func() {
    66  		It("devlink returns info", func() {
    67  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
    68  				&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "switchdev"}}},
    69  				nil)
    70  			mode := s.GetNicSriovMode("0000:d8:00.0")
    71  			Expect(mode).To(Equal("switchdev"))
    72  		})
    73  		It("devlink returns error", func() {
    74  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError)
    75  			mode := s.GetNicSriovMode("0000:d8:00.0")
    76  
    77  			Expect(mode).To(Equal("legacy"))
    78  		})
    79  		It("devlink not supported - fail to get name", func() {
    80  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, syscall.ENODEV)
    81  			mode := s.GetNicSriovMode("0000:d8:00.0")
    82  			Expect(mode).To(Equal("legacy"))
    83  		})
    84  	})
    85  
    86  	Context("SetNicSriovMode", func() {
    87  		It("set", func() {
    88  			testDev := &netlink.DevlinkDevice{}
    89  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil)
    90  			netlinkLibMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(nil)
    91  			Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).NotTo(HaveOccurred())
    92  		})
    93  		It("fail to get dev", func() {
    94  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError)
    95  			Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError))
    96  		})
    97  		It("fail to set mode", func() {
    98  			testDev := &netlink.DevlinkDevice{}
    99  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil)
   100  			netlinkLibMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(testError)
   101  			Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError))
   102  		})
   103  	})
   104  
   105  	Context("ConfigSriovInterfaces", func() {
   106  		It("should configure", func() {
   107  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
   108  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
   109  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
   110  			})
   111  
   112  			dputilsLibMock.EXPECT().GetSriovVFcapacity("0000:d8:00.0").Return(2)
   113  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
   114  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{
   115  				Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}}, nil)
   116  			hostMock.EXPECT().RemoveDisableNMUdevRule("0000:d8:00.0").Return(nil)
   117  			hostMock.EXPECT().RemovePersistPFNameUdevRule("0000:d8:00.0").Return(nil)
   118  			hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
   119  			hostMock.EXPECT().AddDisableNMUdevRule("0000:d8:00.0").Return(nil)
   120  			dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2", "0000:d8:00.3"}, nil)
   121  			pfLinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   122  			netlinkLibMock.EXPECT().LinkByName("enp216s0f0np0").Return(pfLinkMock, nil).Times(3)
   123  			pfLinkMock.EXPECT().Attrs().Return(&netlink.LinkAttrs{OperState: netlink.OperDown, EncapType: "ether"}).Times(2)
   124  			netlinkLibMock.EXPECT().LinkSetUp(pfLinkMock).Return(nil)
   125  
   126  			dputilsLibMock.EXPECT().GetVFID("0000:d8:00.2").Return(0, nil).Times(2)
   127  			hostMock.EXPECT().HasDriver("0000:d8:00.2").Return(false, "")
   128  			hostMock.EXPECT().BindDefaultDriver("0000:d8:00.2").Return(nil)
   129  			hostMock.EXPECT().HasDriver("0000:d8:00.2").Return(true, "test")
   130  			hostMock.EXPECT().UnbindDriverIfNeeded("0000:d8:00.2", true).Return(nil)
   131  			hostMock.EXPECT().BindDefaultDriver("0000:d8:00.2").Return(nil)
   132  			hostMock.EXPECT().SetNetdevMTU("0000:d8:00.2", 2000).Return(nil)
   133  			hostMock.EXPECT().TryGetInterfaceName("0000:d8:00.2").Return("enp216s0f0_0")
   134  			vf0LinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   135  			vf0Mac, _ := net.ParseMAC("02:42:19:51:2f:af")
   136  			vf0LinkMock.EXPECT().Attrs().Return(&netlink.LinkAttrs{HardwareAddr: vf0Mac})
   137  			netlinkLibMock.EXPECT().LinkByName("enp216s0f0_0").Return(vf0LinkMock, nil)
   138  			netlinkLibMock.EXPECT().LinkSetVfHardwareAddr(vf0LinkMock, 0, vf0Mac).Return(nil)
   139  
   140  			dputilsLibMock.EXPECT().GetVFID("0000:d8:00.3").Return(1, nil)
   141  			hostMock.EXPECT().HasDriver("0000:d8:00.3").Return(true, "vfio-pci").Times(2)
   142  			hostMock.EXPECT().UnbindDriverIfNeeded("0000:d8:00.3", false).Return(nil)
   143  			hostMock.EXPECT().BindDpdkDriver("0000:d8:00.3", "vfio-pci").Return(nil)
   144  
   145  			storeManagerMode.EXPECT().SaveLastPfAppliedStatus(gomock.Any()).Return(nil)
   146  
   147  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   148  				[]sriovnetworkv1.Interface{{
   149  					Name:       "enp216s0f0np0",
   150  					PciAddress: "0000:d8:00.0",
   151  					NumVfs:     2,
   152  					VfGroups: []sriovnetworkv1.VfGroup{
   153  						{
   154  							VfRange:      "0-0",
   155  							ResourceName: "test-resource0",
   156  							PolicyName:   "test-policy0",
   157  							Mtu:          2000,
   158  							IsRdma:       true,
   159  						},
   160  						{
   161  							VfRange:      "1-1",
   162  							ResourceName: "test-resource1",
   163  							PolicyName:   "test-policy1",
   164  							Mtu:          1600,
   165  							IsRdma:       false,
   166  							DeviceType:   "vfio-pci",
   167  						}},
   168  				}},
   169  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}, {PciAddress: "0000:d8:00.1"}},
   170  				false)).NotTo(HaveOccurred())
   171  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", "2")
   172  		})
   173  		It("should configure IB", func() {
   174  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
   175  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
   176  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
   177  			})
   178  
   179  			dputilsLibMock.EXPECT().GetSriovVFcapacity("0000:d8:00.0").Return(1)
   180  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
   181  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{
   182  				Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}}, nil)
   183  			hostMock.EXPECT().RemoveDisableNMUdevRule("0000:d8:00.0").Return(nil)
   184  			hostMock.EXPECT().RemovePersistPFNameUdevRule("0000:d8:00.0").Return(nil)
   185  			hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
   186  			hostMock.EXPECT().AddDisableNMUdevRule("0000:d8:00.0").Return(nil)
   187  			dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2"}, nil)
   188  			pfLinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   189  			netlinkLibMock.EXPECT().LinkByName("enp216s0f0np0").Return(pfLinkMock, nil).Times(2)
   190  			pfLinkMock.EXPECT().Attrs().Return(&netlink.LinkAttrs{OperState: netlink.OperDown})
   191  			netlinkLibMock.EXPECT().LinkSetUp(pfLinkMock).Return(nil)
   192  
   193  			dputilsLibMock.EXPECT().GetVFID("0000:d8:00.2").Return(0, nil).Times(2)
   194  			hostMock.EXPECT().Unbind("0000:d8:00.2").Return(nil)
   195  			hostMock.EXPECT().HasDriver("0000:d8:00.2").Return(true, "test").Times(2)
   196  			hostMock.EXPECT().UnbindDriverIfNeeded("0000:d8:00.2", true).Return(nil)
   197  			hostMock.EXPECT().BindDefaultDriver("0000:d8:00.2").Return(nil)
   198  			hostMock.EXPECT().SetNetdevMTU("0000:d8:00.2", 2000).Return(nil)
   199  			vf0LinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   200  			netlinkLibMock.EXPECT().LinkSetVfNodeGUID(vf0LinkMock, 0, gomock.Any()).Return(nil)
   201  			netlinkLibMock.EXPECT().LinkSetVfPortGUID(vf0LinkMock, 0, gomock.Any()).Return(nil)
   202  
   203  			storeManagerMode.EXPECT().SaveLastPfAppliedStatus(gomock.Any()).Return(nil)
   204  
   205  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   206  				[]sriovnetworkv1.Interface{{
   207  					Name:       "enp216s0f0np0",
   208  					PciAddress: "0000:d8:00.0",
   209  					NumVfs:     1,
   210  					LinkType:   "IB",
   211  					VfGroups: []sriovnetworkv1.VfGroup{
   212  						{
   213  							VfRange:      "0-0",
   214  							ResourceName: "test-resource0",
   215  							PolicyName:   "test-policy0",
   216  							Mtu:          2000,
   217  							IsRdma:       true,
   218  						}},
   219  				}},
   220  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}},
   221  				false)).NotTo(HaveOccurred())
   222  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", "1")
   223  		})
   224  
   225  		It("should configure switchdev", func() {
   226  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
   227  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
   228  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
   229  			})
   230  
   231  			dputilsLibMock.EXPECT().GetSriovVFcapacity("0000:d8:00.0").Return(1)
   232  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
   233  			hostMock.EXPECT().RemoveDisableNMUdevRule("0000:d8:00.0").Return(nil)
   234  			hostMock.EXPECT().RemovePersistPFNameUdevRule("0000:d8:00.0").Return(nil)
   235  			hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
   236  			hostMock.EXPECT().AddDisableNMUdevRule("0000:d8:00.0").Return(nil)
   237  			hostMock.EXPECT().AddPersistPFNameUdevRule("0000:d8:00.0", "enp216s0f0np0").Return(nil)
   238  			hostMock.EXPECT().EnableHwTcOffload("enp216s0f0np0").Return(nil)
   239  			hostMock.EXPECT().GetDevlinkDeviceParam("0000:d8:00.0", "flow_steering_mode").Return("", syscall.EINVAL)
   240  			dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2"}, nil).Times(2)
   241  			pfLinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   242  			netlinkLibMock.EXPECT().LinkByName("enp216s0f0np0").Return(pfLinkMock, nil).Times(2)
   243  			pfLinkMock.EXPECT().Attrs().Return(&netlink.LinkAttrs{OperState: netlink.OperDown})
   244  			netlinkLibMock.EXPECT().LinkSetUp(pfLinkMock).Return(nil)
   245  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{
   246  				Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}}, nil).Times(2)
   247  			netlinkLibMock.EXPECT().DevLinkSetEswitchMode(gomock.Any(), "switchdev").Return(nil)
   248  
   249  			dputilsLibMock.EXPECT().GetVFID("0000:d8:00.2").Return(0, nil).Times(2)
   250  			hostMock.EXPECT().Unbind("0000:d8:00.2").Return(nil)
   251  			hostMock.EXPECT().HasDriver("0000:d8:00.2").Return(false, "")
   252  			hostMock.EXPECT().BindDefaultDriver("0000:d8:00.2").Return(nil)
   253  			hostMock.EXPECT().HasDriver("0000:d8:00.2").Return(true, "test")
   254  			hostMock.EXPECT().UnbindDriverIfNeeded("0000:d8:00.2", true).Return(nil)
   255  			hostMock.EXPECT().BindDefaultDriver("0000:d8:00.2").Return(nil)
   256  			hostMock.EXPECT().SetNetdevMTU("0000:d8:00.2", 2000).Return(nil)
   257  			hostMock.EXPECT().TryGetInterfaceName("0000:d8:00.2").Return("enp216s0f0_0")
   258  			vf0LinkMock := netlinkMockPkg.NewMockLink(testCtrl)
   259  			vf0Mac, _ := net.ParseMAC("02:42:19:51:2f:af")
   260  			vf0LinkMock.EXPECT().Attrs().Return(&netlink.LinkAttrs{HardwareAddr: vf0Mac})
   261  			netlinkLibMock.EXPECT().LinkByName("enp216s0f0_0").Return(vf0LinkMock, nil)
   262  			netlinkLibMock.EXPECT().LinkSetVfHardwareAddr(vf0LinkMock, 0, vf0Mac).Return(nil)
   263  			hostMock.EXPECT().GetPhysPortName("enp216s0f0np0").Return("p0", nil)
   264  			hostMock.EXPECT().GetPhysSwitchID("enp216s0f0np0").Return("7cfe90ff2cc0", nil)
   265  			hostMock.EXPECT().AddVfRepresentorUdevRule("0000:d8:00.0", "enp216s0f0np0", "7cfe90ff2cc0", "p0").Return(nil)
   266  			hostMock.EXPECT().CreateVDPADevice("0000:d8:00.2", "vhost_vdpa")
   267  			hostMock.EXPECT().LoadUdevRules().Return(nil)
   268  
   269  			storeManagerMode.EXPECT().SaveLastPfAppliedStatus(gomock.Any()).Return(nil)
   270  
   271  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   272  				[]sriovnetworkv1.Interface{{
   273  					Name:        "enp216s0f0np0",
   274  					PciAddress:  "0000:d8:00.0",
   275  					NumVfs:      1,
   276  					LinkType:    "ETH",
   277  					EswitchMode: "switchdev",
   278  					VfGroups: []sriovnetworkv1.VfGroup{
   279  						{
   280  							VfRange:      "0-0",
   281  							ResourceName: "test-resource0",
   282  							PolicyName:   "test-policy0",
   283  							Mtu:          2000,
   284  							IsRdma:       true,
   285  							VdpaType:     "vhost_vdpa",
   286  						}},
   287  				}},
   288  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}},
   289  				false)).NotTo(HaveOccurred())
   290  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", "1")
   291  		})
   292  
   293  		It("externally managed - wrong VF count", func() {
   294  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
   295  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   296  				[]sriovnetworkv1.Interface{{
   297  					Name:              "enp216s0f0np0",
   298  					PciAddress:        "0000:d8:00.0",
   299  					NumVfs:            1,
   300  					ExternallyManaged: true,
   301  					VfGroups: []sriovnetworkv1.VfGroup{
   302  						{
   303  							VfRange:      "0-0",
   304  							ResourceName: "test-resource0",
   305  							PolicyName:   "test-policy0",
   306  							Mtu:          2000,
   307  							IsRdma:       true,
   308  						}},
   309  				}},
   310  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}},
   311  				false)).To(HaveOccurred())
   312  		})
   313  
   314  		It("externally managed - wrong MTU", func() {
   315  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(1)
   316  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
   317  				&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}},
   318  				nil)
   319  			hostMock.EXPECT().GetNetdevMTU("0000:d8:00.0")
   320  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   321  				[]sriovnetworkv1.Interface{{
   322  					Name:              "enp216s0f0np0",
   323  					PciAddress:        "0000:d8:00.0",
   324  					NumVfs:            1,
   325  					Mtu:               2000,
   326  					ExternallyManaged: true,
   327  					VfGroups: []sriovnetworkv1.VfGroup{
   328  						{
   329  							VfRange:      "0-0",
   330  							ResourceName: "test-resource0",
   331  							PolicyName:   "test-policy0",
   332  							IsRdma:       true,
   333  						}},
   334  				}},
   335  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}},
   336  				false)).To(HaveOccurred())
   337  		})
   338  
   339  		It("reset device", func() {
   340  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
   341  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
   342  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
   343  			})
   344  
   345  			storeManagerMode.EXPECT().LoadPfsStatus("0000:d8:00.0").Return(&sriovnetworkv1.Interface{
   346  				Name:       "enp216s0f0np0",
   347  				PciAddress: "0000:d8:00.0",
   348  				NumVfs:     2,
   349  			}, true, nil)
   350  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
   351  				&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}},
   352  				nil)
   353  			hostMock.EXPECT().RemoveDisableNMUdevRule("0000:d8:00.0").Return(nil)
   354  			hostMock.EXPECT().RemovePersistPFNameUdevRule("0000:d8:00.0").Return(nil)
   355  			hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
   356  			hostMock.EXPECT().SetNetdevMTU("0000:d8:00.0", 1500).Return(nil)
   357  
   358  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   359  				[]sriovnetworkv1.Interface{},
   360  				[]sriovnetworkv1.InterfaceExt{
   361  					{
   362  						Name:       "enp216s0f0np0",
   363  						PciAddress: "0000:d8:00.0",
   364  						LinkType:   "ETH",
   365  						NumVfs:     2,
   366  						TotalVfs:   2,
   367  					}}, false)).NotTo(HaveOccurred())
   368  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", "0")
   369  		})
   370  		It("reset device - skip external", func() {
   371  			storeManagerMode.EXPECT().LoadPfsStatus("0000:d8:00.0").Return(&sriovnetworkv1.Interface{
   372  				Name:              "enp216s0f0np0",
   373  				PciAddress:        "0000:d8:00.0",
   374  				NumVfs:            2,
   375  				ExternallyManaged: true,
   376  			}, true, nil)
   377  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   378  				[]sriovnetworkv1.Interface{},
   379  				[]sriovnetworkv1.InterfaceExt{
   380  					{
   381  						Name:       "enp216s0f0np0",
   382  						PciAddress: "0000:d8:00.0",
   383  						NumVfs:     2,
   384  						TotalVfs:   2,
   385  					}}, false)).NotTo(HaveOccurred())
   386  		})
   387  		It("should configure - skipVFConfiguration is true", func() {
   388  			helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{
   389  				Dirs:  []string{"/sys/bus/pci/devices/0000:d8:00.0"},
   390  				Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}},
   391  			})
   392  
   393  			dputilsLibMock.EXPECT().GetSriovVFcapacity("0000:d8:00.0").Return(2)
   394  			dputilsLibMock.EXPECT().GetVFconfigured("0000:d8:00.0").Return(0)
   395  			netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(
   396  				&netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "legacy"}}},
   397  				nil)
   398  			hostMock.EXPECT().RemoveDisableNMUdevRule("0000:d8:00.0").Return(nil)
   399  			hostMock.EXPECT().RemovePersistPFNameUdevRule("0000:d8:00.0").Return(nil)
   400  			hostMock.EXPECT().RemoveVfRepresentorUdevRule("0000:d8:00.0").Return(nil)
   401  			hostMock.EXPECT().AddDisableNMUdevRule("0000:d8:00.0").Return(nil)
   402  			dputilsLibMock.EXPECT().GetVFList("0000:d8:00.0").Return([]string{"0000:d8:00.2", "0000:d8:00.3"}, nil)
   403  			hostMock.EXPECT().Unbind("0000:d8:00.2").Return(nil)
   404  			hostMock.EXPECT().Unbind("0000:d8:00.3").Return(nil)
   405  
   406  			storeManagerMode.EXPECT().SaveLastPfAppliedStatus(gomock.Any()).Return(nil)
   407  
   408  			Expect(s.ConfigSriovInterfaces(storeManagerMode,
   409  				[]sriovnetworkv1.Interface{{
   410  					Name:       "enp216s0f0np0",
   411  					PciAddress: "0000:d8:00.0",
   412  					NumVfs:     2,
   413  					VfGroups: []sriovnetworkv1.VfGroup{
   414  						{
   415  							VfRange:      "0-0",
   416  							ResourceName: "test-resource0",
   417  							PolicyName:   "test-policy0",
   418  							Mtu:          2000,
   419  							IsRdma:       true,
   420  						},
   421  						{
   422  							VfRange:      "1-1",
   423  							ResourceName: "test-resource1",
   424  							PolicyName:   "test-policy1",
   425  							Mtu:          1600,
   426  							IsRdma:       false,
   427  							DeviceType:   "vfio-pci",
   428  						}},
   429  				}},
   430  				[]sriovnetworkv1.InterfaceExt{{PciAddress: "0000:d8:00.0"}},
   431  				true)).NotTo(HaveOccurred())
   432  			helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", "2")
   433  		})
   434  	})
   435  })