diff --git a/cmd/sriovdp/manager.go b/cmd/sriovdp/manager.go index 455f2c466..0fe0dc607 100644 --- a/cmd/sriovdp/manager.go +++ b/cmd/sriovdp/manager.go @@ -103,6 +103,7 @@ func (rm *resourceManager) readConfig() error { func (rm *resourceManager) initServers() error { rf := rm.rFactory glog.Infof("number of config: %d\n", len(rm.configList)) + deviceAllocated := make(map[string]bool) for _, rc := range rm.configList { // Create new ResourcePool glog.Infof("") @@ -123,12 +124,12 @@ func (rm *resourceManager) initServers() error { glog.Infof("no devices in device pool, skipping creating resource server for %s", rc.ResourceName) continue } + filteredDevices = rm.excludeAllocatedDevices(filteredDevices, deviceAllocated) rPool, err := rm.rFactory.GetResourcePool(rc, filteredDevices) if err != nil { glog.Errorf("initServers(): error creating ResourcePool with config %+v: %q", rc, err) return err } - // Create ResourceServer with this ResourcePool s, err := rf.GetResourceServer(rPool) if err != nil { @@ -141,6 +142,19 @@ func (rm *resourceManager) initServers() error { return nil } +func (rm *resourceManager) excludeAllocatedDevices(filteredDevices []types.PciDevice, deviceAllocated map[string]bool) []types.PciDevice { + filteredDevicesTemp := []types.PciDevice{} + for _, dev := range filteredDevices { + if !deviceAllocated[dev.GetPciAddr()] { + deviceAllocated[dev.GetPciAddr()] = true + filteredDevicesTemp = append(filteredDevicesTemp, dev) + } else { + glog.Warningf("Cannot add PCI Address [%s]. Already allocated.", dev.GetPciAddr()) + } + } + return filteredDevicesTemp +} + func (rm *resourceManager) startAllServers() error { for _, rs := range rm.resourceServers { if err := rs.Start(); err != nil { diff --git a/cmd/sriovdp/manager_test.go b/cmd/sriovdp/manager_test.go index bbdc73846..3f29f9e57 100644 --- a/cmd/sriovdp/manager_test.go +++ b/cmd/sriovdp/manager_test.go @@ -255,7 +255,7 @@ var _ = Describe("Resource manager", func() { mockedRf := &mocks.ResourceFactory{} mockedRf.On("GetResourcePool", rc, devs).Return(rp, nil). On("GetResourceServer", rp).Return(mockedServer, nil) - + dev.On("GetPciAddr").Return("0000:01:10.0") dp.On("GetDevices", rc).Return(devs) rm := &resourceManager{ rFactory: mockedRf, diff --git a/pkg/factory/factory_test.go b/pkg/factory/factory_test.go index abc38f91a..991ac240a 100644 --- a/pkg/factory/factory_test.go +++ b/pkg/factory/factory_test.go @@ -160,6 +160,134 @@ var _ = Describe("Factory", func() { }) }) }) + Describe("getting exclusive resource pool for netdevice", func() { + Context("with all types of selectors used and matching devices found", func() { + defer utils.UseFakeLinks()() + var ( + rp types.ResourcePool + rp2 types.ResourcePool + err error + devs []types.PciDevice + ) + BeforeEach(func() { + f := factory.NewResourceFactory("fake", "fake", true) + devs = make([]types.PciDevice, 4) + vendors := []string{"8086", "8086", "8086", "8086"} + codes := []string{"1111", "1111", "1111", "1111"} + drivers := []string{"iavf", "iavf", "vfio-pci", "vfio-pci"} + pciAddr := []string{"0000:03:02.0", "0000:03:02.0", "0000:03:02.0", "0000:03:02.0"} + pfNames := []string{"enp2s0f2", "ens0", "eth0", "net2"} + rootDevices := []string{"0000:86:00.0", "0000:86:00.1", "0000:86:00.2", "0000:86:00.3"} + linkTypes := []string{"ether", "infiniband", "other", "other2"} + ddpProfiles := []string{"GTP", "PPPoE", "GTP", "PPPoE"} + for i := range devs { + d := &mocks.PciNetDevice{} + d.On("GetVendor").Return(vendors[i]). + On("GetDeviceCode").Return(codes[i]). + On("GetDriver").Return(drivers[i]). + On("GetPciAddr").Return(pciAddr[i]). + On("GetPFName").Return(pfNames[i]). + On("GetPfPciAddr").Return(rootDevices[i]). + On("GetAPIDevice").Return(&pluginapi.Device{}). + On("GetLinkType").Return(linkTypes[i]). + On("GetDDPProfiles").Return(ddpProfiles[i]) + devs[i] = d + } + + var selectors json.RawMessage + err = selectors.UnmarshalJSON([]byte(` + { + "vendors": ["8086"], + "devices": ["1111"], + "drivers": ["iavf","vfio-pci"], + "pciAddresses": ["0000:03:02.0"], + "pfNames": ["enp2s0f2"], + "rootDevices": ["0000:86:00.0"], + "linkTypes": ["ether"], + "ddpProfiles": ["GTP"] + } + `), + ) + Expect(err).NotTo(HaveOccurred()) + + var selectors2 json.RawMessage + err = selectors2.UnmarshalJSON([]byte(` + { + "vendors": ["8086"], + "devices": ["1111"], + "drivers": ["iavf","vfio-pci"], + "pciAddresses": ["0000:03:02.0"], + "pfNames": ["enp2s0f2"], + "rootDevices": ["0000:86:00.0"], + "linkTypes": ["ether"], + "ddpProfiles": ["GTP"] + } + `), + ) + Expect(err).NotTo(HaveOccurred()) + + c := &types.ResourceConfig{ + ResourceName: "fake", + Selectors: &selectors, + DeviceType: types.NetDeviceType, + } + deviceAllocated := make(map[string]bool) + dp := f.GetDeviceProvider(c.DeviceType) + c.SelectorObj, err = f.GetDeviceFilter(c) + Expect(err).NotTo(HaveOccurred()) + filteredDevices, err := dp.GetFilteredDevices(devs, c) + Expect(err).NotTo(HaveOccurred()) + + filteredDevicesTemp := []types.PciDevice{} + for _, dev := range filteredDevices { + if !deviceAllocated[dev.GetPciAddr()] { + deviceAllocated[dev.GetPciAddr()] = true + filteredDevicesTemp = append(filteredDevicesTemp, dev) + } + } + filteredDevices = filteredDevicesTemp + + rp, err = f.GetResourcePool(c, filteredDevices) + Expect(err).NotTo(HaveOccurred()) + + // Second config definition + c2 := &types.ResourceConfig{ + ResourceName: "fake", + Selectors: &selectors2, + DeviceType: types.NetDeviceType, + } + + dp2 := f.GetDeviceProvider(c2.DeviceType) + c2.SelectorObj, err = f.GetDeviceFilter(c2) + Expect(err).NotTo(HaveOccurred()) + filteredDevices, err = dp2.GetFilteredDevices(devs, c2) + Expect(err).NotTo(HaveOccurred()) + + filteredDevicesTemp = []types.PciDevice{} + for _, dev := range filteredDevices { + if !deviceAllocated[dev.GetPciAddr()] { + deviceAllocated[dev.GetPciAddr()] = true + filteredDevicesTemp = append(filteredDevicesTemp, dev) + } + } + filteredDevices = filteredDevicesTemp + + rp2, err = f.GetResourcePool(c2, filteredDevices) + Expect(err).NotTo(HaveOccurred()) + + }) + It("should return valid exclusive resource pool", func() { + Expect(rp).NotTo(BeNil()) + Expect(rp.GetDevices()).To(HaveLen(1)) + Expect(rp.GetDevices()).To(HaveKey("0000:03:02.0")) + // Check second resource pool to make sure nothing got added to it. + Expect(rp2).Should(BeNil()) + }) + It("should not fail", func() { + Expect(err).NotTo(HaveOccurred()) + }) + }) + }) Describe("getting resource pool for accelerator", func() { Context("with all types of selectors used and matching devices found", func() { defer utils.UseFakeLinks()()