Skip to content

Commit 7d7b664

Browse files
committed
Fix domain parsing for GPU
1 parent abdf926 commit 7d7b664

File tree

3 files changed

+264
-48
lines changed

3 files changed

+264
-48
lines changed

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtGpuDef.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,27 @@ private void generatePciXml(StringBuilder gpuBuilder) {
7979
gpuBuilder.append(" <driver name='vfio'/>\n");
8080
gpuBuilder.append(" <source>\n");
8181

82-
// Parse the bus address (e.g., 00:02.0) into domain, bus, slot, function
82+
// Parse the bus address into domain, bus, slot, function. Two input formats are accepted:
83+
// - "dddd:bb:ss.f" full PCI address with domain (e.g. 0000:00:02.0)
84+
// - "bb:ss.f" legacy short BDF; domain defaults to 0000
8385
String domain = "0x0000";
8486
String bus = "0x00";
8587
String slot = "0x00";
8688
String function = "0x0";
8789

8890
if (busAddress != null && !busAddress.isEmpty()) {
8991
String[] parts = busAddress.split(":");
90-
if (parts.length > 1) {
92+
String slotFunction = null;
93+
if (parts.length == 3) {
94+
domain = "0x" + parts[0];
95+
bus = "0x" + parts[1];
96+
slotFunction = parts[2];
97+
} else if (parts.length == 2) {
9198
bus = "0x" + parts[0];
92-
String[] slotFunctionParts = parts[1].split("\\.");
99+
slotFunction = parts[1];
100+
}
101+
if (slotFunction != null) {
102+
String[] slotFunctionParts = slotFunction.split("\\.");
93103
if (slotFunctionParts.length > 0) {
94104
slot = "0x" + slotFunctionParts[0];
95105
if (slotFunctionParts.length > 1) {

plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtGpuDefTest.java

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,110 @@ public void testGpuDef_withComplexPciAddress() {
115115
assertTrue(gpuXml.contains("</hostdev>"));
116116
}
117117

118+
@Test
119+
public void testGpuDef_withFullPciAddressDomainZero() {
120+
LibvirtGpuDef gpuDef = new LibvirtGpuDef();
121+
VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo(
122+
GpuDevice.DeviceType.PCI,
123+
"passthrough",
124+
"passthrough",
125+
"0000:00:02.0",
126+
"10de",
127+
"NVIDIA Corporation",
128+
"1b38",
129+
"Tesla T4"
130+
);
131+
gpuDef.defGpu(pciGpuInfo);
132+
133+
String gpuXml = gpuDef.toString();
134+
135+
assertTrue(gpuXml.contains("<address domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>"));
136+
}
137+
138+
@Test
139+
public void testGpuDef_withFullPciAddressNonZeroDomain() {
140+
LibvirtGpuDef gpuDef = new LibvirtGpuDef();
141+
VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo(
142+
GpuDevice.DeviceType.PCI,
143+
"passthrough",
144+
"passthrough",
145+
"0001:65:00.0",
146+
"10de",
147+
"NVIDIA Corporation",
148+
"1b38",
149+
"Tesla T4"
150+
);
151+
gpuDef.defGpu(pciGpuInfo);
152+
153+
String gpuXml = gpuDef.toString();
154+
155+
assertTrue(gpuXml.contains("<address domain='0x0001' bus='0x65' slot='0x00' function='0x0'/>"));
156+
}
157+
158+
@Test
159+
public void testGpuDef_withFullPciAddressWideDomain() {
160+
LibvirtGpuDef gpuDef = new LibvirtGpuDef();
161+
VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo(
162+
GpuDevice.DeviceType.PCI,
163+
"passthrough",
164+
"passthrough",
165+
"10000:af:00.1",
166+
"10de",
167+
"NVIDIA Corporation",
168+
"1b38",
169+
"Tesla T4"
170+
);
171+
gpuDef.defGpu(pciGpuInfo);
172+
173+
String gpuXml = gpuDef.toString();
174+
175+
assertTrue(gpuXml.contains("<address domain='0x10000' bus='0xaf' slot='0x00' function='0x1'/>"));
176+
}
177+
178+
@Test
179+
public void testGpuDef_withFullPciAddressVfNonZeroDomain() {
180+
LibvirtGpuDef gpuDef = new LibvirtGpuDef();
181+
VgpuTypesInfo vfGpuInfo = new VgpuTypesInfo(
182+
GpuDevice.DeviceType.PCI,
183+
"VF-Profile",
184+
"VF-Profile",
185+
"0002:81:00.3",
186+
"10de",
187+
"NVIDIA Corporation",
188+
"1eb8",
189+
"Tesla T4"
190+
);
191+
gpuDef.defGpu(vfGpuInfo);
192+
193+
String gpuXml = gpuDef.toString();
194+
195+
// Non-passthrough NVIDIA VFs should be unmanaged
196+
assertTrue(gpuXml.contains("<hostdev mode='subsystem' type='pci' managed='no' display='off'>"));
197+
assertTrue(gpuXml.contains("<address domain='0x0002' bus='0x81' slot='0x00' function='0x3'/>"));
198+
}
199+
200+
@Test
201+
public void testGpuDef_withLegacyShortBdfDefaultsDomainToZero() {
202+
// Backward compatibility: short BDF with no domain segment must still
203+
// produce a valid libvirt address with domain 0x0000.
204+
LibvirtGpuDef gpuDef = new LibvirtGpuDef();
205+
VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo(
206+
GpuDevice.DeviceType.PCI,
207+
"passthrough",
208+
"passthrough",
209+
"af:00.0",
210+
"10de",
211+
"NVIDIA Corporation",
212+
"1b38",
213+
"Tesla T4"
214+
);
215+
gpuDef.defGpu(pciGpuInfo);
216+
217+
String gpuXml = gpuDef.toString();
218+
219+
assertTrue(gpuXml.contains("<address domain='0x0000' bus='0xaf' slot='0x00' function='0x0'/>"));
220+
}
221+
118222
@Test
119223
public void testGpuDef_withNullDeviceType() {
120224
LibvirtGpuDef gpuDef = new LibvirtGpuDef();

0 commit comments

Comments
 (0)