Skip to content

Commit c36e0db

Browse files
MrStupnikovElod Illes
authored andcommitted
Translate VF network capabilities to port binding
Libvirt's node device driver accumulates and reports information about host devices. Network capabilities reported by node device driver for NIC contain information about HW offloads supported by this NIC. One of possible features reported by node device driver is switchdev: a NIC capability to implement VFs similar to actual HW switch ports (also referred to as SR-IOV OVS hardware offload). From Neutron perspective, vnic-type should be set to "direct" and "switchdev" capability should be added to port binding profile to enable HW offload (there are also configuration steps on compute hosts to tune NIC config). This patch was written to automatically translate "switchdev" from VF network capabilities reported by node device driver to Neutron port binding profile and allow user to skip manual step that requires admin privileges. Other capabilities are also translated: they are not used right now, but provide visibility and can be utilized later. Closes-bug: #2020813 Closes-bug: #2008238 Change-Id: I3b17f386325b8f42c0c374f766fb21c520161a59 (cherry picked from commit cef3b5e) (cherry picked from commit 7e4f45d) (cherry picked from commit 4fcc8c3)
1 parent 343cd7b commit c36e0db

File tree

7 files changed

+47
-3
lines changed

7 files changed

+47
-3
lines changed

nova/network/neutron.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,13 @@ def _get_vf_pci_device_profile(self, pci_dev):
15881588
'pf_mac_address': pf_mac,
15891589
'vf_num': vf_num,
15901590
})
1591+
1592+
# Update port binding capabilities using PCI device's network
1593+
# capabilities if they exist.
1594+
pci_net_caps = pci_dev.network_caps
1595+
if pci_net_caps:
1596+
vf_profile.update({'capabilities': pci_net_caps})
1597+
15911598
return vf_profile
15921599

15931600
def _get_pci_device_profile(self, pci_dev):

nova/objects/pci_device.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,13 @@ def mac_address(self):
588588
"""
589589
return self.extra_info.get('mac_address')
590590

591+
@property
592+
def network_caps(self):
593+
"""PCI device network capabilities or empty list if not available"""
594+
caps_json = self.extra_info.get('capabilities', '{}')
595+
caps = jsonutils.loads(caps_json)
596+
return caps.get('network', [])
597+
591598

592599
@base.NovaObjectRegistry.register
593600
class PciDeviceList(base.ObjectListBase, base.NovaObject):

nova/tests/fixtures/libvirt_data.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,7 @@ def fake_kvm_guest():
21822182
<feature name='rxvlan'/>
21832183
<feature name='txvlan'/>
21842184
<feature name='rxhash'/>
2185+
<feature name='switchdev'/>
21852186
<capability type='80203'/>
21862187
</capability>
21872188
</device>""", # noqa:E501

nova/tests/unit/network/test_neutron.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8144,17 +8144,20 @@ def test__get_vf_pci_device_profile(self):
81448144
'pf_mac_address': '52:54:00:1e:59:c6',
81458145
'vf_num': 1,
81468146
},
8147+
'network_caps': ['gso', 'sg', 'tso', 'tx'],
81478148
'dev_type': obj_fields.PciDeviceType.SRIOV_VF,
81488149
}
81498150
PciDevice = collections.namedtuple('PciDevice',
81508151
['vendor_id', 'product_id', 'address',
81518152
'card_serial_number', 'sriov_cap',
8152-
'dev_type', 'parent_addr'])
8153+
'dev_type', 'parent_addr',
8154+
'network_caps'])
81538155
mydev = PciDevice(**pci_dev)
81548156
self.assertEqual(self.api._get_vf_pci_device_profile(mydev),
81558157
{'pf_mac_address': '52:54:00:1e:59:c6',
81568158
'vf_num': 1,
8157-
'card_serial_number': 'MT2113X00000'})
8159+
'card_serial_number': 'MT2113X00000',
8160+
'capabilities': ['gso', 'sg', 'tso', 'tx']})
81588161

81598162
@mock.patch.object(
81608163
neutronapi.API, '_get_vf_pci_device_profile',

nova/tests/unit/objects/test_pci_device.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,16 @@ def test_pci_device_extra_info_card_serial_number(self):
171171
self.pci_device = pci_device.PciDevice.create(None, self.dev_dict)
172172
self.assertEqual(self.pci_device.card_serial_number, '42')
173173

174+
def test_pci_device_extra_info_network_capabilities(self):
175+
self.dev_dict = copy.copy(dev_dict)
176+
self.pci_device = pci_device.PciDevice.create(None, self.dev_dict)
177+
self.assertEqual(self.pci_device.network_caps, [])
178+
179+
self.dev_dict = copy.copy(dev_dict)
180+
self.dev_dict['capabilities'] = {'network': ['sg', 'tso', 'tx']}
181+
self.pci_device = pci_device.PciDevice.create(None, self.dev_dict)
182+
self.assertEqual(self.pci_device.network_caps, ['sg', 'tso', 'tx'])
183+
174184
def test_update_device(self):
175185
self.pci_device = pci_device.PciDevice.create(None, dev_dict)
176186
self.pci_device.obj_reset_changes()

nova/tests/unit/virt/libvirt/test_host.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ def test_get_pcidev_info(self):
13371337
"parent_ifname": "ens1",
13381338
"capabilities": {
13391339
"network": ["rx", "tx", "sg", "tso", "gso", "gro", "rxvlan",
1340-
"txvlan", "rxhash"],
1340+
"txvlan", "rxhash", "switchdev"],
13411341
"sriov": {"pf_mac_address": "52:54:00:1e:59:c6",
13421342
"vf_num": 1},
13431343
# Should be obtained from the parent PF in this case.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
fixes:
3+
- |
4+
Previously ``switchdev`` capabilities should be configured manually by a
5+
user with admin privileges using port's binding profile. This blocked
6+
regular users from managing ports with Open vSwitch hardware offloading
7+
as providing write access to a port's binding profile to non-admin users
8+
introduces security risks. For example, a binding profile may contain a
9+
``pci_slot`` definition, which denotes the host PCI address of the
10+
device attached to the VM. A malicious user can use this parameter to
11+
passthrough any host device to a guest, so it is impossible to provide
12+
write access to a binding profile to regular users in many scenarios.
13+
14+
This patch fixes this situation by translating VF capabilities reported
15+
by Libvirt to Neutron port binding profiles. Other VF capabilities are
16+
translated as well for possible future use.

0 commit comments

Comments
 (0)