-
Notifications
You must be signed in to change notification settings - Fork 179
LIBVIRTAT-20967: Add multiple VFIO interfaces in vIOMMU test #6590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
bdce0d5
213aba1
7f94c7e
8c2b566
19b1adb
31b0139
869b90c
c771b29
a5be1ec
23db7a5
75e1f85
ecf63c8
9e1b307
5f587be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -108,17 +108,35 @@ def __init__(self, vm, test, params, session=None): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| libvirt_version.is_libvirt_feature_supported(self.params) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new_xml = vm_xml.VMXML.new_from_inactive_dumpxml(self.vm.name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.orig_config_xml = new_xml.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.test.log.debug("Original VM configuration backed up for restore") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def parse_iface_dict(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parse iface_dict from params | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parse iface_dict from params, supporting both single dict and list of dicts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :return: The updated iface_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :return: The updated iface_dict or list of iface_dicts based on type of input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # generate mac address, if it is needed in iface_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mac_addr = utils_net.generate_mac_address_simple() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iface_dict = eval(self.params.get("iface_dict", "{}")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hholoubk marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.controller_dicts and iface_dict: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if isinstance(iface_dict, list): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for single_iface_dict in iface_dict: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._update_iface_dict_with_controller_info(single_iface_dict) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result.append(single_iface_dict) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._update_iface_dict_with_controller_info(iface_dict) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return iface_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+123
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation and error handling. The code assumes Consider adding validation: iface_dict = literal_eval(self.params.get("iface_dict", "{}"))
+
+ if not isinstance(iface_dict, (dict, list)):
+ raise ValueError(f"iface_dict must be dict or list, got {type(iface_dict).__name__}")
if isinstance(iface_dict, list):
+ if not all(isinstance(item, dict) for item in iface_dict):
+ raise ValueError("All items in iface_dict list must be dicts")
result = []
for single_iface_dict in iface_dict:
self._update_iface_dict_with_controller_info(single_iface_dict)
result.append(single_iface_dict)
return result
else:
self._update_iface_dict_with_controller_info(iface_dict)
return iface_dict📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _update_iface_dict_with_controller_info(self, iface_dict): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Update interface dictionary with controller addressing information | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :param iface_dict: Interface dictionary to update with controller info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.controller_dicts and iface_dict and iface_dict.get('type_name') != 'hostdev': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix conditional check for empty dict. The condition Apply this diff to be explicit: - if self.controller_dicts and iface_dict and iface_dict.get('type_name') != 'hostdev':
+ if self.controller_dicts and iface_dict is not None and iface_dict.get('type_name') != 'hostdev':Or, if empty dicts should skip processing: - if self.controller_dicts and iface_dict and iface_dict.get('type_name') != 'hostdev':
+ if self.controller_dicts and iface_dict and len(iface_dict) > 0 and iface_dict.get('type_name') != 'hostdev':📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iface_bus = "%0#4x" % int(self.controller_dicts[-1].get("index")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iface_attrs = {"bus": iface_bus} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.controller_dicts[-1].get("model") == "pcie-to-pci-bridge": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -129,7 +147,6 @@ def parse_iface_dict(self): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iface_dict.update({"address": {"attrs": iface_attrs}}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.test.log.debug("iface_dict: %s.", iface_dict) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return iface_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def prepare_controller(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -143,17 +160,30 @@ def prepare_controller(self): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contr_dict = self.controller_dicts[i] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pre_controller = contr_dict.get("pre_controller") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if pre_controller: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pre_contrs = list( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filter(None, [c.get("index") for c in self.controller_dicts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if c["type"] == contr_dict["type"] and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c["model"] == pre_controller])) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if pre_contrs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pre_idx = pre_contrs[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.test.log.debug(f"Processing controller {i}: {contr_dict}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.test.log.debug(f"Looking for pre_controller: {pre_controller}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Get parent controller index and busNr | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parent_contrs = [(c.get("index"), c.get("target", {}).get("busNr")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for c in self.controller_dicts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if c["type"] == contr_dict["type"] and c["model"] == pre_controller] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parent_contrs = [(c.get("index"), c.get("target", {}).get("busNr")) | |
| for c in self.controller_dicts | |
| if c["type"] == contr_dict["type"] and c["model"] == pre_controller] | |
| parent_contrs = [(c.get("index"), c.get("target", {}).get("busNr")) | |
| for c in self.controller_dicts | |
| if c.get("type") == contr_dict.get("type") and c.get("model") == pre_controller] |
🤖 Prompt for AI Agents
In provider/viommu/viommu_base.py around lines 166 to 168, the list
comprehension uses c["type"] and c["model"] which can raise KeyError; change
those to c.get("type") and c.get("model") so missing keys return None and the
comparison is safe, preserving the existing c.get("index") and c.get("target",
{}).get("busNr") accesses; ensure the logic still filters controllers by
comparing c.get("type") == contr_dict.get("type") and c.get("model") ==
pre_controller (or contr_dict.get("model") if that was intended).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix truthy check that incorrectly rejects busNr=0.
Line 199 uses a truthy check on busNr, which evaluates to False when busNr is 0. Since 0 is a valid bus number, this check incorrectly skips the target busNr logic and falls through to the else branch.
Apply this diff to check explicitly for None:
- if contr_dict.get("target", {}).get("busNr"):
+ if contr_dict.get("target", {}).get("busNr") is not None:
target_bus = int(contr_dict["target"]["busNr"])📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Only assign index if it wasn't already assigned | |
| if "index" not in contr_dict: | |
| # Check if target busNr is specified and use it as index | |
| if contr_dict.get("target", {}).get("busNr"): | |
| target_bus = int(contr_dict["target"]["busNr"]) | |
| contr_dict["index"] = target_bus | |
| self.test.log.debug(f"Using target busNr {target_bus} as index for controller {i}: {contr_dict['model']}") | |
| else: | |
| contr_dict["index"] = libvirt_pcicontr.get_max_contr_indexes( | |
| vm_xml.VMXML.new_from_dumpxml(self.vm.name), | |
| contr_dict["type"], contr_dict["model"])[-1] | |
| self.test.log.debug(f"Assigned index {contr_dict['index']} to controller {i}: {contr_dict['model']}") | |
| else: | |
| self.test.log.debug(f"Index already assigned {contr_dict['index']} for controller {i}: {contr_dict['model']}") | |
| # Only assign index if it wasn't already assigned | |
| if "index" not in contr_dict: | |
| # Check if target busNr is specified and use it as index | |
| if contr_dict.get("target", {}).get("busNr") is not None: | |
| target_bus = int(contr_dict["target"]["busNr"]) | |
| contr_dict["index"] = target_bus | |
| self.test.log.debug(f"Using target busNr {target_bus} as index for controller {i}: {contr_dict['model']}") | |
| else: | |
| contr_dict["index"] = libvirt_pcicontr.get_max_contr_indexes( | |
| vm_xml.VMXML.new_from_dumpxml(self.vm.name), | |
| contr_dict["type"], contr_dict["model"])[-1] | |
| self.test.log.debug(f"Assigned index {contr_dict['index']} to controller {i}: {contr_dict['model']}") | |
| else: | |
| self.test.log.debug(f"Index already assigned {contr_dict['index']} for controller {i}: {contr_dict['model']}") |
🤖 Prompt for AI Agents
In provider/viommu/viommu_base.py around lines 196 to 209, the truthy check on
contr_dict.get("target", {}).get("busNr") incorrectly treats busNr==0 as absent;
change the logic to explicitly test for None (e.g., bus_nr =
contr_dict.get("target", {}).get("busNr"); if bus_nr is not None: target_bus =
int(bus_nr); contr_dict["index"] = target_bus; ...) so zero is accepted while
still handling missing values, and keep the debug log and remaining branches
unchanged.
Uh oh!
There was an error while loading. Please reload this page.