Skip to content

Commit bae0300

Browse files
committed
feat: rdma discovery
Adds rdmaCapable attribute Signed-off-by: Fred Rolland <frolland@nvidia.com>
1 parent 423e878 commit bae0300

File tree

10 files changed

+465
-53
lines changed

10 files changed

+465
-53
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/k8snetworkplumbingwg/dra-driver-sriov
33
go 1.25.3
44

55
require (
6+
github.com/Mellanox/rdmamap v1.1.0
67
github.com/containerd/nri v0.11.0
78
github.com/containernetworking/cni v1.3.0
89
github.com/jaypipes/ghw v0.21.2
@@ -77,6 +78,8 @@ require (
7778
github.com/sirupsen/logrus v1.9.3 // indirect
7879
github.com/spf13/cobra v1.9.1 // indirect
7980
github.com/tetratelabs/wazero v1.10.1 // indirect
81+
github.com/vishvananda/netlink v1.3.1 // indirect
82+
github.com/vishvananda/netns v0.0.5 // indirect
8083
github.com/x448/float16 v0.8.4 // indirect
8184
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
8285
github.com/yusufpapurcu/wmi v1.2.4 // indirect

go.sum

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
22
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
3+
github.com/Mellanox/rdmamap v1.1.0 h1:A/W1wAXw+6vm58f3VklrIylgV+eDJlPVIMaIKuxgUT4=
4+
github.com/Mellanox/rdmamap v1.1.0/go.mod h1:fN+/V9lf10ABnDCwTaXRjeeWijLt2iVLETnK+sx/LY8=
35
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
46
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
57
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -178,6 +180,10 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
178180
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
179181
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
180182
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
183+
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
184+
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
185+
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
186+
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
181187
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
182188
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
183189
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@@ -242,9 +248,12 @@ golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
242248
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
243249
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
244250
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
251+
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
245252
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
246253
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
247254
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
255+
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
256+
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
248257
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
249258
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
250259
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=

pkg/consts/consts.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
AttributePFDeviceID = DriverName + "/pfDeviceID"
3838
AttributeVFID = DriverName + "/vfID"
3939
AttributeResourceName = DriverName + "/resourceName"
40+
AttributeRDMACapable = DriverName + "/rdmaCapable"
4041
// Use upstream Kubernetes standard attribute prefix for numaNode
4142
AttributeNumaNode = deviceattribute.StandardDeviceAttributePrefix + "numaNode"
4243
// Use upstream Kubernetes standard attribute prefix for pciAddress
@@ -48,6 +49,9 @@ const (
4849
// Network device constants
4950
NetClass = 0x02 // Network controller class
5051
SysBusPci = "/sys/bus/pci/devices"
52+
53+
// RDMA device constants
54+
SysClassInfiniband = "/sys/class/infiniband"
5155
)
5256

5357
// Kubernetes standard attributes

pkg/devicestate/discovery.go

Lines changed: 69 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ func DiscoverSriovDevices() (types.AllocatableDevices, error) {
7676
eswitchMode := host.GetHelpers().GetNicSriovMode(device.Address)
7777

7878
// Get NUMA node information
79+
// -1 indicates NUMA is not supported/enabled (standard Linux convention)
7980
numaNode, err := host.GetHelpers().GetNumaNode(device.Address)
8081
if err != nil {
81-
logger.Error(err, "Failed to get NUMA node, using default", "address", device.Address)
82-
numaNode = "0" // Default to node 0 if we can't determine it
82+
logger.Error(err, "Failed to get NUMA node, using -1 (not supported)", "address", device.Address)
83+
numaNode = "-1" // Default to -1 if we can't determine it
8384
}
8485

8586
// Get PCIe Root Complex information using upstream Kubernetes implementation
@@ -132,65 +133,84 @@ func DiscoverSriovDevices() (types.AllocatableDevices, error) {
132133

133134
logger.Info("Found VFs for PF", "pf", pfInfo.NetName, "vfCount", len(vfList))
134135

136+
// Parse NUMA node value. Keep the actual value including -1 which indicates
137+
// NUMA is not supported/enabled (standard Linux convention).
138+
// This allows users to filter devices based on NUMA availability.
139+
numaNodeInt, err := strconv.ParseInt(pfInfo.NumaNode, 10, 64)
140+
if err != nil {
141+
logger.Error(err, "Failed to parse NUMA node, defaulting to -1",
142+
"pf", pfInfo.NetName, "numaNodeStr", pfInfo.NumaNode)
143+
numaNodeInt = -1
144+
}
145+
numaNodeIntPtr := ptr.To(numaNodeInt)
146+
135147
for _, vfInfo := range vfList {
136148
deviceName := strings.ReplaceAll(vfInfo.PciAddress, ":", "-")
137149
deviceName = strings.ReplaceAll(deviceName, ".", "-")
138150

151+
// Check RDMA capability for this VF
152+
rdmaCapable, err := host.GetHelpers().VerifyRDMACapability(vfInfo.PciAddress)
153+
if err != nil {
154+
logger.Error(err, "Failed to verify RDMA capability, assuming not RDMA capable",
155+
"vfAddress", vfInfo.PciAddress)
156+
rdmaCapable = false
157+
}
158+
139159
logger.V(2).Info("Adding VF device to resource list",
140160
"deviceName", deviceName,
141161
"vfAddress", vfInfo.PciAddress,
142162
"vfID", vfInfo.VFID,
143163
"vfDeviceID", vfInfo.DeviceID,
144164
"pfDeviceID", pfInfo.DeviceID,
145-
"pf", pfInfo.NetName)
165+
"pf", pfInfo.NetName,
166+
"rdmaCapable", rdmaCapable)
146167

147-
resourceList[deviceName] = resourceapi.Device{
148-
Name: deviceName,
149-
Attributes: map[resourceapi.QualifiedName]resourceapi.DeviceAttribute{
150-
consts.AttributeVendorID: {
151-
StringValue: ptr.To(pfInfo.VendorID),
152-
},
153-
consts.AttributeDeviceID: {
154-
StringValue: ptr.To(vfInfo.DeviceID),
155-
},
156-
consts.AttributePFDeviceID: {
157-
StringValue: ptr.To(pfInfo.DeviceID),
158-
},
159-
consts.AttributePciAddress: {
160-
StringValue: ptr.To(vfInfo.PciAddress),
161-
},
162-
consts.AttributePFName: {
163-
StringValue: ptr.To(pfInfo.NetName),
164-
},
165-
consts.AttributeEswitchMode: {
166-
StringValue: ptr.To(pfInfo.EswitchMode),
167-
},
168-
consts.AttributeVFID: {
169-
IntValue: ptr.To(int64(vfInfo.VFID)),
170-
},
171-
consts.AttributeNumaNode: {
172-
IntValue: func() *int64 {
173-
numaNodeInt, err := strconv.ParseInt(pfInfo.NumaNode, 10, 64)
174-
if err != nil {
175-
// Default to -1 if parsing fails
176-
return ptr.To(int64(-1))
177-
}
178-
return ptr.To(numaNodeInt)
179-
}(),
180-
},
181-
// PCIe Root Complex (upstream Kubernetes standard) - for topology-aware scheduling
182-
consts.AttributePCIeRoot: {
183-
StringValue: ptr.To(pfInfo.PCIeRoot),
184-
},
185-
// Immediate parent PCI address - for granular filtering
186-
consts.AttributeParentPciAddress: {
187-
StringValue: ptr.To(pfInfo.ParentPciAddress),
188-
},
189-
// Standard Kubernetes PCI address attribute
190-
consts.AttributeStandardPciAddress: {
191-
StringValue: ptr.To(vfInfo.PciAddress),
192-
},
168+
// Build device attributes
169+
attributes := map[resourceapi.QualifiedName]resourceapi.DeviceAttribute{
170+
consts.AttributeVendorID: {
171+
StringValue: ptr.To(pfInfo.VendorID),
172+
},
173+
consts.AttributeDeviceID: {
174+
StringValue: ptr.To(vfInfo.DeviceID),
175+
},
176+
consts.AttributePFDeviceID: {
177+
StringValue: ptr.To(pfInfo.DeviceID),
178+
},
179+
consts.AttributePciAddress: {
180+
StringValue: ptr.To(vfInfo.PciAddress),
181+
},
182+
consts.AttributePFName: {
183+
StringValue: ptr.To(pfInfo.NetName),
193184
},
185+
consts.AttributeEswitchMode: {
186+
StringValue: ptr.To(pfInfo.EswitchMode),
187+
},
188+
consts.AttributeVFID: {
189+
IntValue: ptr.To(int64(vfInfo.VFID)),
190+
},
191+
consts.AttributeNumaNode: {
192+
IntValue: numaNodeIntPtr,
193+
},
194+
// PCIe Root Complex (upstream Kubernetes standard) - for topology-aware scheduling
195+
consts.AttributePCIeRoot: {
196+
StringValue: ptr.To(pfInfo.PCIeRoot),
197+
},
198+
// Immediate parent PCI address - for granular filtering
199+
consts.AttributeParentPciAddress: {
200+
StringValue: ptr.To(pfInfo.ParentPciAddress),
201+
},
202+
// Standard Kubernetes PCI address attribute
203+
consts.AttributeStandardPciAddress: {
204+
StringValue: ptr.To(vfInfo.PciAddress),
205+
},
206+
consts.AttributeRDMACapable: {
207+
BoolValue: ptr.To(rdmaCapable),
208+
},
209+
}
210+
211+
resourceList[deviceName] = resourceapi.Device{
212+
Name: deviceName,
213+
Attributes: attributes,
194214
}
195215
}
196216
}

pkg/devicestate/discovery_test.go

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ var _ = Describe("DiscoverSriovDevices", func() {
7878
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("pci0000:00", nil)
7979
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("0000:00:01.0", nil)
8080
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
81+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, nil)
82+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.2").Return(false, nil)
8183

8284
devices, err := DiscoverSriovDevices()
8385
Expect(err).NotTo(HaveOccurred())
@@ -149,7 +151,9 @@ var _ = Describe("DiscoverSriovDevices", func() {
149151
mockHost.EXPECT().GetParentPciAddress("0000:02:00.0").Return("0000:00:02.0", nil)
150152

151153
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList1, nil)
154+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, nil)
152155
mockHost.EXPECT().GetVFList("0000:02:00.0").Return(vfList2, nil)
156+
mockHost.EXPECT().VerifyRDMACapability("0000:02:00.1").Return(false, nil)
153157

154158
devices, err := DiscoverSriovDevices()
155159
Expect(err).NotTo(HaveOccurred())
@@ -198,14 +202,15 @@ var _ = Describe("DiscoverSriovDevices", func() {
198202
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("", nil)
199203
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("", nil)
200204
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
205+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, nil)
201206

202207
devices, err := DiscoverSriovDevices()
203208
Expect(err).NotTo(HaveOccurred())
204209
Expect(devices).To(HaveLen(1))
205210

206-
// NUMA should default to 0
211+
// NUMA should default to -1 (not supported)
207212
dev := devices["0000-01-00-1"]
208-
Expect(dev.Attributes[consts.AttributeNumaNode].IntValue).To(Equal(ptr.To(int64(0))))
213+
Expect(dev.Attributes[consts.AttributeNumaNode].IntValue).To(Equal(ptr.To(int64(-1))))
209214
// Standard PCI address should still be set
210215
Expect(dev.Attributes[consts.AttributeStandardPciAddress].StringValue).To(Equal(ptr.To("0000:01:00.1")))
211216
})
@@ -234,6 +239,7 @@ var _ = Describe("DiscoverSriovDevices", func() {
234239
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("", nil)
235240
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("", fmt.Errorf("parent not found"))
236241
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
242+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, nil)
237243

238244
devices, err := DiscoverSriovDevices()
239245
Expect(err).NotTo(HaveOccurred())
@@ -245,6 +251,110 @@ var _ = Describe("DiscoverSriovDevices", func() {
245251
// Standard PCI address should still be set
246252
Expect(dev.Attributes[consts.AttributeStandardPciAddress].StringValue).To(Equal(ptr.To("0000:01:00.1")))
247253
})
254+
255+
It("should discover RDMA-capable VFs with RDMA attributes", func() {
256+
pciInfo := &pci.Info{
257+
Devices: []*pci.Device{
258+
{
259+
Address: "0000:01:00.0",
260+
Class: &pcidb.Class{ID: "02"},
261+
Vendor: &pcidb.Vendor{ID: "15b3"}, // Mellanox
262+
Product: &pcidb.Product{ID: "1017"}, // ConnectX-5
263+
},
264+
},
265+
}
266+
267+
vfList := []host.VFInfo{
268+
{
269+
PciAddress: "0000:01:00.1",
270+
VFID: 0,
271+
DeviceID: "1018",
272+
},
273+
{
274+
PciAddress: "0000:01:00.2",
275+
VFID: 1,
276+
DeviceID: "1018",
277+
},
278+
}
279+
280+
mockHost.EXPECT().PCI().Return(pciInfo, nil)
281+
mockHost.EXPECT().IsSriovVF("0000:01:00.0").Return(false)
282+
mockHost.EXPECT().TryGetInterfaceName("0000:01:00.0").Return("ib0")
283+
mockHost.EXPECT().GetNicSriovMode("0000:01:00.0").Return("switchdev")
284+
mockHost.EXPECT().GetNumaNode("0000:01:00.0").Return("1", nil)
285+
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("pci0000:00", nil)
286+
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("0000:00:01.0", nil)
287+
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
288+
289+
// First VF is RDMA-capable
290+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(true, nil)
291+
292+
// Second VF is not RDMA-capable
293+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.2").Return(false, nil)
294+
295+
devices, err := DiscoverSriovDevices()
296+
Expect(err).NotTo(HaveOccurred())
297+
Expect(devices).To(HaveLen(2))
298+
299+
// Check first VF (RDMA-capable)
300+
dev1 := devices["0000-01-00-1"]
301+
Expect(dev1.Name).To(Equal("0000-01-00-1"))
302+
Expect(dev1.Attributes[consts.AttributeVendorID].StringValue).To(Equal(ptr.To("15b3")))
303+
Expect(dev1.Attributes[consts.AttributeDeviceID].StringValue).To(Equal(ptr.To("1018")))
304+
Expect(dev1.Attributes[consts.AttributePFDeviceID].StringValue).To(Equal(ptr.To("1017")))
305+
Expect(dev1.Attributes[consts.AttributePciAddress].StringValue).To(Equal(ptr.To("0000:01:00.1")))
306+
Expect(dev1.Attributes[consts.AttributePFName].StringValue).To(Equal(ptr.To("ib0")))
307+
Expect(dev1.Attributes[consts.AttributeEswitchMode].StringValue).To(Equal(ptr.To("switchdev")))
308+
Expect(dev1.Attributes[consts.AttributeVFID].IntValue).To(Equal(ptr.To(int64(0))))
309+
Expect(dev1.Attributes[consts.AttributeNumaNode].IntValue).To(Equal(ptr.To(int64(1))))
310+
Expect(dev1.Attributes[consts.AttributePCIeRoot].StringValue).To(Equal(ptr.To("pci0000:00")))
311+
Expect(dev1.Attributes[consts.AttributeParentPciAddress].StringValue).To(Equal(ptr.To("0000:00:01.0")))
312+
Expect(dev1.Attributes[consts.AttributeStandardPciAddress].StringValue).To(Equal(ptr.To("0000:01:00.1")))
313+
// RDMA-specific attributes
314+
Expect(dev1.Attributes[consts.AttributeRDMACapable].BoolValue).To(Equal(ptr.To(true)))
315+
316+
// Check second VF (not RDMA-capable)
317+
dev2 := devices["0000-01-00-2"]
318+
Expect(dev2.Name).To(Equal("0000-01-00-2"))
319+
Expect(dev2.Attributes[consts.AttributeVFID].IntValue).To(Equal(ptr.To(int64(1))))
320+
Expect(dev2.Attributes[consts.AttributeRDMACapable].BoolValue).To(Equal(ptr.To(false)))
321+
})
322+
323+
It("should handle RDMA capability check errors gracefully", func() {
324+
pciInfo := &pci.Info{
325+
Devices: []*pci.Device{
326+
{
327+
Address: "0000:01:00.0",
328+
Class: &pcidb.Class{ID: "02"},
329+
Vendor: &pcidb.Vendor{ID: "15b3"},
330+
Product: &pcidb.Product{ID: "1017"},
331+
},
332+
},
333+
}
334+
335+
vfList := []host.VFInfo{
336+
{PciAddress: "0000:01:00.1", VFID: 0, DeviceID: "1018"},
337+
}
338+
339+
mockHost.EXPECT().PCI().Return(pciInfo, nil)
340+
mockHost.EXPECT().IsSriovVF("0000:01:00.0").Return(false)
341+
mockHost.EXPECT().TryGetInterfaceName("0000:01:00.0").Return("ib0")
342+
mockHost.EXPECT().GetNicSriovMode("0000:01:00.0").Return("switchdev")
343+
mockHost.EXPECT().GetNumaNode("0000:01:00.0").Return("0", nil)
344+
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("pci0000:00", nil)
345+
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("0000:00:01.0", nil)
346+
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
347+
// RDMA capability check fails
348+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, fmt.Errorf("failed to verify RDMA"))
349+
350+
devices, err := DiscoverSriovDevices()
351+
Expect(err).NotTo(HaveOccurred())
352+
Expect(devices).To(HaveLen(1))
353+
354+
// Should default to not RDMA capable
355+
dev := devices["0000-01-00-1"]
356+
Expect(dev.Attributes[consts.AttributeRDMACapable].BoolValue).To(Equal(ptr.To(false)))
357+
})
248358
})
249359

250360
Context("Filtering Cases", func() {
@@ -307,6 +417,7 @@ var _ = Describe("DiscoverSriovDevices", func() {
307417
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("", nil)
308418
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("", nil)
309419
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
420+
mockHost.EXPECT().VerifyRDMACapability("0000:01:00.1").Return(false, nil)
310421

311422
// Second device (VF) - should be skipped
312423
mockHost.EXPECT().IsSriovVF("0000:01:00.1").Return(true)
@@ -436,6 +547,7 @@ var _ = Describe("DiscoverSriovDevices", func() {
436547
mockHost.EXPECT().GetPCIeRoot("0000:01:00.0").Return("", nil)
437548
mockHost.EXPECT().GetParentPciAddress("0000:01:00.0").Return("", nil)
438549
mockHost.EXPECT().GetVFList("0000:01:00.0").Return(vfList, nil)
550+
mockHost.EXPECT().VerifyRDMACapability("0000:af:10.7").Return(false, nil)
439551

440552
devices, err := DiscoverSriovDevices()
441553
Expect(err).NotTo(HaveOccurred())

0 commit comments

Comments
 (0)